Dziś jest piątek, 25 lipca 2008 roku (z kalendarza...)

Formaty danych: benchmark cz. 2

Icon

05.09.2007, 10:02

PHP

Komentarze (3)

Powrót

W poprzednim wpisie porównywaliśmy szybkość odczytu różnych formatów danych dostępnych w PHP, a także ich możliwości. Ponieważ jednak po jego opublikowaniu pojawiły się nowe pytania, zdecydowałem się napisać kontynuację, w której postaram się je wyjaśnić. Przyjrzymy się kompilowanemu rozszerzeniu Syck do parsowania YAML w PHP, które znalazłem w repozytorium PECL - jednak więc takie coś istnieje, tyle że w wersji beta, a wyszukiwarka niestety nie pomaga w jego znalezieniu, jeśli nie zna się tej nazwy. Ponadto porównamy szybkość SimpleXML oraz DOM. Procedura testowa pozostaje ta sama.

Zacznę od YAML. Poprzednio testowaliśmy tu dwa przypadki. Pierwszy to napisana w PHP biblioteka Spyc - w czystej postaci nie wypadła ona rewelacyjnie, osiągając jedynie około 250 req/s, podczas gdy wszystkie inne formaty przetwarzane przez napisane w C parsery miały przynajmniej 2700. Dla zmniejszenia liczby operacji dyskowych usunąłem z kodu biblioteki wszystkie komentarze i wkleiłem jej kod bezpośrednio do skryptu testowego (przy korzystaniu z require wydajność spadała do ok. 140 req/s). Drugi przypadek to rozbudowa kodu o cache'owanie danych w postaci zserializowanej tablicy. Do testowania, czy istnieje cache, korzystałem z funkcji file_exists, lecz pozostawiłem w pliku kod Spyca. Rezultat to około 900 req/s.

Tu nastąpiło istotne przeoczenie - powinienem jeszcze uwzględnić przypadek, ładowania Spyca tylko wtedy, gdy jest on rzeczywiście potrzebny. Kod przykładu testowego prezentuje się następująco:

<?php
	if(@(filemtime('./file.ydt') > filemtime('./file.yaml')))
	{
		$info = unserialize(file_get_contents('./file.ydt'));
	}
	else
	{
		require('./spyc.php');
		$spyc = new spyc;
		$info = $spyc -> load('./file.yaml');
		file_put_contents('./file.ydt', serialize($info));
	}
?>

Tak napisany skrypt uzyskuje wyniki rzędu 2500-2600 req/s. Jeśli zastąpimy dwa wywołania filemtime() przez jedno file_exists(), wydajność wzrośnie do ok. 3200 req/s, lecz musimy wtedy wynaleźć inny sposób automatycznego sprawdzania, czy oryginał pliku nie został zmieniony.

Przetestowałem także rozszerzenie ściągnięte z repozytorium PECL. Są to w zasadzie dwie dodatkowe funkcje dla PHP: syck_load() oraz syck_dump(). Instalacja w Arch Linuksie była bardzo prosta:

# yaourt -Sy syck
# pecl install syck-0.9.1
# echo "extension=syck.so" >> /etc/php.ini
# /etc/rc.d/httpd restart

Moduł musiał wczytać ten sam plik konfiguracyjny, co inne. Udało mu się wykonać około 2700 req/s. Dodając cache'owanie można ten rezultat dalej poprawić.

Na prośbę Splatcha przyjrzałem się też dokładniej różnym sposobom przetwarzania XML-a w samym PHP. Przypomnę, że użyty wczoraj SimpleXML osiągnął wynik ok. 2800 req/s. Dziś sprawdziłem rozszerzenie DOM, które parsowało identyczny plik i jego rezultat to ok. 2700 req/s. Różnica nieduża, ale zauważalna podczas uruchamiania procedur testowych. Jednak to nie wszystko. PHP przechowuje dane wczytane z plików XML w formie drzewa obiektów, z którego trzeba je wyciągać na różne sposoby i nie zawsze jest to szczyt elegancji oraz wygody. Postanowiłem sprawdzić, jak wydajny jest ten proces. Stworzyłem dwa skrypty testowe, które załadowany plik testowy miały przekonwertować na dokładnie taką samą tablicę, jaką otrzymalibyśmy, ładując dane z YAML-a. Na początek konwerter SimpleXML:

<?php
	$xml = simplexml_load_file('./file.xml');
 
	$info = array();
	foreach($xml -> group as $grp)
	{
		$info[(string)$grp['name']] = array();
		foreach($grp -> option as $opt)
		{
			$info[(string)$grp['name']][(string)$opt['name']] = (string)$opt;
		}
	}
?>

Potem DOM:

<?php
	$dom = new DOMDocument();
	$dom -> load('file.xml');
 
	$info = array();
	$groups = $dom -> getElementsByTagName('group');
	for($i = 0; $i < $groups -> length; $i++)
	{
		$item = $groups -> item($i);
		$info[$item -> getAttribute('name')] = array();
 
		$options = $item -> getElementsByTagName('option');
		for($j = 0; $j < $options -> length; $j++)
		{
			$subitem = $options -> item($j);
			$info[$item -> getAttribute('name')][$subitem -> getAttribute('name')] = (string)$subitem -> nodeValue;
		}
	}
?>

Wynik: SimpleXML - 2100 req/s. DOM - 1800 req/s. Nawet po uwzględnieniu samego czasu załadowania pliku do pamięci rezultaty działają na korzyść pierwszego z rozszerzeń. Można zatem pokusić się o wniosek, że rezygnując z części funkcjonalności i upraszczając API, zyskujemy w zamian większą wydajność.

Okazało się, że YAML-a skreśliłem nieco zbyt szybko. Dobry system cache potrafi bowiem zdziałać cuda. Z drugiej strony Syck mnie lekko zawiódł - sądziłem, że prostota tego języka umożliwi napisanie mniejszego i zarazem wydajniejszego parsera, ale jak widać, twórców projektu czeka jeszcze sporo optymalizacji, zanim uda im się tego dokonać. Różnice czasowe wprawdzie nie są wielkie, ale miałem nadzieję na przynajmniej 3000 req/s.

Powrót

Komentarze

Napisał Ludvik w środę, 5 września 2007 o 11:27

Bardzo dobre porównanie, zdziwiłem się tylko słabym wynikiem yaml+cache w pierwszej części... Jak widzę, wszystko już sprostowane ;) Sam stawiałem właśnie na cache'owany yaml, który jest moim zdaniem w tym przypadku przyjemniejszy od xmla...

Miałem w przyszłości przemyśleć ten temat, więc mam jeden problem z głowy ;)

Napisał blid w środę, 5 września 2007 o 14:56

Bardzo przydatne opracowanie. Osobiscie jestem troche zawiedziony stosunkowo wolnym odczytem plikow YAML, a jeszcze bardziej tym, ze obsluga takowych plikow nie jest wbudowana w PHP.

Napisał rad w środę, 5 września 2007 o 21:58

Świetne opracowanie, widzę, że będę musiał się przenieść na SimpleXML, zawsze z przyzwyczajenia z JavaScriptu korzystałem z DOM.

Strona 1 z 1 :: 1

Skomentuj

NickInformacja
E-mailTylko do użytku wewnętrznego.
WWWNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki
Internauto, pamiętaj! Wolność to nie samowola - dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2008 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia