<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arkadiusz Kuryłowicz, blog prywatny &#187; Developer</title>
	<atom:link href="http://www.kurylowicz.info/category/dev/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kurylowicz.info</link>
	<description>Blog prywatny, projekty, PHP, Linux, MySQL</description>
	<lastBuildDate>Thu, 19 Nov 2009 21:40:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Proof of concept: demon fastcgi w PHP tudzież serwlet PHP</title>
		<link>http://www.kurylowicz.info/2009/11/01/proof-of-concept-demon-fastcgi-w-php/</link>
		<comments>http://www.kurylowicz.info/2009/11/01/proof-of-concept-demon-fastcgi-w-php/#comments</comments>
		<pubDate>Sun, 01 Nov 2009 00:28:44 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[Php]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/?p=133</guid>
		<description><![CDATA[Z racji, iż w firmie dla której pracuję, zajmuję się sporo tematem optymalizacji kodu chodzą mi po głowie kuriozalne niekiedy pomysły. W ostatnim wpisie objaśniałem jak działa mechanizm FastCgi. Pośrednikiem pomiędzy skryptem PHP a klientem FastCGI jest SAPI php.cgi. Implementuje to główne założenie jak i niestety wadę PHP - konieczność uruchomienia skryptu dla każdego żądania [...]]]></description>
			<content:encoded><![CDATA[<p>Z racji, iż w firmie dla której pracuję, zajmuję się sporo tematem optymalizacji kodu chodzą mi po głowie kuriozalne niekiedy pomysły. W ostatnim wpisie objaśniałem jak działa mechanizm FastCgi. Pośrednikiem pomiędzy skryptem PHP a klientem FastCGI jest SAPI php.cgi. Implementuje to główne założenie jak i niestety wadę PHP - konieczność uruchomienia skryptu dla każdego żądania HTTP.</p>
<p>A co gdyby napisać demona w PHP, który potrafiłby przyjmować żądania z klienta FastCgi, przekazać je do zainicjalizowanego już kontrolera (patrz MVC) odebrać wynik i odesłać? Pomysł fajny - odpada konieczność wielokrotnej uruchamiania, kompilacji kodu, inkludowania plików, bo przecież aplikacja cały czas działa. Odpada konieczność konstruowania klas, populowania w nich danych dla każdego żądania - wystarczy zrobić to raz, podczas uruchomienia.</p>
<p>Tak mi się ten pomysł spodobał, że postanowiłem się przekonać, czy to ma szanse zadziałać. Google? Cóż, nikt chyba wcześniej nie wpadł na taki pomysł, ponieważ nie znalazłem niczego konkretnego. Zacząłem zatem od <a href="http://www.fastcgi.com/devkit/doc/fcgi-spec.html">specyfikacji protokołu FastCgi</a>. Sam protokół do najprostszych nie należy, nie mniej jednak w implementacji serwera pomogła mi implementacja klienta stworzona na potrzeby aplikacji <a href="http://nanoweb.si.kz/">Nanoweb - The PHP Web Server</a>. Dodatkowo posłużyłem się funkcjonalnością <a href="http://pl.php.net/manual/en/book.pcntl.php">PCNTL</a> w celu implementacji wielowątkowości.</p>
<p>Testowa aplikacja działała na zasadzie utworzenia nasłuchującego na porcie TCP socketa, w momencie nadejścia połączenia wersja 1) odsyłała odpowiedź, zamykała połaczenie z klientem i była gotowa do obsługi następnych wersja 2) dla każdego żądania tworzyła nowy wątek. Obie wersje, oraz skrypt referencyjny odpowiadały zawartością phpinfo().</p>
<p>Problemy jakie napotkałem po drodze:</p>
<ul>
<li>problem z parsowaniem ramek FCGI_PARAMS - one są osadzane w standardowej ramce FastCgi, ale mają chyba krótszy niż 8 bajtów nagłówek, postanowiłem całkowicie je zignorować, nie mniej jednak od ich poprawnego sparsowania zależy czy w aplikacji pojawi się tablica $_SERVER, $_GET i $_POST</li>
<li>trzeba samodzielnie zaimplementować cały mechanizm dekodowania formularzy jak i plików z żądania POST</li>
<li>zmienne pomiędzy procesami utworzonymi via pcntl_fork() kopiują się, nie są referencjami, dlatego w wątku potomnym możemy odczytać wartość zmiennej, ale zmiana nie jest widoczna dla innych wątków. Nie dotyczy to oczywiście zmiennych typu resource.</li>
</ul>
<p>Kiedy udało mi się już zaimplementować podstawowe minimum: demon potrafi odesłać prawidłową odpowiedź: przystąpiłem do benchmarkowania.</p>
<p><span id="more-133"></span></p>
<p>Wyniki mnie rozwaliły. Pierwsze referencyjny benchmark dla standardowej konfiguracji: apacz + php.fcgi -b 127.0.0.1:80800 + skrypt</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema ~<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">5</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">57346</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">5</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.859</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">5750300</span> bytes
HTML transferred:       <span style="color: #000000;">5734600</span> bytes
Requests per second:    <span style="color: #000000;">116.39</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">42.960</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">8.592</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">6535.76</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">0.3</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">3</span>
Processing:    <span style="color: #000000;">13</span>   <span style="color: #000000;">42</span>   <span style="color: #000000;">4.2</span>     <span style="color: #000000;">43</span>      <span style="color: #000000;">48</span>
Waiting:        <span style="color: #000000;">7</span>   <span style="color: #000000;">36</span>   <span style="color: #000000;">4.3</span>     <span style="color: #000000;">38</span>      <span style="color: #000000;">42</span>
Total:         <span style="color: #000000;">13</span>   <span style="color: #000000;">42</span>   <span style="color: #000000;">4.1</span>     <span style="color: #000000;">43</span>      <span style="color: #000000;">48</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">43</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">43</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">43</span>
  <span style="color: #000000;">80</span>%     <span style="color: #000000;">43</span>
  <span style="color: #000000;">90</span>%     <span style="color: #000000;">44</span>
  <span style="color: #000000;">95</span>%     <span style="color: #000000;">44</span>
  <span style="color: #000000;">98</span>%     <span style="color: #000000;">44</span>
  <span style="color: #000000;">99</span>%     <span style="color: #000000;">48</span>
 <span style="color: #000000;">100</span>%     <span style="color: #000000;">48</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Drugi wynik apacz + przygotowanego servera FastCGI bez forkowania, co oznacza, że każde żądanie przetwarzane jest pojedynczo:</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema ~<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">5</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">23082</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">5</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.622</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">2323900</span> bytes
HTML transferred:       <span style="color: #000000;">2308200</span> bytes
Requests per second:    <span style="color: #000000;">160.84</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">31.088</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">6.218</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">3650.07</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">0.6</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">5</span>
Processing:     <span style="color: #000000;">9</span>   <span style="color: #000000;">30</span>   <span style="color: #000000;">8.3</span>     <span style="color: #000000;">28</span>      <span style="color: #000000;">60</span>
Waiting:        <span style="color: #000000;">9</span>   <span style="color: #000000;">29</span>   <span style="color: #000000;">8.5</span>     <span style="color: #000000;">26</span>      <span style="color: #000000;">59</span>
Total:          <span style="color: #000000;">9</span>   <span style="color: #000000;">30</span>   <span style="color: #000000;">8.2</span>     <span style="color: #000000;">28</span>      <span style="color: #000000;">60</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">28</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">30</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">33</span>
  <span style="color: #000000;">80</span>%     <span style="color: #000000;">35</span>
  <span style="color: #000000;">90</span>%     <span style="color: #000000;">38</span>
  <span style="color: #000000;">95</span>%     <span style="color: #000000;">56</span>
  <span style="color: #000000;">98</span>%     <span style="color: #000000;">58</span>
  <span style="color: #000000;">99</span>%     <span style="color: #000000;">60</span>
 <span style="color: #000000;">100</span>%     <span style="color: #000000;">60</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Czas o parę procent krótszy dla zwykłego phpinfo(). W przypadku inicjalizacji połączeń z bazami, memcache, odczytywania identycznych zestawów danych (ustawień) ta różnica może być o wiele większa. <span style="text-decoration: line-through;">Przy czym pojawia się tu jeden problem: im więcej równoczesnych żądań (parametr -c dla ab) tym wynik jest gorszy i zbliża się do tego poniżej. Oba benchmarki, referencyjny jak i testowy obsługiwane były przez pojedynczy backend FastCgi, przy czym ten w referencyjnej konfiguracji radzi sobie lepiej ze współbieżnymi żądaniami.</span> Należy zadbać tutaj o odpowiednie parametry dla <a href="http://pl.php.net/manual/pl/function.socket-listen.php">socket_listen()</a> ponieważ zbyt mały backlog powoduje, iż połączenia współbieżne się kolejkują. Przy odpowiednio dużej wartości $backlog problem nie występuje.</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema ~<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">5</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">23047</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">5</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">3.327</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">2320400</span> bytes
HTML transferred:       <span style="color: #000000;">2304700</span> bytes
Requests per second:    <span style="color: #000000;">30.05</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">166.372</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">33.274</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">681.01</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">0.9</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">7</span>
Processing:    <span style="color: #000000;">11</span>  <span style="color: #000000;">165</span>  <span style="color: #000000;">62.5</span>    <span style="color: #000000;">166</span>     <span style="color: #000000;">391</span>
Waiting:        <span style="color: #000000;">8</span>  <span style="color: #000000;">132</span>  <span style="color: #000000;">60.7</span>    <span style="color: #000000;">129</span>     <span style="color: #000000;">288</span>
Total:         <span style="color: #000000;">11</span>  <span style="color: #000000;">165</span>  <span style="color: #000000;">62.3</span>    <span style="color: #000000;">166</span>     <span style="color: #000000;">391</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%    <span style="color: #000000;">166</span>
  <span style="color: #000000;">66</span>%    <span style="color: #000000;">189</span>
  <span style="color: #000000;">75</span>%    <span style="color: #000000;">204</span>
  <span style="color: #000000;">80</span>%    <span style="color: #000000;">209</span>
  <span style="color: #000000;">90</span>%    <span style="color: #000000;">236</span>
  <span style="color: #000000;">95</span>%    <span style="color: #000000;">270</span>
  <span style="color: #000000;">98</span>%    <span style="color: #000000;">337</span>
  <span style="color: #000000;">99</span>%    <span style="color: #000000;">391</span>
 <span style="color: #000000;">100</span>%    <span style="color: #000000;">391</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Jak łatwo zauważyć w tym przypadku wyniki są kilkanaście razy gorsze. Przypuszczam, że wynika to z niewydolności forkowania w PHP.</p>
<p><strong>Konkludując:</strong> idea wygląda wielce obiecująco i wydaje mi się, że <span style="text-decoration: line-through;">jeśli by rozwiązać jakoś problem spadku wydajności przy konkurencyjnych żądaniach (forkowanie skreślam całkowicie, wyniki mówią same za siebie) poprzez uruchomienie większej ilości instancji demona i rozproszoną dystrybucję żądań CGI</span> można by osiągnąć całkiem przyzwoite wyniki. Dalszą poprawę wydajności jak i redundancję systemu można osiągnąć poprzez uruchomienie klastra serwletów i balansowanie ruchu apacz, klient fCGI -&gt;serwlet z użyciem <a href="http://haproxy.1wt.eu/">HAProxy</a> (przetestowałem, z metodą balansowania round-robin, wyniki niżej)</p>
<p>Niestety inną sprawą jest stabilność takiego rozwiązania. PHP nie jest zaprojektowany do pracy w trybie demona i prawdopodobnie mogą pojawić się problemy z garbage collectorem lub wyciekami pamięci. Dodatkowo pisanie aplikacji serwletowych wymaga nieco innego podejścia do samej architektury - nie można sobie pozwolić na radosne używanie miliona zmiennych bez zawracania sobie głowy zwalnianiem pamięci, ponieważ trzeba mieć na uwadze, iż po zakończeniu żądania zaalokowana pamięć nie zostanie zwolniona samodzielnie. Dodatkowo zmienia się także koncepcja deployowania aplikacji, ponieważ każda zmiana kodu wymaga restartu całego klastra serwletów.</p>
<p><strong>Update:</strong> wyniki z użyciem 3 wątków php.fcgi -b 127.0.0.1:8061, php.fcgi -b 127.0.0.1:8062, php.fcgi -b 127.0.0.1:8063 + haproxy z balansowaniem round-robin:</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema php cgi server<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">15</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">57373</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">15</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.535</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">33</span>
   <span style="color: #7a0874; font-weight: bold;">&#40;</span>Connect: <span style="color: #000000;">0</span>, Receive: <span style="color: #000000;">0</span>, Length: <span style="color: #000000;">33</span>, Exceptions: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">5754584</span> bytes
HTML transferred:       <span style="color: #000000;">5738884</span> bytes
Requests per second:    <span style="color: #000000;">186.75</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">80.323</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">5.355</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">10494.54</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">5</span>   <span style="color: #000000;">9.6</span>      <span style="color: #000000;">0</span>      <span style="color: #000000;">31</span>
Processing:    <span style="color: #000000;">24</span>   <span style="color: #000000;">70</span>  <span style="color: #000000;">24.0</span>     <span style="color: #000000;">68</span>     <span style="color: #000000;">117</span>
Waiting:        <span style="color: #000000;">6</span>   <span style="color: #000000;">57</span>  <span style="color: #000000;">25.4</span>     <span style="color: #000000;">55</span>     <span style="color: #000000;">106</span>
Total:         <span style="color: #000000;">30</span>   <span style="color: #000000;">75</span>  <span style="color: #000000;">22.6</span>     <span style="color: #000000;">77</span>     <span style="color: #000000;">117</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">77</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">85</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">90</span>
  <span style="color: #000000;">80</span>%     <span style="color: #000000;">95</span>
  <span style="color: #000000;">90</span>%    <span style="color: #000000;">110</span>
  <span style="color: #000000;">95</span>%    <span style="color: #000000;">112</span>
  <span style="color: #000000;">98</span>%    <span style="color: #000000;">115</span>
  <span style="color: #000000;">99</span>%    <span style="color: #000000;">117</span>
 <span style="color: #000000;">100</span>%    <span style="color: #000000;">117</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Wyniki z użyciem 3 instancji serwletu + haproxy z balansowaniem round-robin:</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema php cgi server<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">15</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">23173</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">15</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.479</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">67</span>
   <span style="color: #7a0874; font-weight: bold;">&#40;</span>Connect: <span style="color: #000000;">0</span>, Receive: <span style="color: #000000;">0</span>, Length: <span style="color: #000000;">67</span>, Exceptions: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">2329784</span> bytes
HTML transferred:       <span style="color: #000000;">2314084</span> bytes
Requests per second:    <span style="color: #000000;">208.65</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">71.891</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">4.793</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">4747.12</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">2</span>   <span style="color: #000000;">5.1</span>      <span style="color: #000000;">0</span>      <span style="color: #000000;">21</span>
Processing:     <span style="color: #000000;">9</span>   <span style="color: #000000;">64</span>  <span style="color: #000000;">45.3</span>     <span style="color: #000000;">49</span>     <span style="color: #000000;">180</span>
Waiting:        <span style="color: #000000;">2</span>   <span style="color: #000000;">61</span>  <span style="color: #000000;">45.0</span>     <span style="color: #000000;">46</span>     <span style="color: #000000;">179</span>
Total:          <span style="color: #000000;">9</span>   <span style="color: #000000;">66</span>  <span style="color: #000000;">44.8</span>     <span style="color: #000000;">52</span>     <span style="color: #000000;">180</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">52</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">60</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">85</span>
  <span style="color: #000000;">80</span>%    <span style="color: #000000;">105</span>
  <span style="color: #000000;">90</span>%    <span style="color: #000000;">148</span>
  <span style="color: #000000;">95</span>%    <span style="color: #000000;">166</span>
  <span style="color: #000000;">98</span>%    <span style="color: #000000;">180</span>
  <span style="color: #000000;">99</span>%    <span style="color: #000000;">180</span>
 <span style="color: #000000;">100</span>%    <span style="color: #000000;">180</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Jak widać wyniki serwletu nadal lepsze i zapewne jak w poprzednim przypadku róznica może powiększyć się parokrotnie przy kodzie wymagającym inicjalizacji stałych elementów (konfig, includy klas).</p>
<p><strong>Update:</strong> wyniki z jednym watkiem serwletu, ale za to z nieco bardziej złożoną aplikacją: klasa, która w konstruktorze tworzy jedno połaczenie do memcache, jedno połaczenie z bazą danych i robi prepare zapytania SQL, i dalej we właściwej metodzie run() podbija wartość klucza memcache i wykonuje przygotowane wcześniej zapytanie.</p>
<p>Test php.cli -b 127.0.0.1:8060, klasa inicjalizowana i uruchamiana w pojedynczym pliku index.php</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema var<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">10</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">1990</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">10</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.483</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">214700</span> bytes
HTML transferred:       <span style="color: #000000;">199000</span> bytes
Requests per second:    <span style="color: #000000;">207.17</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">48.270</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">4.827</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">434.36</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">1.2</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">5</span>
Processing:    <span style="color: #000000;">12</span>   <span style="color: #000000;">46</span>   <span style="color: #000000;">6.6</span>     <span style="color: #000000;">48</span>      <span style="color: #000000;">60</span>
Waiting:       <span style="color: #000000;">11</span>   <span style="color: #000000;">45</span>   <span style="color: #000000;">6.6</span>     <span style="color: #000000;">47</span>      <span style="color: #000000;">60</span>
Total:         <span style="color: #000000;">13</span>   <span style="color: #000000;">46</span>   <span style="color: #000000;">6.4</span>     <span style="color: #000000;">48</span>      <span style="color: #000000;">65</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">48</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">48</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">49</span>
  <span style="color: #000000;">80</span>%     <span style="color: #000000;">49</span>
  <span style="color: #000000;">90</span>%     <span style="color: #000000;">50</span>
  <span style="color: #000000;">95</span>%     <span style="color: #000000;">50</span>
  <span style="color: #000000;">98</span>%     <span style="color: #000000;">59</span>
  <span style="color: #000000;">99</span>%     <span style="color: #000000;">65</span>
 <span style="color: #000000;">100</span>%     <span style="color: #000000;">65</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Test serwletu, klasa inicjalizowana przed otwarciem portu TCP, połączenie klienckie wykonuje metodę run() na zainicjalizowanej już klasie:</p>
<pre class="bash"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pink@poema var<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ ab -n <span style="color: #000000;">100</span> -c <span style="color: #000000;">10</span> http://stateless.projekt.kurylowicz.info/
This is ApacheBench, Version <span style="color: #000000;">2.3</span> &amp;lt;<span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $&amp;gt;
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
&nbsp;
Benchmarking stateless.projekt.kurylowicz.info <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>.....<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
Server Software:        Apache/<span style="color: #000000;">2.2</span><span style="color: #000000;">.14</span>
Server Hostname:        stateless.projekt.kurylowicz.info
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          /
Document Length:        <span style="color: #000000;">1994</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">10</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.245</span> seconds
Complete requests:      <span style="color: #000000;">100</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">215100</span> bytes
HTML transferred:       <span style="color: #000000;">199400</span> bytes
Requests per second:    <span style="color: #000000;">407.70</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #808080; font-style: italic;">#/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
Time per request:       <span style="color: #000000;">24.528</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">2.453</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">856.41</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes/sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+/-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">1</span>   <span style="color: #000000;">2.5</span>      <span style="color: #000000;">0</span>      <span style="color: #000000;">13</span>
Processing:     <span style="color: #000000;">8</span>   <span style="color: #000000;">22</span>   <span style="color: #000000;">7.0</span>     <span style="color: #000000;">22</span>      <span style="color: #000000;">42</span>
Waiting:        <span style="color: #000000;">5</span>   <span style="color: #000000;">21</span>   <span style="color: #000000;">7.3</span>     <span style="color: #000000;">20</span>      <span style="color: #000000;">41</span>
Total:          <span style="color: #000000;">8</span>   <span style="color: #000000;">24</span>   <span style="color: #000000;">7.0</span>     <span style="color: #000000;">23</span>      <span style="color: #000000;">43</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span>%     <span style="color: #000000;">23</span>
  <span style="color: #000000;">66</span>%     <span style="color: #000000;">25</span>
  <span style="color: #000000;">75</span>%     <span style="color: #000000;">28</span>
  <span style="color: #000000;">80</span>%     <span style="color: #000000;">31</span>
  <span style="color: #000000;">90</span>%     <span style="color: #000000;">33</span>
  <span style="color: #000000;">95</span>%     <span style="color: #000000;">37</span>
  <span style="color: #000000;">98</span>%     <span style="color: #000000;">41</span>
  <span style="color: #000000;">99</span>%     <span style="color: #000000;">43</span>
 <span style="color: #000000;">100</span>%     <span style="color: #000000;">43</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre>
<p>Jak widac z dwóch powyższych testów średni czas przetwarzania pojedynczego żadania przez serwlet jest <strong>50%</strong> krótszy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/11/01/proof-of-concept-demon-fastcgi-w-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stored procedures czasem sie przydają</title>
		<link>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/</link>
		<comments>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 13:17:58 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2009/04/06/stored-procedures-czasem-sie-przydaja/</guid>
		<description><![CDATA[Podczas konwersji bazy danych serwisu Poema napotkałem pewien problem. Otóż dane dotyczące przypisania użytkownika do grup dostępu nie były zapisywane w osobnej tabeli jako indywidualne rekordy, lecz w rekordzie użytkownika, w pojedynczym polu o nazwie GID,  jako identyfikatory grup oddzielanych przecinkami, np. '1,3,19,3' lub pojedyncze wartości '8'. Z oczywistych względów dane takie są mało użyteczne. [...]]]></description>
			<content:encoded><![CDATA[<p>Podczas konwersji bazy danych serwisu Poema napotkałem pewien problem. Otóż dane dotyczące przypisania użytkownika do grup dostępu nie były zapisywane w osobnej tabeli jako indywidualne rekordy, lecz w rekordzie użytkownika, w pojedynczym polu o nazwie GID,  jako identyfikatory grup oddzielanych przecinkami, np. '1,3,19,3' lub pojedyncze wartości '8'. Z oczywistych względów dane takie są mało użyteczne. Zatem trzeba je przenieść do osobnej tabeli i powkładać w indywidualne rekordy. Na pierwszy rzut oka MySQL sobie nie poradzi. No to skrypt PHP, ale... leniwy jestem - nie chce mi się pisać skryptu, może zatem jednak MySQL. Rozwiązaniem jest napisanie własnej funkcji. Wygląda ona mniej więcej tak:</p>
<pre class="mysql">delimiter //</pre>
<pre class="mysql"><span style="color: #993333; font-weight: bold;">CREATE FUNCTION</span> create_records_in_poema_uid_group<span style="color: #66cc66;">&#40;</span>p_id <span style="color: #aa9933; font-weight: bold;">INT</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">RETURNS</span> <span style="color: #aa9933; font-weight: bold;">INT</span>
<span style="color: #993333; font-weight: bold;">BEGIN</span>
  <span style="color: #993333; font-weight: bold;">DECLARE</span> gid_set <span style="color: #aa9933; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #aa3399; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> gid <span style="color: #aa9933; font-weight: bold;">INT</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> pos <span style="color: #aa9933; font-weight: bold;">INT</span>;
&nbsp;
  <span style="color: #993333; font-weight: bold;">SET</span> @done = <span style="color: #cc66cc;">0</span>;
  <span style="color: #993333; font-weight: bold;">SET</span> @num = <span style="color: #cc66cc;">0</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Pobieramy wartość pola do zmiennej gid_set, pole może wyglądać</span>
  <span style="color: #808080; font-style: italic;">-- '1,5,12,16' lub być pojedyncza wartością '10'</span>
  <span style="color: #808080; font-style: italic;">-- dodatkowy warunek w WHERE zapobiega duplikatom</span>
     <span style="color: #993333; font-weight: bold;">SELECT</span> u.GID
       <span style="color: #993333; font-weight: bold;">INTO</span> gid_set
       <span style="color: #993333; font-weight: bold;">FROM</span> poema_users u
  <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> poema_uid_group g ON <span style="color: #66cc66;">&#40;</span>g.intUid = u.ID<span style="color: #66cc66;">&#41;</span>
      <span style="color: #993333; font-weight: bold;">WHERE</span> u.ID = p_id
        <span style="color: #993333; font-weight: bold;">AND</span> g.intUidGroupId <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #aa3399; font-weight: bold;">NULL</span>;
&nbsp;
  IF gid_set &lt;&gt; <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">THEN</span>
    <span style="color: #993333; font-weight: bold;">REPEAT</span>
&nbsp;
      <span style="color: #808080; font-style: italic;">-- Ustalamy pozycję znaku przecinka</span>
      <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">LOCATE</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span>, gid_set<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> pos;
&nbsp;
      IF pos &gt; <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">THEN</span>
        <span style="color: #808080; font-style: italic;">-- jest przecinek, odetnij pierwszą wartość, i usuń ją ze zmiennej gid_set</span>
        <span style="color: #993333; font-weight: bold;">SELECT</span> CAST<span style="color: #66cc66;">&#40;</span>SUBSTR<span style="color: #66cc66;">&#40;</span>gid_set, <span style="color: #cc66cc;">1</span>, pos<span style="color: #66cc66;">&#41;</span> AS <span style="color: #aa3399; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid;
        <span style="color: #993333; font-weight: bold;">SELECT</span> SUBSTR<span style="color: #66cc66;">&#40;</span>gid_set, pos + <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid_set;
      <span style="color: #993333; font-weight: bold;">ELSE</span>
        <span style="color: #808080; font-style: italic;">-- nie znaleziono przecinka, gid_set zawiera wyłącznie cyfrę,</span>
        <span style="color: #808080; font-style: italic;">-- zzutuj ją do zmiennej gid jako</span>
        <span style="color: #808080; font-style: italic;">-- INT i ustaw flagę zakończenia pętli</span>
        <span style="color: #993333; font-weight: bold;">SELECT</span> CAST<span style="color: #66cc66;">&#40;</span>gid_set AS <span style="color: #aa3399; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid;
        <span style="color: #993333; font-weight: bold;">SET</span> @done = <span style="color: #cc66cc;">1</span>;
      <span style="color: #993333; font-weight: bold;">END</span> IF;
&nbsp;
      <span style="color: #808080; font-style: italic;">-- Można dodać rekord do bazy</span>
      <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> poema_uid_group <span style="color: #66cc66;">&#40;</span>intUid, intGid, intGrantorUid, dtmGranted<span style="color: #66cc66;">&#41;</span>
      <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>p_id, gid, <span style="color: #cc66cc;">1</span>, <span style="color: #993333; font-weight: bold;">NOW</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
      <span style="color: #993333; font-weight: bold;">SET</span> @num = @num + <span style="color: #cc66cc;">1</span>;
&nbsp;
    UNTIL @done <span style="color: #993333; font-weight: bold;">END</span> <span style="color: #993333; font-weight: bold;">REPEAT</span>;
  <span style="color: #993333; font-weight: bold;">END</span> IF;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Zwróć ilość dodanych rekordów</span>
  RETURN @num;
<span style="color: #993333; font-weight: bold;">END</span>;
//</pre>
<pre class="mysql">delimiter ;</pre>
<p>Ok, funkcja dodana, teraz wystarczy wywołać ją dla każdego ID użytkownika:</p>
<pre class="mysql"><span style="color: #993333; font-weight: bold;">SELECT</span> create_records_in_poema_uid_group<span style="color: #66cc66;">&#40;</span>ID<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> poema_users;</pre>
<p>Przy odrobinie inwencji będziesz w stanie wykorzystać funkcję do rozwiązania podobnego problemu w Twojej bazie danych.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

