Opóźnienie Cufon w IE

Przez wiele lat nie było prostej możliwości dołączania dowolnych czcionek do stron www tak aby wyglądały one identycznie w wiodących przeglądarkach. Zamiast tego trzeba było używać obrazków.

Później nastał czas biblioteki Cufon gdzie wszystko było pięknie renderowane. Wszystko, ale nie wszędzie. W IE widoczna była brzydka przerwa (ok. pół sekundy) w momencie ładowania strony, udało się jednak znaleźć na to rozwiązanie.

Aby uniknąć tego brzydkiego efektu, należy:
1. zaraz po ukryć podmieniane elementy

 
<style type="text/css">
.menu {  visibility: hidden; }
</style>
 

2. bezpośrednio przed uruchomić cufon

<script type="text/javascript">
Cufon.replace(".menu");
Cufon.now();
</script>

3. pokazać podmienione elementy

 
<style type="text/css">
.menu { visibility: visible; }
</style>
 

 

MongoDB vs MySQL (MyISAM i InnoDB) – porównanie wydajnoÅ›ci

W ramach nauki nowych narzędzi zabrałem się za testowanie wydajności bazy mongoDB i porównanie wyników z bazą MySQL, zarówno w tabelach MyISAM jak i innoDB.

Jako platforma testowa posłużył mi jedynie lokalny komputer 4 GB RAM z i3 (2.4 Ghz). Źródło danych stanowiła tabela z 217 tys. rekordów.

MySQL (MyISAM) - 5.1.49
MySQL (InnoDB) - 5.1.49
MongoDB - 2.0.2
PHP - 5.3.6

Wszystkie czasy podane są w sekundach, zaś każde z zapytań wykonywane jest w pętli 10 razy i jako wynik prezentowana jest średnia z tych 10 wykonań.

MySQL (MyISAM)MySQL (innoDB)mongoDB
WHERE field = ?3.631 21.9110.016
WHERE field zLIKE 'x%'3.75519.5620.040

Wyniki mówią same za siebie - mongoDB idealnie nadaje się szczególnie do dużych baz danych, gdzie przewaga nad MySQL jest najbardziej widoczna.

Jak parsować duże pliki XML w PHP?

Jakiś czas temu stanąłem przed problemem parsowania dużych plików XML w PHP. O ile z małymi plikami nie ma problemu i całość parsowana jest szybko, to próba obsługi większych plików często powoduje zatrzymywanie wykonywania skryptów. Tak duże pliki są jednak często wykorzystywane przy zdalnych aktualizacjach ofert (np. publikowanych przez hurtownie).

Dzieje się tak, gdyż PHP ma z góry założone ograniczenie na możliwą do wykorzystania pamięć, a parsowanie plików standardową metodą (np. DOMDocument) potrafi ją skutecznie wykorzystać.

Rozwiązaniem jest skorzystanie z klasy XMLReader, domyślnie dostępnej w standardowej konfiguracji PHP od wersji 5.1.0 .

Zrobiłem krótkie porównanie szybkości działań dla DOMDocument i XMLReader korzystając z 4 różnych komputerów

Rozmiar pliku XML: 208 MB
Liczba wpisów: 148723

DOMDocumentXMLReader
Lokalny komnputer269 sek41 sek.
Serwer dedykowany / Hetzner264 sek.15 sek.
Serwer współdzielony / vipserv.orgerror 500 / timeout15 sek.
Serwer współdzielony / IQ.pl277 sek.33 sek.

Jak widać różnica jest kolosalna (ok. 10-20 razy szybciej) i w przypadku dużych plików warto postawić na XMLReader.

Fragment kodu odpowiedzialny za parsowanie przez DOMDocument:

$doc = new DOMDocument();
$doc->load($localurl);
$items= $doc->getElementsByTagName("item");
$countItems = $items->length;
 
foreach($items as $item)
{
	$id = $item->getElementsByTagName("id")->item(0)->nodeValue;
	$url = $item->getElementsByTagName("url")->item(0)->nodeValue;
	$title = $item->getElementsByTagName("title")->item(0)->nodeValue;
	$author = $item->getElementsByTagName("author")->item(0)->nodeValue;
	$isbn = $item->getElementsByTagName("isbn")->item(0)->nodeValue;
	$image = $item->getElementsByTagName("image")->item(0)->nodeValue;
	$ean = $item->getElementsByTagName("ean")->item(0)->nodeValue;
	$published = $item->getElementsByTagName("published")->item(0)->nodeValue;
	$publisher = $item->getElementsByTagName("publisher")->item(0)->nodeValue;
	$pages = $item->getElementsByTagName("pages")->item(0)->nodeValue;
	$price = $item->getElementsByTagName("price")->item(0)->nodeValue;
	$description = $item->getElementsByTagName("description")->item(0)->nodeValue;
	$status = $item->getElementsByTagName("status")->item(0)->nodeValue;
	$count++;
  }

 

Fragment kodu odpowiedzialny za parsowanie przez XMLReader:

$reader = new XMLReader();
$reader->open($localurl);
 
while($reader->read())
{
	if($reader->nodeType == XMLReader::ELEMENT) $nodeName = $reader->name;
	if($reader->nodeType == XMLReader::TEXT || $reader->nodeType == XMLReader::CDATA)
	{
		if ($nodeName == 'id') $id = $reader->value;
		if ($nodeName == 'url') $url = $reader->value;
		if ($nodeName == 'title') $title = $reader->value;
		if ($nodeName == 'author') $author = $reader->value;
		if ($nodeName == 'isbn') $isbn = $reader->value;
		if ($nodeName == 'image') $image = $reader->value;
		if ($nodeName == 'ean') $ean = $reader->value;
		if ($nodeName == 'published') $published = $reader->value;
		if ($nodeName == 'publisher') $publisher = $reader->value;
		if ($nodeName == 'pages') $pages = $reader->value;
		if ($nodeName == 'price') $price = $reader->value;
		if ($nodeName == 'description') $description = $reader->value;
		if ($nodeName == 'status') $status = $reader->value;
		$ean = '';
	}
 
	if($reader->nodeType == XMLReader::END_ELEMENT &amp;&amp; $reader->name == 'item')
	{
		$count++;
	}
}
$reader->close();