<?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</title>
	<atom:link href="http://www.kurylowicz.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kurylowicz.info</link>
	<description>Blog prywatny, projekty, PHP, Linux, MySQL</description>
	<lastBuildDate>Sun, 11 Apr 2010 12:11:31 +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>Smoleńsk</title>
		<link>http://www.kurylowicz.info/2010/04/11/smolensk/</link>
		<comments>http://www.kurylowicz.info/2010/04/11/smolensk/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 11:52:15 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Prywatne]]></category>

		<guid isPermaLink="false">http://www.kurylowicz.info/?p=165</guid>
		<description><![CDATA[Trudno przejść obok wczorajszej tragedii obojętnie, trudno nie skomentować, choć wiele - czy nawet wszystko już zostało powiedziane i napisane. Tragedia jest dla mnie tym dotkliwsza, bo był to także mój prezydent. Jeśli tak popatrzeć na to z pewnego dystansu, dostrzec można symboliczny wymiar tej tragedii. I bynajmniej, nie chodzi mi o symbolikę, którą niektóre [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Trudno przejść obok wczorajszej tragedii obojętnie, trudno nie skomentować, choć wiele - czy nawet wszystko już zostało powiedziane i napisane. Tragedia jest dla mnie tym dotkliwsza, bo był to także <a href="http://www.kurylowicz.info/2007/10/28/konkluzje-po-wyborcze">mój prezydent</a>. Jeśli tak popatrzeć na to z pewnego dystansu, dostrzec można symboliczny wymiar tej tragedii. I bynajmniej, nie chodzi mi o symbolikę, którą niektóre media próbują obrazować, zestawiając  obok Katynia 2010, Katyń z roku 1940. To jest co najmniej dziwaczne zestawienie. Mi chodzi przede wszystkim o symbolikę poświęcenia dla ofiar wydarzeń z 1940. To poświęcenie jest wartościowe, bo wydaje mi się, iż wczorajsze wydarzenia na pewno przyczynią się do zaistnienia w świadomości świata terminu "zbrodnia katyńska", który pojawia się w kontekście samych wydarzeń. Wystarczyło spojrzeć wczoraj na Google trends albo Tweetera, wystarczy popatrzeć na dzisiejsze doniesienia z prasy zagranicznej, czy choćby tak symboliczne wydarzenie, jak <a href="http://wiadomosci.gazeta.pl/Wiadomosci/1,80277,7757734,Rosyjska_telewizja_panstwowa_wieczorem_pokaze__Katyn_.html" target="_blank">emisja Katynia Wajdy</a> w głównym programie publicznej telewizji rosyjskiej. Pozostaje sobie tylko zadać pytanie, czemu takim kosztem?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2010/04/11/smolensk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dobraniania.pl unleashed</title>
		<link>http://www.kurylowicz.info/2009/11/17/dobraniania-pl-unleashed/</link>
		<comments>http://www.kurylowicz.info/2009/11/17/dobraniania-pl-unleashed/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 04:00:36 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Projekty]]></category>

		<guid isPermaLink="false">http://www.kurylowicz.info/?p=155</guid>
		<description><![CDATA[Wczoraj po długich trudach udało się wreszcie wypuścić pierwszy oficjalny release projektu, nad którym z doskoku siedziałem niemalże rok: serwis ogłoszeń opiekunek www.dobraniania.pl. Serwis wykonany jest w oparciu o mój framework, o którym może nieco później coś wspomnę, na łamach bloga. Strona wykonana jest w technologii PHP 5 i oparta na bazie danych MySQL. Serwis [...]]]></description>
			<content:encoded><![CDATA[<p>Wczoraj po długich trudach udało się wreszcie wypuścić pierwszy oficjalny release projektu, nad którym z doskoku siedziałem niemalże rok: serwis ogłoszeń opiekunek <a href="http://www.dobraniania.pl" target="_blank">www.dobraniania.pl</a>. Serwis wykonany jest w oparciu o mój framework, o którym może nieco później coś wspomnę, na łamach bloga. Strona wykonana jest w technologii PHP 5 i oparta na bazie danych MySQL. Serwis ma zastapić istniejący portal prowadzony przez firmę, dla której oprogramowanie było pisane.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/11/17/dobraniania-pl-unleashed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Apache + PHP+ FastCGI + Spawn FastCGI? Wydajność, migracja.</title>
		<link>http://www.kurylowicz.info/2009/09/20/apache-php-fastcgi-spawn-fastcgi-wydajnosc-migracja/</link>
		<comments>http://www.kurylowicz.info/2009/09/20/apache-php-fastcgi-spawn-fastcgi-wydajnosc-migracja/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 21:32:54 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Php]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/?p=119</guid>
		<description><![CDATA[
Mijający już weekend upłynął mi pod znakiem migracji serwera www.poema.art.pl na FastCgi. Sporo alternatyw, sporo, ale niepełnych informacji - trudno się w tym połapać komuś, kto nie jest zaznajomiony z tą technologią.  Ale od początku. Dlaczego warto się przerzucić  na FastCgi? Otóż powody są co najmniej dwa:

wydajność
bezpieczeństwo

Rozwinięcie wątku wydajności należałoby zacząć od wyjaśnienia w [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify">
<p>Mijający już weekend upłynął mi pod znakiem migracji serwera www.poema.art.pl na FastCgi. Sporo alternatyw, sporo, ale niepełnych informacji - trudno się w tym połapać komuś, kto nie jest zaznajomiony z tą technologią.  Ale od początku. Dlaczego warto się przerzucić  na FastCgi? Otóż powody są co najmniej dwa:</p>
<ol>
<li>wydajność</li>
<li>bezpieczeństwo</li>
</ol>
<p style="text-align: justify">Rozwinięcie wątku wydajności należałoby zacząć od wyjaśnienia w jaki sposób FastCgi działa. Otóż dzięki FastCgi separujemy wykonanie kodu PHP od wątków Apacza. Apacz w modelu FastCgi służy wyłącznie do komunikacji z przeglądarką klienta. W momencie kiedy klient zażąda uruchomienia skryptu PHP - żądanie to przekazywane jest do 'serwera FastCGI' który używając interpretera PHP uruchamia skrypt i odsyła wynik do Apacza. Wygląda to mniej więcej tak:</p>
<pre>+----------+  TCP 80  +----------+ Unix socket
|  Klient  | &lt;-----&gt;  |  Apache  | &lt;-----+
+----------+          +----------+       |
                       user: http        |
+----------+          +----------+       |      +-------------+        +--------------+
|  Klient  | &lt;-----&gt;  |  Apache  | &lt;-----+----&gt; | PHP FastCgi | &lt;----&gt; | Server MySQL |
+----------+          +----------+       |      +-------------+        +--------------+
                       user: http        |        user: john
+----------+          +----------+       |
|  Klient  | &lt;-----&gt;  |  Apache  | &lt;-----+
+----------+          +----------+
                       user: http</pre>
<p style="text-align: justify">Przy użyciu spawn-fastcgi uruchamiamy dla każdego z użytkowników własny serwer PHP FastCgi który nasłuchuje na Unixowym sockecie. Apache komunikuje się po sockecie z wybranym zgodnie z ustawieniami (per vhost) serwerem żądając wykonania skryptu. Dzięki temu otrzymujemy izolację wątków PHP od wątków Apache. Dodatkowo PHP FastCgi działając z uprawnieniami użytkownika, nie zaś serwera Apache ma możliwość zapisu do katalogów użytkownika, a także ograniczenia odczytu plików do których posiada uprawnienia.</p>
<h2>Ok, ale co z wydajnością?</h2>
<p style="text-align: justify">Po pierwsze Apache, dzięki temu że nie parsuje w każdym swoim wątku PHP zabiera o wiele mniej pamięci. Przy dużej ilości żądań jest  to sprawa kluczowa. Dzięki modelowi FastCgi można w prawidłowy sposób wykorzystać mechanizm database persistent connections (eg. w MySQL). W przypadku wielu wątków Apacza parsujących PHP nawiązywanych jest tyle połączeń ile wątków. Nowe wątki nie potrafią użyć ponownie połączeń utworzonych przez zabite wątki. Dzięki temu w parę minut osiągamy maksymalny limit połączeń z bazą.  W przypadku FastCgi nawiązanych zostaje tyle połączeń ile wątków i połączenia te są cały czas utrzymywane. To jest także sprawa kluczowa dla serwisów o wysokim obciążeniu.</p>
<h2>Bezpieczeństwo?</h2>
<p style="text-align: justify">Wspomniałem wcześniej - wykonanie kodu PHP z uprawnieniami użytkownika. Ale nie tylko - separacja cache APC to kolejny element bezpieczeństwa. Dalej: możliwość pozbycia się safe mode w PHP - aktualnie to mechanizm z którego PHP się wycofuje. W wersji 5 ma już go nie być.</p>
<h2>fCgi, FastCgi, fCgid?</h2>
<p style="text-align: justify;">Jest sporo zamieszania jeśli chodzi o mechanizm FastCgi. Istnieje mnóstwo alternatyw. Osoba zaznajamiająca się z tematem za pomocą poldek search *cgi*   może czyć się nieco zagubiona. Dlatego opiszę co potrzebujemy aby to wszystko właściwie uruchomić.</p>
<p style="text-align: justify;">Zacznijmy od końca, czyli od PHP. Potrzebna będzie paczka zawierająca interpreter fcgi dla PHP - jest to dodatkowy moduł SAPI (oprócz eg. zwyczajnego cli, lub modułu do Apacha) które można skompilować, tudzież zainstalować. Pod PLD jest to pakiet "php-fcgi". Dalej, przyda się coś co będzie potrafiło utworzyć nam serwery FastCgi dla użytkowników. Pakiet "spawn-fcgi" jest całkiem dobry do tego. I wreszcie musimy nauczyć Apache komunikować się z naszymi serwerami. Doinstalujmy moduł "apache-mod_fastcgi".</p>
<p style="text-align: justify;">Wszystkie moduły można bez obaw zainstalować na serwerze który używa modułu "apache-mod_php"  do parsowania kodu PHP. Generalnie można używać obu modeli parsowania jednocześnie - część vhostów i aplikacji parsować modułem Apacza, najbardziej obciążone vhosty puścić przez FastCgi.</p>
<p><span id="more-119"></span></p>
<h2>Konfiguracja PHP</h2>
<p style="text-align: justify;">Nieco problematyczną sprawą w modelu FastCgi jest  konfiguracja PHP per vhost. Nie możemy do tego użyć ani plików .htacess ani dyrektyw php_flag w konfiguracji vhosta. Należy dla każdego z vhostów wymagającego niestandardowego konfigu utworzyć osobny php.ini. Ma to jedną zasadniczą wadę. /etc/php/php.ini który zawiera nasze istawienia PHP nie będzie czytany. Zatem dla każdego z vhostów należy mieć kopię php.ini zawierającą <strong>wsztstkie opcje konfiguracyjne które chcemy zmienić</strong>. Jeśli którejś z opcji nie ujmiemy w indywidualnym .ini będzie ona miała wartość domyślną, taką, jaka jest wkompilowana w php. Czytany jest za to katalog /etc/php/conf.d, przy czym każda zdefiniowana tam opcja konfiguracyjna <strong>nadpisuje</strong> tę zdefiniowaną w indywidualnym .ini.</p>
<p style="text-align: justify;">W PHP 5 ma być możliwość używania w globalnym php.ini wpisów [myhost.com], dzięki czemu będzie można nadpisać globalne ustawienia per vhost. Niestety póki co, trzeba robić kopie globalnego php.ini i zmieniać w niej wybrane opcje. Minimalna postać indywidualnego php.ini, tak, aby zachować najważniejsze spersonalizowane dla dystrybucji ustawienia to:</p>
<pre class="ini"><span style="color: #666666; font-style: italic;">; Safe mode w binarce PHP domyślnie jest on, więc jeśli serwis</span>
<span style="color: #666666; font-style: italic;">; pod nim nie działa trzeba wyłączyć</span>
<span style="color: #000099;">safe_mode </span>=<span style="color: #660066;"> Off</span>
<span style="color: #666666; font-style: italic;">; To warto podać, ograniczymy możliwość otwierania cudzych katalogów</span>
<span style="color: #000099;">open_basedir </span>= <span style="color: #933;">&quot;/home/webhosts/www.mychost.pl:/home/services/httpd:/tmp&quot;</span>
<span style="color: #000099;">include_path </span>=<span style="color: #660066;"> $<span style="">&#123;</span>open_basedir<span style="">&#125;</span></span>
<span style="color: #000099;">error_reporting  </span>=<span style="color: #660066;">  E_ALL &amp; ~E_NOTICE &amp; ~E_STRICT</span>
<span style="color: #000099;">display_errors </span>=<span style="color: #660066;"> Off</span>
<span style="color: #000099;">log_errors </span>=<span style="color: #660066;"> On</span>
<span style="color: #666666; font-style: italic;">; Błedy do sysloga, to php będzie działało z prawami usera, więc nie</span>
<span style="color: #666666; font-style: italic;">; można zapisywać błędów do wspólnego pliku</span>
<span style="color: #000099;">error_log </span>=<span style="color: #660066;"> syslog</span>
<span style="color: #000099;">ignore_repeated_errors </span>=<span style="color: #660066;"> On</span>
<span style="color: #000099;">html_errors </span>=<span style="color: #660066;"> Off</span>
<span style="color: #000099;">upload_tmp_dir </span>= <span style="color: #933;">&quot;/tmp&quot;</span>
<span style="color: #000099;">expose_php </span>=<span style="color: #660066;"> Off</span>
<span style="color: #000099;">memory_limit </span>=<span style="color: #660066;"> 32M</span>
date.<span style="color: #000099;">timezone </span>= <span style="color: #933;">&quot;Europe/Warsaw&quot;</span>
<span style="color: #000099;">browscap </span>=<span style="color: #660066;"> /etc/php/browscap.ini</span></pre>
<h2>Konfiguracja spawn-fastcgi</h2>
<p style="text-align: justify;">Tu sprawa jest dość prosta, otóż spawn-fastcgi nie ma żadych konfigów, a wszystkie parametry przekazujemy w linii poleceń.</p>
<pre class="bash">spawn-fcgi -s /var/run/fastcgi/fcgi.myhost.sock -M <span style="color: #000000;">0660</span> \
  -P /var/run/fastcgi/fcgi.myhost.pid -U http -G http \
  -u <span style="color: #000000;">10012</span> -g <span style="color: #000000;">10012</span> -C <span style="color: #000000;">2</span> -- /usr/sbin/php.fcgi -c /etc/php/webapps.d/myhost.ini</pre>
<p style="text-align: justify;">Po kolei: -s  /var/run/fastcgi/fcgi.myhost.sock mówi w którym miejscu tworzyć sockety serwerów FastCgi. Ja wybrałem sobie katalog /var/run/fastcgi. Należy go utworzyć nadając prawo do zapisu użytkownikowi, z którego prawami będzie działał serwer oraz prawa do odczytu dla serwera Apache (user http). -M 0660 każe zmienić uprawnienia do utworzonego socketa na 660, -P /var/run/fastcgi/fcgi.myhost.pid mówi gdzie zapisujemy plik z PIDem serwera. Parametry -U http -G http są ważne, i mówią że prawa dostępu do socketa mają być nadane dla użytkownika http. Jako że z socketa będzie korzystał serwer Apache zmiana uprawnień jest konieczna. Dalej -u 10012 -g 10012 - tutaj definiujemy id (bądź nazwę) użytkownika i grupy z uprawnieniami którego ma działać FastCgi. Z uprawnieniami tego użytkownika będzie wykonany kod PHP.  Można tu użyć ID'ów użytkowników wirtualnych. Nie muszą być dodani do /etc/passwd. Idealnie to się wpisuje w model hostingu gdzie użytkowników trzymamy w bazie danych bazie danych. Ważną sprawą jest jedynie, aby wirtualny użytkownik miał prawa do zapisu do katalogu na który wskazuje parametr -s. Można mu nadać prawa 777 lub trzymać sockety w katalogach domowych użytkowników.  -C 2 określa ile instancji FastCgi ma zostać uruchomionych. Wartość trzeba dobrać doświadczalnie. W przypadku zbyt małej ilości Apache będzie podawał klientom bład 500. I wreszcie pora na interpreter: -- /usr/sbin/php.fcgi -c /etc/php/webapps.d/myhost.ini - używamy zainstalowanego wcześniej php-fgi - podając mu parametr -c z indywidualnym plikiem konfiguracyjnym. Jeśli nie podamy parametru -c zostanie użyty domyślny /etc/php/php.ini.</p>
<p style="text-align: justify;">Jeden serwer FastCgi może obsługiwać wiele hostów wirtualnych. W najprostszym przypadku  można uruchomić jedną instancję serwera na prawach użytkownika mającego prawa do odczyty dla plików PHP (może to być http) i uruchomić na nim wszystkie nasze vhosty. Przy czym w oczywisty sposób pozbywamy się w takim przypadku korzyści płynących z separacji uprawnień. Przy hostingu wirtualnym lepiej przyjąć strategię: jedna instancja per 1 użytkownik na której odpalamy wszystkie jego vhosty.</p>
<p style="text-align: justify;">W ogóle fajnie jest napisać sobie jakiś rc.skrypt, który będzie uruchamiał wszystkie zdefiniowane instancje podczas startu, pozwoli nam je zresetować, zatrzymać, etc.</p>
<h2>Konfiguracja Apache</h2>
<p style="text-align: justify;">Ok, i teraz Apacz. Wszystko co zostało zrobione do tej pory można bez obaw robić na serwerze który obsługuje PHP via moduł Apacza. Operacje poniżej wymagają już zmiany w konfiguracji serwera WWW, a co za tym idzie są ryzykowne. Główne ryzyko, przy pomyłce w konfiguracji to możliwość zaserwowania niesparsowanych skryptów PHP, tak więc na działających serwerach polecam blokadę dostępu dla virtualki via Order deny, allow Allow from my.ad.re.ss Deny from all. Dodatkowo jak wspomniałem wcześnej model parsowania PHP via moduł jak i FastCgi może współistnieć jednocześnie, tak więc możemy przerzucać na FastCgi pojedyncze virtualki.</p>
<p style="text-align: justify;">Ok, zaczynamy od pliku "/etc/httpd/conf.d/90_mod_fastcgi.conf" . Domyślnie jest tam jedynie linijka ładująca moduł fastcgi. Dopiszmy do pliku:</p>
<pre class="apache">&lt;IfModule mod_fastcgi.c&gt;
  <span style="color: #adadad; font-style: italic;"># Domyślne ustawienia serwera FastCgi, -pass-header Authorization jest bardzo ważne</span>
  FastCgiConfig -idle-<span style="color: #00007f;">timeout</span> <span style="color: #ff0000;">20</span> -maxClassProcesses <span style="color: #ff0000;">1</span> -pass-<span style="color: #00007f;">header</span> Authorization
  <span style="color: #adadad; font-style: italic;"># Zarejestrujmy dwie akcje</span>
  <span style="color: #00007f;">Action</span> php5-fcgi /php-cgi
  <span style="color: #00007f;">Action</span> application/x-fcgi-php /php-cgi
  <span style="color: #adadad; font-style: italic;"># Załóżmy że nasz serwer FastCgi będzie znajdował pod wirtualnym adresem /php-cgi</span>
  &lt;Location <span style="color: #7f007f;">&quot;/php-cgi&quot;</span>&gt;
    php_flag engine <span style="color: #0000ff;">off</span>
    <span style="color: #00007f;">Order</span> <span style="color: #00007f;">Deny</span>,<span style="color: #00007f;">Allow</span>
    <span style="color: #00007f;">Deny</span> <span style="color: #00007f;">from</span> <span style="color: #00007f;">All</span>
    <span style="color: #00007f;">Allow</span> <span style="color: #00007f;">from</span> env=REDIRECT_STATUS
    <span style="color: #00007f;">Options</span> ExecCGI <span style="color: #0000ff;">FollowSymLinks</span>
    <span style="color: #00007f;">SetHandler</span> fastcgi-<span style="color: #00007f;">script</span>
  &lt;/Location&gt;
&lt;/IfModule&gt;</pre>
<p style="text-align: justify;">Ok, to wystarczy, żeby móc przystąpić do konfigurowania vhostów. Do vhosta, dla którego uruchomiona została już instancja spawn-fcgi i mamy utworzony socket w katalogu /var/run/fastcgi/fcgi.myhost.sock dopiszmy:</pre>
<pre class="apache">&lt;VirtualHost www.myhost.pl:<span style="color: #ff0000;">80</span>&gt;
<span style="color: #66cc66;">&#91;</span>...<span style="color: #66cc66;">&#93;</span>
&lt;IfModule mod_fastcgi.c&gt;
<span style="color: #adadad; font-style: italic;"># Tak! wyłączamy engine PHP, dzięki temu moduł PHP, który</span>
<span style="color: #adadad; font-style: italic;"># cały czas działa zostawi pliki PHP tej wirtualki w spokoju</span>
php_flag engine <span style="color: #0000ff;">off</span>
<span style="color: #adadad; font-style: italic;"># Magic! Nadpisujemy handler application/x-httpd-php każąc wszystkim</span>
<span style="color: #adadad; font-style: italic;"># plikom php zdefiniowany wcześniej dla modułu zostać sparsowanym via FastCgi</span>
<span style="color: #00007f;">Action</span> application/x-httpd-php /php-cgi
<span style="color: #adadad; font-style: italic;"># Definicja serwera, ścieżka musi być taka sama jak doc_root vhosta + /php-cgi</span>
<span style="color: #adadad; font-style: italic;"># Nie należy się przejmować faktem, iż /php-cgi nie istnieje w tej ścieżce, tak ma być!</span>
FastCgiExternalServer /home/webhosts/myhost/php-cgi -socket /var/run/fastcgi/fcgi.myhost.sock
&lt;/IfModule&gt;
&lt;/VirtualHost&gt;</pre>
<p>Jeśli mamy jakiekolwiek opcje konfiguracyjne dla php (php_flag, php_admin_value) to należy je usunąć.</p>
<h2>Uruchamiamy!</h2>
<p>Checklist:</p>
<ul>
<li>Sprawdzamy czy  instancja serwera FastCgi uruchomiona przez spawn-cgi działa: ps aux | grep cgi:
<pre>10008   7832  0.0  1.6  71324 34212 ? SN   14:19   0:18 /usr/bin/php.fcgi -c /etc/php/webapps.d/myhost.ini
10008   7833  0.0  1.4  67408 29276 ? SN   14:19   0:19 /usr/bin/php.fcgi -c /etc/php/webapps.d/myhost.ini
http   15808  0.0  0.5  72288 11548 ? SN   20:11   0:00 /usr/sbin/fcgi-pm</pre>
</li>
<li>Sprawdzamy czy jest socket i czy http ma możliwośc odczytu: ls -la /var/run/fastcgi:
<pre>-rw-r--r--  1 root root    4 09-20 14:19 fcgi.myhost.pid
srw-rw----  1 http http    0 09-20 14:19 fcgi.myhost.sock</pre>
</li>
<li>Sprawdzamy, czy w naszym konfigu apacza nie ma błedów: service httpd configtest</li>
</ul>
<p style="text-align: justify;">Pora na restart Apache. Po tym kod PHP dla konfigurowanego vhosta powinien być parsowany via FastCgi, co będzie sygnalozowane w wyniku funkcji phpini() wpisem Server API CGI/FastCGI.</p>
<p style="text-align: justify;">Dla kodu parsowanego via moduł Apache Server API  to Apache Handler.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/09/20/apache-php-fastcgi-spawn-fastcgi-wydajnosc-migracja/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cpuset dla Linux 2.6</title>
		<link>http://www.kurylowicz.info/2009/04/09/cpuset-dla-linux-26/</link>
		<comments>http://www.kurylowicz.info/2009/04/09/cpuset-dla-linux-26/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 06:29:31 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/?p=100</guid>
		<description><![CDATA[Ostatnio, z ciekawości chciałem przetestować sobie Cupset w Linux kernel 2.6. Standardowo pod PLD jest to wkompilowane w Kernel oraz wspierane (mniej więcej) w RC-scripts. Generalnie Cpusets  przydatne jest dla maszyn wieloprocesorowych. Służy do tworzenia wirtualnych procesorów, w których skład może wchodzić dowolna ilość procesorów fizycznych. Następnie, można przypisać wybrany proces do takiego wirtualnego procesora, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Ostatnio, z ciekawości chciałem przetestować sobie Cupset w Linux kernel 2.6. Standardowo pod PLD jest to wkompilowane w Kernel oraz wspierane (mniej więcej) w RC-scripts. Generalnie Cpusets  przydatne jest dla maszyn wieloprocesorowych. Służy do tworzenia wirtualnych procesorów, w których skład może wchodzić dowolna ilość procesorów fizycznych. Następnie, można przypisać wybrany proces do takiego wirtualnego procesora, tak, aby wykonywał się wyłącznie na nim. Potencjalne korzyści wydają się oczywiste:</p>
<ul style="text-align: justify;">
<li>przypisanie zasobów konkretnych procesorów dla wybranych usług, tak aby nie zajmowały sobie wzajemnie czasu procesora, eg. apache + mysql</li>
<li>przypisanie procesów wybranego użytkownika do konkretnego procesora</li>
<li>etc</li>
</ul>
<p style="text-align: justify;">Dla mnie ciekawym wydało się zastosowanie numer 1, z uwagi na fakt, iż mam Apache i MySql na tej samej maszynie. Postanowiłem zatem przypisać obie usługi do osobnych grup procesorów. Jako, iż dysponuje maszyną 2 x Intel(R) XEON(TM) CPU 2.20GHz każdej usłudze przypadło po 1 procesorze.</p>
<p style="text-align: justify;">Ogólne wnioski są takie, ze przy 2 procesorach nie warto. Apache zżera o wiele więcej czasu procesora niż MySQL, co skutkuje ciągłym przeciążeniem jednego procesora, i co za tym idzie obniżeniem wydajności. Procesor przypisany dla MySQL jest obciążany w tym czasie na poziomie 20-40%.</p>
<p style="text-align: justify;">Jedyną korzyścią, jaką widzę w tej konfiguracji, jest to, że przy dużym ruchu, Apache nie zablokuje całkowicie maszyny, ponieważ pozostałe usługi będą mogły wykonać się na mniej obciążonym procesorze.</p>
<p style="text-align: justify;">Przy większej ilości procesorów miało by to być może sensowne zastosowanie. Linki:</p>
<ul style="text-align: justify;">
<li> <a href="http://www.bullopensource.org/cpuset/" target="_blank">http://www.bullopensource.org/cpuset/</a></li>
</ul>
<h2 style="text-align: center;"><span id="more-100"></span><strong>Konfiguracja</strong>:</h2>
<p>/etc/sysconfig/system</p>
<pre class="bash"><span style="color: #808080; font-style: italic;"># Enable cpusets support?</span>
<span style="color: #007800;">CPUSETS=</span>yes</pre>
<p>/etc/sysconfig/cpusets/cpuset-0-httpd</p>
<pre class="bash"><span style="color: #808080; font-style: italic;"># Name of the cpuset</span>
<span style="color: #007800;">NAME=</span>cpuset<span style="color: #000000;">-0</span>-httpd
&nbsp;
<span style="color: #808080; font-style: italic;"># list of CPUs <span style="color: #000000; font-weight: bold;">in</span> that cpuset</span>
<span style="color: #007800;">CPUS=</span><span style="color: #000000;">0</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># list of Memory Nodes <span style="color: #000000; font-weight: bold;">in</span> that cpuset</span>
<span style="color: #007800;">MEMS=</span><span style="color: #000000;">0</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct</span>
<span style="color: #808080; font-style: italic;"># ancestor or descendent, may share any of the same CPUs or Memory Nodes.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># is cpu placement exclusive?</span>
<span style="color: #007800;">CPU_EXCLUSIVE=</span><span style="color: #000000;">1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># is memory placement exclusive?</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">MEM_EXCLUSIVE=</span><span style="color: #000000;">1</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">NOTIFY_ON_RELEASE=</span><span style="color: #000000;">0</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;"># PIDs of tasks <span style="color: #000000; font-weight: bold;">in</span> this cpuset</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">TASKS=</span></span>
&nbsp;
<span style="color: #007800;">ONBOOT=</span>yes</pre>
<p>/etc/sysconfig/cpusets/cpuset-1-mysql</p>
<pre class="bash"><span style="color: #808080; font-style: italic;"># Name of the cpuset</span>
<span style="color: #007800;">NAME=</span>cpuset<span style="color: #000000;">-1</span>-mysql
&nbsp;
<span style="color: #808080; font-style: italic;"># list of CPUs <span style="color: #000000; font-weight: bold;">in</span> that cpuset</span>
<span style="color: #007800;">CPUS=</span><span style="color: #000000;">1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># list of Memory Nodes <span style="color: #000000; font-weight: bold;">in</span> that cpuset</span>
<span style="color: #007800;">MEMS=</span><span style="color: #000000;">0</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct</span>
<span style="color: #808080; font-style: italic;"># ancestor or descendent, may share any of the same CPUs or Memory Nodes.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># is cpu placement exclusive?</span>
<span style="color: #007800;">CPU_EXCLUSIVE=</span><span style="color: #000000;">1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># is memory placement exclusive?</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">MEM_EXCLUSIVE=</span><span style="color: #000000;">1</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">NOTIFY_ON_RELEASE=</span><span style="color: #000000;">0</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;"># PIDs of tasks <span style="color: #000000; font-weight: bold;">in</span> this cpuset</span>
<span style="color: #808080; font-style: italic;">#<span style="color: #007800;">TASKS=</span></span>
&nbsp;
<span style="color: #007800;">ONBOOT=</span>yes</pre>
<p>Później robimy:</p>
<pre class="bash">service cpusets start</pre>
<p>W katalogu /dev/cpusets powinny pojawić sie dwa katalogi, o nazwach takich jakie podano w opcjach NAME. W następnej kolejności przypisujemy usługi do konkretnych Cpusets, defaultowo robi się to w plikach eg. /etc/sysyconfig/httpd dodając rozumianą przez RC-scripts opcję:</p>
<pre class="bash"><span style="color: #007800;">SERVICE_CPUSET=</span><span style="color: #ff0000;">&quot;cpuset-0-httpd&quot;</span></pre>
<p>RC-scripts, przypiszą wtedy podczas startu usługi jej proces do wybranego bpuset. W przypadku MySQL to nie działa, skrypt startowy jest napisany w innej konwencji. W tym przypadku standardowo trzeba dodać do /etc/sysconfig/mysql opcję:</p>
<pre class="bash"><span style="color: #007800;">SERVICE_CPUSET=</span><span style="color: #ff0000;">&quot;cpuset-1-mysql&quot;</span></pre>
<p>i dalej edytować /etc/init.d/mysql, poszukaj poniższy kawałek kodu, i dodaj brakującą linię:</p>
<pre class="bash">        <span style="color: #007800;">pid=</span>$!
&nbsp;
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;$pid&quot;</span> &amp;gt; <span style="color: #ff0000;">&quot;/dev/cpuset/${SERVICE_CPUSET}/tasks&quot;</span>
&nbsp;
        <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">0.1</span>
        mysqlstatus <span style="color: #ff0000;">&quot;$clusterdir&quot;</span> start
        <span style="color: #808080; font-style: italic;"># it takes longer <span style="color: #000000; font-weight: bold;">for</span> mysqld to start and create pidfile <span style="color: #000000; font-weight: bold;">if</span> it has to recover innodb transactions</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;$MYSQL_STATUS&quot;</span> = <span style="color: #ff0000;">&quot;starting&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; the</pre>
<p>Dalej, restart obu usług, cat /dev/cpusets/cpuset-0-httpd/tasks i cat /dev/cpusets/cpuset-1-mysql/tasks - w obu powinny być odpowiednie PIDy procesów, dalej htop i warto sprawdzić, czy faktycznie dany proces trzyma się swojego procesora.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/04/09/cpuset-dla-linux-26/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>
		<item>
		<title>Małe a cieszy: Postfix + SASL + Dovecot</title>
		<link>http://www.kurylowicz.info/2008/12/19/male-a-cieszy-postfix-sasl-dovecot/</link>
		<comments>http://www.kurylowicz.info/2008/12/19/male-a-cieszy-postfix-sasl-dovecot/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 18:57:59 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2008/12/19/male-a-cieszy-postfix-sasl-dovecot/</guid>
		<description><![CDATA[
Podręcznikowa konfiguracja Postfixa z uwierzytelnianiem SASL opiera się na Cyrus SASL. Nie znalazłem nigdzie innego przykładu. A tymczasem można inaczej!  Cyrus ma to do siebie, że jeśli chce się go zmusić do używania bazy SQL i do tego jeszcze szyfrowanych haseł, posługiwać się trzeba w celu rozwiązania tego problemu mechanizmem PAM, a dokładnie pam_mysql. [...]]]></description>
			<content:encoded><![CDATA[<p align="justify">
Podręcznikowa konfiguracja Postfixa z uwierzytelnianiem SASL opiera się na Cyrus SASL. Nie znalazłem nigdzie innego przykładu. A tymczasem można inaczej!  Cyrus ma to do siebie, że jeśli chce się go zmusić do używania bazy SQL i do tego jeszcze szyfrowanych haseł, posługiwać się trzeba w celu rozwiązania tego problemu mechanizmem PAM, a dokładnie pam_mysql. Rozwiązanie podręcznikowe, ale jak dla mnie niezbyt dobre. Sam  Cyrus co prawda potrafi przy pomocy pluginów autoryzować się w bazie SQL, ale jeśli hasło użytkownika jest szyfrowane, jest problem. Tutaj z pomocą przychodzi Dovecot, najczęściej stosowany serwer POP3/IMAP. Otóż zmuszenie go do współpracy z MySQL jest banalnie proste, a dodatkowo, o czym dowiedziałem się dziś zupełnie przypadkowo udostępnia własny mechanizm autoryzacji SASL. Konfiguracja to parę linijek w dovecot.conf i konfigach Postfixa. Małe a cieszy <img src='http://www.kurylowicz.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Linki:</strong></p>
<ul>
<li><a target="_blank" href=" http://wiki.dovecot.org/HowTo/PostfixAndDovecotSASL"> http://wiki.dovecot.org/HowTo/PostfixAndDovecotSASL</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2008/12/19/male-a-cieszy-postfix-sasl-dovecot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Konfiguracja łącza światłowodowego ATM POLPAK pod Linux PLD</title>
		<link>http://www.kurylowicz.info/2008/06/07/konfiguracja-lacza-swiatlowodowego-atm-polpak-pod-linux-pld/</link>
		<comments>http://www.kurylowicz.info/2008/06/07/konfiguracja-lacza-swiatlowodowego-atm-polpak-pod-linux-pld/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 22:08:00 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2008/06/07/konfiguracja-lacza-swiatlowodowego-atm-polpak-pod-linux-pld/</guid>
		<description><![CDATA[Firma ISP dla której od czasu do czasu świadczę usługi postanowiła wykupić nieco szybsze łącze i z uwagi na w sumie niewielki, a właściwie żaden   wybór - padło na Telekomunikację Polską. Interesującą okazała się usługa ATM/Frame relay. Z uwagi na zastosowaną technologie jak i wymagania co do transferu łącze zakończone zostało światłowodem.
Jako zakończenie [...]]]></description>
			<content:encoded><![CDATA[<p>Firma <a href="http://www.e-mactel.com/" target="_blank">ISP</a> dla której od czasu do czasu świadczę usługi postanowiła wykupić nieco szybsze łącze i z uwagi na w sumie niewielki, a właściwie żaden <img src='http://www.kurylowicz.info/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  wybór - padło na Telekomunikację Polską. Interesującą okazała się usługa <a href="http://www.tp.pl/prt/pl/klienci_biz/transmisja_danych/frame_relay/">ATM/Frame relay</a>. Z uwagi na zastosowaną technologie jak i wymagania co do transferu łącze zakończone zostało światłowodem.</p>
<p>Jako zakończenie klienckie użyta została karta <a href="http://www.prosum.net/atmv155_E.html" target="_blank">PROATM-V155FM</a> firmy Prosum. Jest to doskonała <strong>alternatywa</strong> do zastosowań sprzetowych typu <em>Cisco, Nortel</em>, etc, szczególnie jeśli chodzi o cenę. W Polsce koszt zakupu tej karty na chwilę obecną to około 2.500 zł. Tak więc przy koszcie ~3k, bazuąc na Linuxie można uruchomić w pełni funkcjonalny punkt dostępowy obsługujący interfejs ATM, routing, firewall, QOS oraz dodatkowe, przydatne usługi takie jak DHCP, lokalny DNS.</p>
<p>Zasadniczo karta ma wsparcie w postaci natywnie dostarczanych wraz z kernelem sterowników - konfiguracja samego ATM jest wspierana przez kernel i oprogramowanie linux-atm - w <a target="_blank" href="http://www.pld-linux.org/">PLD</a>, którego użyłem jako systemu bazowego - dostępne są nawet rc-scripts które w ładny sposób pozwalają skonfigurować interfejs i resztę rzeczy.</p>
<p>Sama konfiguracja poszła szybko i bezproblemowo - sterownik wykrył kartę bez problemu - skrypty podniosły interfejs - pozostało czekać jedynie na zestawienie łącza.</p>
<p>Niestety po uruchomieniu usługi przez TP sprawa się nieco skomplikowała. Otóż okazało się że całość po prostu nie działa. Po ponad 2 dniowych rozmowach z działem reklamacyjnym POLPAKu skierowano mnie wreszcie do kompetentnej (dziękuję Panie Grzegorzu za okazaną pomoc) osoby, która była mi stanie wyjaśnić mi na czym dokładnie polega problem.</p>
<p>Otóż TP podłącza klientów do dwóch rodzajów przełączników ATM, o ile przełączniki <em>Nortel Passport 4860</em> nie sprawiają większych problemów, o tyle <em>Nortel Passport 15000/20000</em> wymagają komunikacji z użyciem protokołu strict SDH.</p>
<p><span id="more-80"></span>Problem niestety leży w tym, iż sterownik warstwy ATM w linuxie (suni) domyślnie pracuje z użyciem protokołu SONET - starsze przełączniki są to w stanie obsłużyć - nowsze niestety wymagają obsługi SDH.</p>
<p>Po jakimś czasie grzebania w źródłach sterownika karty i sterowniku suni udało mi się zmusić do inicjalizacji domyślnie w trybie SDH co oczywiście poskutkowało natychmiastowym (na wcześniej przygotowanych konfigach) uaktywnieniem łącza.</p>
<p>Ok, jak to zatem wszystko do kupy uruchomić? Otóż na początek należy od TP uzyskać informacje o adresacji, adresie IP przełącznika, oraz VPI/VCI. Warto równe, po to aby uniknąć kłopotów dowiedzieć się do <strong>jakiego przełącznika</strong> jest wpięte zakończenie - szczególnie zaś jakiego protokołu wymaga. Jeśli jest to starszy typ przełącznika Nortel, lub taki który obsłuży protokół SONET całość prawdopodobnie ruszy na domyślnym sterowniku, który jest dostępny w paczce z kernelem PLD. Jeśli przełącznik wymaga SDH lub nie powiedzie sie uruchomienie karty na domyślnym sterowniku niestety czeka cię ręczna kompilacja jądra.</p>
<p>Przed kompilacją jądra pobrać należy <a target="_blank" href="http://www.prosum.net/soft_E.html#proatm">sterowniki dla karty</a>, które znaleźć można na stronie producenta. Po wymianie listów i wskazaniu problemu producent poprawił sterowniki, tak aby inicjowały suni w trybie SDH, tak więc używając obecnie dostępnych sterowników nie musisz grzebać w suni.</p>
<p>W dalszej kolejności pobieramy paczkę ze źródłami kernela oraz wszystko co przyda sie do kompilacji (mam nadzieję że nie pominąłem niczego, część nie podanych tu pakietów doinstaluje sie jako zależności):</p>
<p><code>[root@ozi-x proc]# poldek -i patch gcc make glibc-devel ncurses-devel kernel-sources</code></p>
<p>Lepiej jest użyć gotowej paczki PLD, gdyż te źródła kernela zawierają nałozone już wszystkie przydatne później łaty takie jak IMQ, Layer7, esfq, etc. W dalszej kolejności przekopiować należy pliki z paczki do katalogu drivers/atm, nałożyć patch odpowiedni dla wersji kernela, <strike>wyedytować <em>nicstar.h</em> i uaktywnić opcję NS_SUNI_FULL_SDH </strike> <em>(update: poczytaj dołączony do sterownika plik README, wymuszenie trybu SDH odbywa sie aktualnie poprzez przekazanie parametru  do modułu)</em>, zaznaczyć odpowiednie moduły do kompilacji i skompilować jądro. Zajrzyj do README, który znajdziesz w paczce ze sterownikiem - tam jest opisane które moduły należy zaznaczyć przy kompilacji kernela, którego patcha użyć, etc.</p>
<p>Tutaj jedna uwaga - zmiany w sterowniku, wg. tego co mi napisał producent nie zostały jeszcze przetestowane za switchem SDH tak więc nie ma pewności że działają. Producent prosił mnie o przeprowadzenie testów, niestety w tym momencie nie jestem tego w stanie zrobić. Jeśli z jakiegoś powodu sterownik nadal by nie działał potrzebne jest patchowanie suni.c</p>
<p>Po kompilacji otrzymujemy sterownik <strong>nicstar</strong> - który to najlepiej dopisać do /etc/modules - tak aby się ładował przy starcie.</p>
<p>Sama karta powinna być widoczna via lspci:</p>
<p><code>[root@ozi-x proc]# lspci<br />
[...]<br />
02:08.0 ATM network controller: Integrated Device Technology, Inc. IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller (rev 05)</code></p>
<p>Załadowanie sterownika <strong>nicstar</strong> powinno wrzucić do logu kernela:</p>
<p><code>NET: Registered protocol family 8<br />
NET: Registered protocol family 20<br />
nicstar0: PHY type detection called.<br />
nicstar0: PHY seems to be 155 Mbps.<br />
nicstar0: SRAM size = 512K x 32bit<br />
nicstar0: vpibase=0, vcibase=0, VPM=0x0<br />
nicstar0: MAC address 00:XX:XX:XX:XX:XX</code></p>
<p>Załadowanie sterownika <strong>idt77252</strong> wygląda nieco inaczej:</p>
<p><code>NET: Registered protocol family 8<br />
NET: Registered protocol family 20<br />
idt77252_init: at df80d000<br />
ACPI: PCI Interrupt 0000:02:08.0[A] -&gt; GSI 18 (level, low) -&gt; IRQ 169<br />
idt77252-0: ABR SAR (Rev E): MEM f1000000 SRAM f4000000 [2048 KB]<br />
idt77252-0: Linkrate on ATM line : 149760000 bit/s, 353207 cell/s.</code></p>
<p>W obu przypadkach załadowanie sterownika powinno automatycznie załadować sterowniki atm i suni.</p>
<p>Paczki które należy zainstalować w PLD to:</p>
<p><code>[root@ozi-x proc]# poldek -i linux-atm linux-atm-rc-scripts</code></p>
<p>Następnie wyedytuj plik:</p>
<p><code>[root@ozi-x atm]# cat /etc/sysconfig/atm<br />
ATM=yes<br />
ATM_NICS_NUMBER=1<br />
CLIP=yes<br />
LANE=no<br />
BR2684=no<br />
PPPOA=no<br />
LANE_SERVER_SERVICES=no<br />
ILMI=yes</code></p>
<p>Konfiguracja samego interfejsu powinna wyglądać tak:</p>
<p><code>[root@ozi-x atm]# cat /etc/sysconfig/interfaces/ifcfg-atm0<br />
# ip - adres ip przydzielony przez TP<br />
# gw - adres portu routera brzegowego<br />
DEVICE=atm0<br />
IPADDR=80.50.55.ip<br />
PREFIX=30<br />
ATMARP_REMIP=80.50.55.gw<br />
ATMARP_PVC=0.VPI.VCI<br />
ATMARP_QOS="ubr,aal5:pcr=20000"<br />
DEFAULTHANDLING=yes<br />
ARP=yes<br />
ONBOOT=yes<br />
</code><code>. /etc/sysconfig/network-scripts/ifup-atm.post</code></p>
<p>Uruchom usługę ATM:</p>
<p><code>[root@ozi-x atm]# service atm start</code></p>
<p>I teraz trochę diagnostyki. Użyteczne informacje znajdziesz w /proc/net/atm - w pvc powinieneś zobaczyć wszystkie zestawione kanały PVC - w szczególności ten odpowiadający VPI/VCI twojego łącza:</p>
<p><code>[root@ozi-x atm]# cat /proc/net/atm/pvc<br />
Itf VPI VCI   AAL RX(PCR,Class) TX(PCR,Class)<br />
0   0     5 5         0 UBR         0 UBR<br />
0   0    16 5         0 UBR         0 UBR<br />
0   x   xxx 5         0 UBR         0 UBR   CLIP, Itf:atm0, Encap:LLC/SNAP<br />
</code><br />
0.5 i 0.16 są zestawiane przez atmsigd i ilmi i służą do sterowania sygnalizacją ATM</p>
<p>Dodatkowo używając atmarp możesz sprawdzić czy poprawnie zestawił się CLIP via PVC:</p>
<p><code>[root@ozi-x atm]# atmarp -a<br />
----- Itf 0 (80.50.55.ip, netmask 255.255.255.252) -----<br />
Default QOS: ubr,aal5:max_sdu=9188<br />
IP 80.50.55.gw, state VALID, addr &lt;none&gt;, flags 0x4&lt;PERM&gt;<br />
QOS: ubr,aal5:pcr=20000,max_sdu=9188<br />
0.vpi.vci<br />
Send buffer: 109568<br />
----- Unknown incoming connections -----<br />
----- Incoming unidirectional connections -----<br />
----- End of dump -----<br />
</code><br />
Statystyki ramek ATM pokazuje atmdiag:</p>
<p><code>[root@ozi-x atm]# atmdiag<br />
Itf       TX_okay   TX_err    RX_okay   RX_err    RX_drop<br />
0 AAL0         0         0         0         0         0<br />
AAL5  103087429         0  131246245         0         0</code></p>
<p>W przypadku <strong>pojawienia się problemów</strong> z protokołem SONET/SDH (patrz port switcha ATM i sterownik) interfejs podniesie się bez problemów, otrzymasz również prawidłowe wyniki z atmarp. Zaś admdiag pokaże zmianę liczników TX_okay i <strong>RX_drop</strong>, RX_okay będzie cały czas pokazywało 0. Próbuj w takim przypadku kompilować sterownik ręcznie.</p>
<p>Jeśli wszystko jest prawidłowo, pingując IP portu switcha ATM powinieneś otrzymać odpowiedź. IP switcha oraz twoje IP powinno również odpowiadać na ping z zewnątrz. Tutaj uwaga: jeśli nie podniesiesz interfejsu ATM, lub wystąpią problemy w komunikacji karta-&gt;przełacznik ATM IP portu switcha <strong>nie odpowiada na ping</strong> z zewnątrz.</p>
<p>Po uruchomieniu interfejsu należy ustawić jeszcze domyślną bramę:</p>
<p><code>[root@ozi-x atm]# route del default<br />
[root@ozi-x atm]# route add default gw $ATMARP_REMIP</code></p>
<p>Można do dopisać do <em>/etc/sysconfig/network-scripts/ifup-atm.post</em>, nie ma chyba lepszej metody bo skrypty nie ustawiają domyślnej bramy same.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2008/06/07/konfiguracja-lacza-swiatlowodowego-atm-polpak-pod-linux-pld/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kocham iTVP</title>
		<link>http://www.kurylowicz.info/2008/04/09/kocham-itvp/</link>
		<comments>http://www.kurylowicz.info/2008/04/09/kocham-itvp/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 23:20:38 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Prywatne]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2008/04/09/kocham-itvp/</guid>
		<description><![CDATA[ Jako iż siłą rzeczy przebywam aktualnie za granicą, jedynym kontaktem z informacjami z Polski jest dla mnie Internet. Oczywiście serwisy informacyjne bywają nieocenione - ale czasem człowiek ma ochotę obejrzeć i również nieco ruchomych obrazków w postaci naszych reżymowych wiadomości telewizyjnych. I oto na przeciw wychodzi nam dotowana z naszych publicznych pieniędzy, abonamentu i [...]]]></description>
			<content:encoded><![CDATA[<p><a TITLE="creappy-itvp-via-opera-enjoy.JPG" HREF="http://www.pink.art.pl/wp-content/uploads/creappy-itvp-via-opera-enjoy.JPG"><img ALT="creappy-itvp-via-opera-enjoy.JPG" SRC="http://www.pink.art.pl/wp-content/uploads/creappy-itvp-via-opera-enjoy.thumbnail.JPG" ALIGN="left" /></a> Jako iż siłą rzeczy przebywam aktualnie za granicą, jedynym kontaktem z informacjami z Polski jest dla mnie Internet. Oczywiście serwisy informacyjne bywają nieocenione - ale czasem człowiek ma ochotę obejrzeć i również nieco ruchomych obrazków w postaci naszych reżymowych wiadomości telewizyjnych. I oto na przeciw wychodzi nam dotowana z naszych publicznych pieniędzy, abonamentu i tak dalej TVP, która prowadzi serwis iTVP. Serwis byłby nawet ciekawy, o ile dało by się go oglądać - otóż z niewiadomych przyczyn, choć być może i wiadomych, TVP silnie wspiera poprzez technologie i sposób wykonania monopol  firmy Microsoft. Próbując obejrzeć serwis serwis pod przeglądarką Opera otrzymujemy całkowicie zdeformowany i bezużyteczny kawałek czegoś. Dzięki temu niestety ludze używający na co dzień wyłącznie Opery nie są w stanie uzyskać dostępu do tegoż wspaniałego serwisu.</p>
<p>Oczywiście postanowiłem sprawę w iTVP wyjaśnić - czasem zdarza się jakieś niedopatrzenie podczas zmiany designu. Sam jestem programistą, wiem jak jest. Korzystając zatem z formularza kontaktowego napisałem co następuje:</p>
<p><code>Bosz - patrzal ktos na te strone pod Opera? Jak nie to sprawdzcie ja prosze. Ja wiem ze nei mozna wymagac wodotryskow ktore zapewni jedynie sluszna przegladarka - ale zeby choc sie pod opera cokolwiek pokazywalo i w jakis link dalo sie kliknac to bylo by super.</code></p>
<p>Ku mojej uciesze otrzymałem nawet po 24h odpowiedź, niestety po jej przeczytaniu mina mi lekko zrzedła, oto ona:</p>
<p><code>Witamy Nie sprawdzamy ani nie ustawiamy strony pod Operę. Oprócz "jedynej słusznej przeglądarki" strona świetnie działa także pod Firefoxem.<br />
</code></p>
<p>Czy drodzy Państwo mamy przez to rozumieć, iż dotowana z publicznych pieniędzy iTVP ma w głębokim poważaniu kilkanaście tysięcy użytkowników opery? Czy wreszcie nie świadczy to o 'profesjonalizmie' ekipy tworzącej iTVP? Nie mam pojęcia jak to rozumieć - może następna odpowiedź rozwieje moje wątpliwości - o ile następna odpowiedź się pojawi.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2008/04/09/kocham-itvp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nie pracuj dla korporacji.</title>
		<link>http://www.kurylowicz.info/2008/03/15/nie-pracuj-dla-korporacji/</link>
		<comments>http://www.kurylowicz.info/2008/03/15/nie-pracuj-dla-korporacji/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 22:08:23 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Prywatne]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2008/03/15/nie-pracuj-dla-korporacji/</guid>
		<description><![CDATA[Powszechnie sądzi się, że praca programisty jest pracą twórczą. Pracą na miarę artysty-demiurga, z zamysłem, który oczami wyobraźni widzi i wskazuje palcem co i gdzie. Niestety jest to tylko poniekąd zgodne z prawdą. Programista pracujący na usługach korporacji - z działami analityków biznesowych, z ustalonymi wzorcami, ustabilizowaną platformą softwareową jest tylko wyrobnikiem.
Praca w środowiskach korporacyjnych [...]]]></description>
			<content:encoded><![CDATA[<p>Powszechnie sądzi się, że praca programisty jest pracą twórczą. Pracą na miarę artysty-demiurga, z zamysłem, który oczami wyobraźni widzi i wskazuje palcem co i gdzie. Niestety jest to tylko poniekąd zgodne z prawdą. Programista pracujący na usługach korporacji - z działami analityków biznesowych, z ustalonymi wzorcami, ustabilizowaną platformą softwareową jest tylko wyrobnikiem.</p>
<p>Praca w środowiskach korporacyjnych ma coś z układania klocków z obrazkami. Dostaje się wielką listę klocków, z których można korzystać, obrazek jak nasza konstrukcja ma wyglądać, czas w którym mamy się zmieścić z zakończeniem  prac i zaczyna się zabawę. Przy czym jest tu jeden problem. O ile każdy klocki odpowiadają rysunkowi który mamy, sprawa jest prosta - jeśli jednak nie to mamy dylemat. Można wówczas problem brakującego klocka rozwiązać na dwa sposoby. Zrobić sobie taki klocek, lub wziąć najbardziej podobny do tego z obrazka i tak przerobić aby pasował do całości.</p>
<p>O ile zrobienie nowego klocka, idealnie spełniającego nasze oczekiwania wydaje się rzeczą naturalną, o tyle w przypadku pracy korporacyjnej tak naturalną rzeczą już nie jest. Otóż zrobienie nowego klocka to praca czasochłonna - a tego korporacje nie lubią. Dla tego najczęściej wybiera się opcję drugą.</p>
<p>Przejdźmy do przykładów - otóż załóżmy, że potrzebujemy klocek z obrazkiem portowego nabrzeża. Tymczasem po kilkugodzinnym grzebaniu w pudełku znajdujemy jedynie taki z hawajską plażą. Zgodnie zatem z wytycznymi biznesu przerabiamy go. I tu pojawia się następny problem - otóż klocek z plażą używany jest w dwudziestu innych miejscach i nie może zmienić swojego charakteru. Stawiamy zatem na owej plaży, w sobie tylko znanym miejscu dźwigi portowe i skrupulatnie maskujemy je bambusem i palmami.</p>
<p>I tak oto stajemy się jednym z trybów korporacyjnej maszyny, skierowanej na odtwórczą pracę. Praca w korporacjach Proszę Państwa daje zarobki, praca w korporacjach daje uznanie w oczach innych bo nakierowana jest na interpersonalno-socjalne stosunki. Ale praca w korporacjach dla programisty chcącego się rozwijać nie da satysfakcji. Praca taka to niekończące się pasmo grzebania w pudle z klockami i nieustannego potykania się w najmniej oczekiwanych miejscach o jakieś cholerne żelastwo zamaskowane liśćmi palmowymi.</p>
<p>Nie dziwić się należy zatem, że najlepsi programiści inwestują swój czas w projekty open source które pozwalają się im właściwie rozwijać.</p>
<p>Drugim dnem tego postu jest sprawa architektury platformy w której przyszło nam pracować. Używanie frameworku (to słowo elektryzuje korporacyjnych managerów, gdyż od razu przed oczami mają ilość zaoszczędzonego czasu) ma sens tylko wtedy, jeśli jest on zaprojektowany w sposób na tyle elastyczny, że pozwala na zbudowanie własnej aplikacji bez konieczności modyfikacji samego kodu frameworka. No niestety rzadkość - bo tego typu rzeczy buduje się na zasadzie - co potrzebujemy to wkładamy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2008/03/15/nie-pracuj-dla-korporacji/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
