<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>ITBlog</title>
    <link>http://itblog.grono.net</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>grono.net</description>
    <item>
      <title>Memoize - cichy przyjaciel programisty</title>
      <description>&lt;p align="justify"&gt;Grono generuje wszystkie strony html ca&#322;kowicie dynamicznie. W przeciwie&#324;stwie do innych serwis&#243;w, nie mamy &#380;adnego odwrotnego proxy (reverse proxy). Nie zapami&#281;tujemy w cache wygenerowanych stron, nie zachodzi u nas taka potrzeba. To na czym si&#281; skupiamy, to cache'owanie&lt;sup&gt;1&lt;/sup&gt; surowych informacji pobieranych z bazy danych.&lt;/p&gt;


&lt;img src="http://b62.grono.net/176/184/gallery-46441157-500x500.jpg" alt="Architektura serwisu"&gt;&lt;/img&gt;
  
&lt;p align="justify"&gt;W naszej architekturze zapytanie klienta trafia poprzez &lt;i&gt;Loadbalancer&lt;/i&gt; do serwera, kt&#243;ry generuje stron&#281; html. Te serwery nazywamy &lt;i&gt;Backendami&lt;/i&gt;. Backendy pobieraj&#261; niezb&#281;dne informacje z bazy danych i zwracaj&#261; wynikow&#261; stron&#281; stworzon&#261; dla konkretnego u&#380;ytkownika. &lt;/p&gt;

&lt;p align="justify"&gt;W takiej architekturze baza danych musi obs&#322;u&#380;y&#263; ogromne ilo&#347;ci zapyta&#324;. Aby j&#261; odci&#261;&#380;y&#263; wyniki zapyta&#324; s&#261; zapisywane w cache. Je&#347;li w przysz&#322;o&#347;ci zajdzie potrzeba wykonania takiego samego zapytania, to nie trzeba b&#281;dzie ponownie pyta&#263; bazy. Wystarczy tylko pobra&#263; wynik z cache. Ta technika jest szeroko znana pod nazw&#261; &lt;a href="http://en.wikipedia.org/wiki/Memoization"&gt;Memoization&lt;/a&gt;.&lt;/p&gt;

Rozwa&#380;my najprostszy przyk&#322;ad:
&lt;pre style='color:#000000;background:#ffffff;'&gt;mem_dict &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;span style='color:#800080; '&gt;}&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; add&lt;span style='color:#808030; '&gt;(&lt;/span&gt;a&lt;span style='color:#808030; '&gt;,&lt;/span&gt; b&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    key &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"%r %r"&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;a&lt;span style='color:#808030; '&gt;,&lt;/span&gt;b&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; key &lt;span style='color:#800000; font-weight:bold; '&gt;in&lt;/span&gt; mem_dict&lt;span style='color:#808030; '&gt;:&lt;/span&gt; &lt;span style='color:#696969; '&gt;# mamy zapami&#281;tane?&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; mem_dict&lt;span style='color:#808030; '&gt;[&lt;/span&gt;key&lt;span style='color:#808030; '&gt;]&lt;/span&gt;
 
    val &lt;span style='color:#808030; '&gt;=&lt;/span&gt; a &lt;span style='color:#808030; '&gt;+&lt;/span&gt; b &lt;span style='color:#696969; '&gt;# wylicz warto&#347;&#263;&lt;/span&gt;
    mem_dict&lt;span style='color:#808030; '&gt;[&lt;/span&gt;key&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;span style='color:#808030; '&gt;=&lt;/span&gt; val &lt;span style='color:#696969; '&gt;# zapami&#281;taj&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; val
&lt;/pre&gt;


&lt;p align="justify"&gt;W s&#322;owniku &lt;i&gt;mem_dict&lt;/i&gt; zapami&#281;tywane s&#261; wyniki funkcji. Je&#347;li funkcja b&#281;dzie wywo&#322;ana drugi raz z tymi samymi parametrami, to nie b&#281;dzie konieczne powt&#243;rne wykonywanie oblicze&#324;. Wynik zostanie pobrany ze s&#322;ownika.&lt;/p&gt;

&lt;p align="justify"&gt;W Gronie do przechowywania cache u&#380;ywamy wielu serwer&#243;w &lt;a href="http://www.danga.com/memcached/"&gt;Memcached&lt;/a&gt;. Nasze serwery Memcached s&#261; traktowane przez programist&#281; jako gigantyczny rozproszony s&#322;ownik, w kt&#243;rym dane s&#261; trzymane w pami&#281;ci wielu maszyn.&lt;/p&gt;

&lt;p align="justify"&gt;Stosowanie Memcached to do&#347;&#263; standardowa praktyka. U&#380;ywa go wiele serwis&#243;w, na przyk&#322;ad Facebook.&lt;/p&gt;

&lt;p align="justify"&gt;Jednak standardowy serwer Memcached udost&#281;pnia jedynie podstawowe funkcje, kt&#243;rych trudno jest u&#380;ywa&#263; w naszym &#347;rodowisku. Dlatego stworzyli&#347;my programistyczny interfejs do cache'owania o nazwie &lt;i&gt;Memoize&lt;/i&gt;, kt&#243;ry znacz&#261;co upraszcza u&#380;ywanie cache (jego g&#322;&#243;wnym autorem jest &lt;i&gt;Marek Pu&#322;czy&#324;ski&lt;/i&gt;).&lt;/p&gt;

&lt;p align="justify"&gt;Kolejnym przyk&#322;adem b&#281;dzie funkcja, kt&#243;ra pobiera pewne informacje z bazy danych, na przyk&#322;ad dane u&#380;ytkownika. Standardowo w Django wygl&#261;da&#322;oby to mniej wi&#281;cej tak:&lt;/p&gt;
&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; models &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; User

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; User&lt;span style='color:#808030; '&gt;.&lt;/span&gt;objects&lt;span style='color:#808030; '&gt;.&lt;/span&gt;get&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; user
&lt;/pre&gt;


&lt;p align="justify"&gt;Spr&#243;bujmy u&#380;y&#263; dekoratora Memoize, aby wynik tej funkcji by&#322; pobierany z cache:&lt;/p&gt;
&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; models &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; User
&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; grono2&lt;span style='color:#808030; '&gt;.&lt;/span&gt;contrib&lt;span style='color:#808030; '&gt;.&lt;/span&gt;memoize &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; memoize

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; user_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'model.user.%i'&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;

@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;user_key&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; User&lt;span style='color:#808030; '&gt;.&lt;/span&gt;objects&lt;span style='color:#808030; '&gt;.&lt;/span&gt;get&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; user
&lt;/pre&gt;

&lt;p align="justify"&gt;Funkcja &lt;i&gt;user_key&lt;/i&gt; generuje klucz, pod kt&#243;rym zostanie umieszczony element w cache. Mo&#380;a by przypuszcz&#263;, &#380;e klucz do obiektu mo&#380;na wygenerowa&#263; automatycznie z parametr&#243;w funkcji. Jednak funkcja generuj&#261;ca klucz zosta&#322;a wyodr&#281;bniona, gdy&#380; mo&#380;e zaistnie&#263; przypadek, &#380;e niekt&#243;re parametry cache&#8217;owanej funkcji nie s&#261; jej kluczami g&#322;&#243;wnymi. &lt;/p&gt;

&lt;p align="justify"&gt;Na przyk&#322;ad, poni&#380;szy parametr &lt;i&gt;print_debug&lt;/i&gt; nie wp&#322;ywa w &#380;aden spos&#243;b na stan cache'owanego obiektu, dlatego nie powinien by&#263; brany pod uwag&#281; podczas generowania klucza:&lt;p&gt;
&lt;pre style='color:#000000;background:#ffffff;'&gt;@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;user_key2&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_user_with_warning&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;,&lt;/span&gt; print_debug&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; User&lt;span style='color:#808030; '&gt;.&lt;/span&gt;objects&lt;span style='color:#808030; '&gt;.&lt;/span&gt;get&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; user&lt;span style='color:#808030; '&gt;.&lt;/span&gt;name &lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Jozin"&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;and&lt;/span&gt; print_debug&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Jozin pobrany z bazy."&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; user
&lt;/pre&gt;

&lt;p align="justify"&gt;Jednak co si&#281; stanie, gdy zmienimy co&#347; na obiekcie &lt;i&gt;User&lt;/i&gt;? W cache b&#281;dzie przecie&#380; stara warto&#347;&#263;, wi&#281;c kolejne wywo&#322;ania funkcji b&#281;d&#261; zwraca&#263; niew&#322;a&#347;ciwe stare dane. Dlatego programista musi explicite usun&#261;&#263; (uniewa&#380;ni&#263;, zinwalidowa&#263;) star&#261; warto&#347;&#263; z cache. &lt;/p&gt;

Realizowane jest to nast&#281;puj&#261;co:
&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; grono2&lt;span style='color:#808030; '&gt;.&lt;/span&gt;contrib&lt;span style='color:#808030; '&gt;.&lt;/span&gt;memoize &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; invalidate

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; change_user_name&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;,&lt;/span&gt; new_name&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    user&lt;span style='color:#808030; '&gt;.&lt;/span&gt;name &lt;span style='color:#808030; '&gt;=&lt;/span&gt; new_name
    user&lt;span style='color:#808030; '&gt;.&lt;/span&gt;save&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    invalidate&lt;span style='color:#808030; '&gt;(&lt;/span&gt;user_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#696969; '&gt;# wyczy&#347;&#263; stary cache&lt;/span&gt;
&lt;/pre&gt;

&lt;p align="justify"&gt;Zajmijmy si&#281; trudniejszym przyk&#322;adem, gdzie dwa obiekty po&#322;&#261;czone s&#261; relacj&#261;. Przy zmianie jednego mo&#380;e zaistnie&#263; potrzeba zinwalidowania drugiego. Nasza implementacja &lt;i&gt;Memoize&lt;/i&gt; pozwala na to. &lt;/p&gt;

W tym przyk&#322;adzie niech model &lt;i&gt;Profile&lt;/i&gt; b&#281;dzie powi&#261;zany relacj&#261; z modelem &lt;i&gt;User&lt;/i&gt;:
&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; models &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; User&lt;span style='color:#808030; '&gt;,&lt;/span&gt; Profile 
&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; grono2&lt;span style='color:#808030; '&gt;.&lt;/span&gt;contrib&lt;span style='color:#808030; '&gt;.&lt;/span&gt;memoize &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; memoize

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; user_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'model.user.%i'&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;

@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;user_key&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; User&lt;span style='color:#808030; '&gt;.&lt;/span&gt;objects&lt;span style='color:#808030; '&gt;.&lt;/span&gt;get&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; user


&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; profile_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'model.profile.%i'&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;

@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;profile_key&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_profile&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    p &lt;span style='color:#808030; '&gt;=&lt;/span&gt; Profile&lt;span style='color:#808030; '&gt;.&lt;/span&gt;objects&lt;span style='color:#808030; '&gt;.&lt;/span&gt;get&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    p&lt;span style='color:#808030; '&gt;.&lt;/span&gt;user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; p
&lt;/pre&gt;

&lt;p align="justify"&gt;Jak wida&#263; zmiana w &lt;i&gt;User&lt;/i&gt; musi spowodowa&#263; uniewa&#380;nienie cache obiektu &lt;i&gt;Profile&lt;/i&gt;. Aby to osi&#261;gn&#261;&#263; definiujemy klucz wi&#261;&#380;&#261;cy, u nas nazywany kluczem wersji. Nast&#281;pnie, aby usun&#261;&#263; wszystkie powi&#261;zane rekordy wystarczy jedynie zinwalidowa&#263; ten klucz. &lt;/p&gt;
&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; super_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
  &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"super_key.%d"&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; uid

@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;user_key&lt;span style='color:#808030; '&gt;,&lt;/span&gt; super_key&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
&lt;span style='color:#808030; '&gt;.&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;

@memoize&lt;span style='color:#808030; '&gt;(&lt;/span&gt;profile_key&lt;span style='color:#808030; '&gt;,&lt;/span&gt; super_key&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; get_profile&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
&lt;span style='color:#808030; '&gt;.&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;


&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; change_user_name&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;,&lt;/span&gt; new_name&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    user &lt;span style='color:#808030; '&gt;=&lt;/span&gt; get_user&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    user&lt;span style='color:#808030; '&gt;.&lt;/span&gt;name &lt;span style='color:#808030; '&gt;=&lt;/span&gt; new_name
    user&lt;span style='color:#808030; '&gt;.&lt;/span&gt;save&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    invalidatev&lt;span style='color:#808030; '&gt;(&lt;/span&gt;super_key&lt;span style='color:#808030; '&gt;(&lt;/span&gt;uid&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#696969; '&gt;# usu&#324; powi&#261;zane rekordy z cache&lt;/span&gt;
&lt;/pre&gt;


&lt;p align="justify"&gt;Wygl&#261;da to prosto i intuicyjnie. Jednak g&#322;&#243;wna trudno&#347;&#263; polega na tym, &#380;e dzia&#322;amy w &#347;rodowisku rozproszonym. Jest mo&#380;liwa sytuacja, gdy jeden Backend zmodyfikuje rekord i go usunie z cache, a inny Backend pobierze chwil&#281; wcze&#347;niej star&#261; warto&#347;&#263; i doda j&#261; do cache. Efekt tego b&#281;dzie taki, &#380;e w cache b&#281;dzie przechowywana niepoprawna warto&#347;&#263;. Na szcz&#281;&#347;cie, dzi&#281;ki przemy&#347;lanej implementacji Memoize mamy gwarancj&#281;, &#380;e taka sytuacja nie wyst&#261;pi.&lt;/p&gt;

&lt;p align="justify"&gt;Opisana architektura bardzo dobrze sprawdza si&#281; w praktyce. Serwery Memcached bardzo &#322;atwo si&#281; skaluj&#261;, gdy brakuje nam pami&#281;ci na cache, to po prostu dostawiamy kolejn&#261; maszyn&#281;.&lt;/p&gt;

&lt;p align="justify"&gt;Ciekawskich mo&#380;e zainteresowa&#263; to, &#380;e raz na jaki&#347; czas musimy zrestartowa&#263; serwery Memcached. Zanim cache ponownie zostanie wype&#322;niony danymi mija co najmniej doba.&lt;/p&gt;

&lt;p align="justify"&gt;Z punktu widzenia programisty dekorator Memoize mo&#380;na bardzo prosto stosowa&#263; w praktyce. Nie jest to &#380;adna prze&#322;omowa technologia, lecz &#322;atwo&#347;&#263; w nauce i zastosowaniu powoduje &#380;e nawet m&#322;odsi informatycy mog&#261; pisa&#263; kod, kt&#243;ry b&#281;dzie dzia&#322;a&#322; dla dziesi&#261;tk&#243;w tysi&#281;cy u&#380;ytkownik&#243;w.&lt;/p&gt;

&lt;p align="justify"&gt;Dzi&#281;ki cache'owaniu prawie 99% wszystkich zapyta&#324; nie musi trafi&#263; do bazy. Jednak ca&#322;y czas staramy si&#281; znale&#378;&#263; miejsca, kt&#243;re nie s&#261; poprawnie cache&#8217;owane, aby m&#243;c jeszcze bardziej przyspieszy&#263; serwis i odci&#261;&#380;y&#263; baz&#281; danych.&lt;/p&gt;



&lt;br/&gt;&lt;br/&gt;
&lt;small&gt;
&lt;p align="justify"&gt;&lt;sup&gt;1&lt;/sup&gt;Przepraszam puryst&#243;w j&#281;zykowych za polonizowanie wyrazu cache. Jak to cz&#281;sto w informatyce bywa, nie istnieje jeszcze dobry odpowiednik tego wyrazu w j&#281;zyku polskim. &lt;a href="http://pl.wikipedia.org/wiki/Cache"&gt;Artyku&#322; Wikipedii&lt;/a&gt; sugeruje odmian&#281; z apostrofem i postaram si&#281; tego trzyma&#263;.&lt;/p&gt;

&lt;/small&gt;
</description>
      <pubDate>Wed, 05 Mar 2008 13:00:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:d4c494cd-0f82-46c2-99a4-d0b3ca57f3fa</guid>
      <author>Marek Majkowski</author>
      <link>http://itblog.grono.net/articles/2008/03/05/memoize-cichy-przyjaciel-programisty</link>
      <category>python</category>
      <category>cache</category>
      <trackback:ping>http://itblog.grono.net/articles/trackback/56</trackback:ping>
    </item>
    <item>
      <title>32 czy 64 bity?</title>
      <description>&lt;p style="text-align:justify;"&gt;Parafrazuj&#261;c tytu&#322; jednego z poprzednich post&#243;w, ten powinien brzmie&#263; &amp;#8220;64 bitom m&#243;wimy papa&amp;#8221;.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Nie jest &#380;adn&#261; tajemnic&#261;, &#380;e w Gronie u&#380;ywamy Linuxa. Niczym nowym te&#380; nie jest, &#380;e serwis stoi na frameworku Django. Podobno jeste&#347;my najwi&#281;kszym serwisem u&#380;ywaj&#261;cym tej technologii.&lt;/p&gt;


	&lt;p&gt;Jednak nie dla wszystkich jest jasne jak wygl&#261;da Django od strony serwerowej&amp;#8230;&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Podczas surfowania po Gronie, Twoje &#380;&#261;danie dotycz&#261;ce strony grona (request) trafia do jednego z naszych serwer&#243;w. Nast&#281;pnie serwer przypisuje obs&#322;ug&#281; Twojego requesta jednemu z wielu proces&#243;w Django. Pojedynczy proces generuje stron&#281; Grona, ale mo&#380;e obs&#322;ugiwa&#263; tylko jedno &#380;&#261;danie na raz. Linuxowcy mog&#261; znale&#378;&#263; podobie&#324;stwo
w tym modelu z modelem &amp;#8220;prefork&amp;#8221; z konfiguracji Apache. Po wygenerowaniu strony proces jest zn&#243;w dost&#281;pny i czeka na kolejne klikni&#281;cia u&#380;ytkownik&#243;w.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Wynika z tego, &#380;e na pojedynczym serwerze mo&#380;emy obs&#322;u&#380;y&#263; na raz tylko tyle &#380;&#261;da&#324;, ile mamy uruchomionych proces&#243;w Django&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;. Niestety, pojedynczy proces zu&#380;ywa do&#347;&#263; du&#380;o pami&#281;ci. Aby m&#243;c obs&#322;ugiwa&#263; jak najwi&#281;cej u&#380;ytkownik&#243;w na raz, wypada&#322;oby mie&#263; mo&#380;liwie du&#380;o uruchomionych proces&#243;w. Jednak ich ilo&#347;&#263; jest limitowana wielko&#347;ci&#261; pami&#281;ci operacyjnej.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Aby zwi&#281;kszy&#263; wydajno&#347;&#263; (czyli ilo&#347;&#263; stron kt&#243;re mo&#380;emy wygenerowa&#263;), staramy si&#281; w miar&#281; mo&#380;liwo&#347;ci zmniejsza&#263; wielko&#347;&#263; pojedynczego procesu. W tym celu mo&#380;emy zmniejsza&#263; ilo&#347;&#263; linii kodu lub optymalizowa&#263; zu&#380;ycie pami&#281;ci operacyjnej przez proces. Niestety oba zadania s&#261; bardzo trudne.&lt;/p&gt;


	&lt;p&gt;Ostatnio wpadli&#347;my na inny pomys&#322;.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Nasze serwery u&#380;ywaj&#261; 64 bitowej wersji linuxa. Administratorzy zdecydowali si&#281; na to ju&#380; dawno temu. G&#322;&#243;wnym argumentem by&#322;o to, &#380;e zamierzali&#347;my u&#380;ywa&#263; wi&#281;kszej ilo&#347;ci RAMu ni&#380; 4GB, oraz lepsza wydajno&#347;&#263; tej architektury.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Pad&#322; pomys&#322;, &#380;eby sprawdzi&#263; ile RAMu zaoszcz&#281;dzimy przenosz&#261;c si&#281; na &#8220;stare&#8221; 32 bity. W sumie to w Pythonie ca&#322;kiem sporo pami&#281;ci zaj&#281;tej jest przez wska&#378;niki, a w&#322;a&#347;nie
zmniejszenie jej da&#322;oby najwi&#281;kszy zysk.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;Efekt okaza&#322; si&#281; du&#380;o lepszy ni&#380; przewidywali&#347;my. W pe&#322;ni za&#322;adowany proces Django na 32 bitach zajmuje oko&#322;o 60MB, czyli o 30% mniej ni&#380; na 64 bitach, gdzie jest to 95MB.&lt;/p&gt;


Oto przyk&#322;ad &#8220;topa&#8221; z maszyny 64 bitowej. Kolumna &lt;span class="caps"&gt;RES&lt;/span&gt; pokazuje orientacyjne zu&#380;ycie pami&#281;ci przez proces:
&lt;pre&gt;
VIRT  RES  SHR S %CPU   TIME+  COMMAND
212m  96m 3832 S    0  1:49.61 django '/gallery/3329236/0/'
203m  96m 3120 S    0  1:37.78 django '/gallery/4871149/6/0/'
211m  95m 3832 S    0  1:38.74 django '/mailbox/box/1/'
210m  95m 3824 S    0  1:45.45 django '/gallery/photo/40328359/'
210m  95m 3844 S    0  1:48.43 django '/users/index/'
210m  94m 3848 S    0  1:33.94 django '/users/'
&lt;/pre&gt;

A oto, dla por&#243;wnania, analogiczny z maszyny 32 bitowej:
&lt;pre&gt;
VIRT  RES  SHR S %CPU    TIME+  COMMAND
68396  62m 3484 S    0  2:06.94 django '/users/433317/'
67716  61m 3488 S    0  1:50.23 django '/gallery/photo/42009962/'
66264  60m 3488 S    0  2:01.94 django '/pub/join/'
65312  59m 3484 S    0  2:08.75 django '/users/'
65148  59m 3508 S    0  1:48.02 django '/users/1533943/friendlist/'
64884  59m 3508 S    0  1:51.48 django '/'
&lt;/pre&gt;

	&lt;p style="text-align:justify;"&gt;Podsumowuj&#261;c, mo&#380;emy powiedzie&#263;, &#380;e stosowane 64 bit&#243;w mo&#380;e nie by&#263; takie wspania&#322;e. Architektura x86_64 niew&#261;tpliwie ma wiele zalet, jednak w naszej sytuacji,
gdzie ilo&#347;&#263; zaj&#281;tego RAMu zaczyna mie&#263; znaczenie, zaczynamy odczuwa&#263; jej wady.&lt;/p&gt;


	&lt;p&gt;Teoretycznie, po ca&#322;kowitej migracji na 32 bity byliby&#347;my w stanie obs&#322;ugiwa&#263; o 1/3 wi&#281;cej 
ruchu ni&#380; obecnie. Mamy wi&#281;c o co walczy&#263;.&lt;/p&gt;


&lt;br&gt;
	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; W praktyce nie jest to takie proste, bo mamy tak&#380;e inne ograniczenia, jak na
przyk&#322;ad moc procesora.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Jan 2008 11:19:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:724c4f88-04f5-4cb7-91ff-01de5678854c</guid>
      <author>Marek Majkowski</author>
      <link>http://itblog.grono.net/articles/2008/01/17/32-czy-64-bity</link>
      <category>ciekawostki</category>
      <category>python</category>
      <category>python</category>
    </item>
    <item>
      <title>MySQL' owi m&#243;wimy papa</title>
      <description>&lt;p&gt;Jak zapewne wiadomo Grono.net PostgreSQL&amp;#8217;em stoi. Jedynym kawa&#322;kiem, kt&#243;ry chodzi&#322; na czym&#347; innym (MySQL) by&#322;a baza wiadomo&#347;ci mi&#281;dzy u&#380;ytkownikami.&lt;/p&gt;


	&lt;p&gt;Ostatnio przeprowadzili&#347;my operacj&#281; zmigrowania jej na PostgreSQL. Udan&#261; operacj&#281; :)&lt;/p&gt;


	&lt;p&gt;W chwili obecnej ca&#322;o&#347;&#263; dzia&#322;a ju&#380; na PostgreSQLu, dzia&#322;a &#322;adnie i szybko. Load maszyny z PostgreSQLem jest oko&#322;o &lt;strong&gt;3 krotnie&lt;/strong&gt; ni&#380;szy ni&#380; load maszyny z MySQL&amp;#8217; em (przy tym samym obci&#261;&#380;eniu).&lt;/p&gt;


	&lt;p&gt;Czym si&#281; maszyny r&#243;&#380;ni&#261;? tylko silnikiem bazy danych.&lt;/p&gt;


	&lt;p&gt;Obie s&#261; to dwuprocesorowe xeony 3ghz, z 16GB ramu i macierz&#261; &lt;span class="caps"&gt;RAID10&lt;/span&gt; z 6 dysk&#243;w &lt;span class="caps"&gt;SCSI 72GB&lt;/span&gt; 15k rpm.&lt;/p&gt;


	&lt;p&gt;Wielko&#347;&#263; bazy &amp;#8211; oko&#322;o 60 gigabajt&#243;w w 150 milionach rekord&#243;w (i ro&#347;nie).&lt;/p&gt;


	&lt;p&gt;&#346;redni &amp;#8220;load&amp;#8221; na tej maszynie wynosi ledwie 1.5.&lt;/p&gt;


	&lt;p&gt;Wychodzi na to, &#380;e da si&#281; zrobi&#263; by PostgreSQL by&#322; szybszy i nadal zachowa&#263; pe&#322;n&#261; funkcjonalno&#347;&#263;.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Dec 2007 16:33:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:a3316f10-b098-4800-a78f-22caa5dc5711</guid>
      <author>depesz</author>
      <link>http://itblog.grono.net/articles/2007/12/10/baza1</link>
      <category>ciekawostki</category>
      <category>PostgreSQL</category>
      <category>MySQL</category>
    </item>
    <item>
      <title>Walka ze spamfiltrami</title>
      <description>&lt;p&gt;Zdecydowa&#322;em si&#281; na napisanie tego kr&#243;tkiego tekstu po wielokrotnych pr&#243;bach skutecznego dostarczenia poczty do serwisu pocztowego, kt&#243;rego w&#322;a&#347;cicielem jest pewien &#347;wiatowy potentat z bran&#380;y software. Mowa tu o serwisie hotmail.com i wszystkich przystawkach do niego (live.com, msn.com etc.)&lt;/p&gt;

&lt;p&gt;Na wst&#281;pie warto przytoczy&#263; par&#281; fakt&#243;w.

Whois dla domeny &lt;a href="http://grono.net"&gt;grono.net&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;
[...]
Domain servers in listed order:
      DNS1.GRONO.NET
      DNS2.GRONO.NET
&lt;/pre&gt;

	&lt;p&gt;Odpytanie naszych serwer&#243;w dns o rekordy NS dla strefy grono.net&lt;/p&gt;


&lt;pre&gt;
mieki@mieki-laptop:~$ host -t ns grono.net dns1.grono.net
Using domain server:
Name: dns1.grono.net
Address: 193.33.58.3#53
Aliases: 

grono.net name server dns1.grono.net.
grono.net name server dns2.grono.net.
&lt;/pre&gt;

oraz:
&lt;pre&gt;
mieki@mieki-laptop:~$ host -t ns grono.net dns2.grono.net
Using domain server:
Name: dns2.grono.net
Address: 193.33.58.4#53
Aliases: 

grono.net name server dns2.grono.net.
grono.net name server dns1.grono.net.

&lt;/pre&gt;

&lt;p&gt;Czyli jak wida&#263;, delegacja na nasze serwery jest zrobiona w spos&#243;b poprawny.
Serwis grono.net posiada przyznan&#261; przez &lt;a href="http://en.wikipedia.org/wiki/RIPE"&gt;&lt;span class="caps"&gt;RIPE&lt;/span&gt;&lt;/a&gt; klas&#281; adres&#243;w 193.33.59.0/23. Jest to pula &lt;a href="http://en.wikipedia.org/wiki/Provider_Independent_Address_Space"&gt; PI&lt;/a&gt; i rozg&#322;aszamy j&#261; z naszego routera (&lt;a href="http://www.ripe.net/fcgi-bin/whois?form_type=simple&amp;#38;full_query_string=&amp;#38;searchtext=AS42782&amp;#38;submit.x=17&amp;#38;submit.y=15&amp;#38;submit=Search"&gt;&lt;span class="caps"&gt;AS42782&lt;/span&gt;&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;Jak wiadomo, powszechnym problemem w sieci internet jest wsz&#281;dobylski spam. Wiadomo&#347;ci o tre&#347;ci reklamowej na przyk&#322;ad o powi&#281;kszaniu pewnej cz&#281;&#347;ci cia&#322;a. Najcz&#281;&#347;ciej s&#261; rozsy&#322;ane z zainfekowanych wirusami (lub koniami troja&#324;skimi) komputer&#243;w. Posiadacze zara&#380;onego peceta nie s&#261; &#347;wiadomi, &#380;e mog&#261; rozsy&#322;a&#263; kilkaset maili na sekund&#281;. Odbiorcami spamu s&#261; maile u&#380;ytkownik&#243;w, zbierane do bazy przez spam-harvestery (czyli takie skrypty, monitoruj&#261;ce witryny webowe, grupy dyskusyjne i inne zasoby sieci w poszukiwaniu prawid&#322;owych adres&#243;w email), a tak&#380;e pobierane s&#261; z ksi&#261;&#380;ek adresowych popularnych program&#243;w pocztowych na zainfekowanych komputerach.&lt;/p&gt;
&lt;p&gt;Protok&#243;&#322; przesy&#322;ania poczty (&lt;a href="http://en.wikipedia.org/wiki/SMTP"&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt;&lt;/a&gt;) zosta&#322; zaprojektowany we wczesnych latach osiemdziesi&#261;tych XX wieku i praktycznie w niezmienionej formie pozosta&#322; do dzi&#347;. Ma on szereg b&#322;&#281;d&#243;w, kt&#243;rych istnienie mo&#380;na by&#322;o przewidzie&#263; ju&#380; na poziomie projektowania samego protoko&#322;u. Jednym z powa&#380;niejszych z nich jest mo&#380;liwo&#347;&#263; podszywania si&#281; pod nadawc&#281;. Do tego mo&#380;na u&#380;y&#263; zwyk&#322;ego programu telnet i udawa&#263; klienta pocztowego.&lt;/p&gt;

	&lt;p&gt;Poni&#380;ej zaprezentowa&#322;em pr&#243;b&#281; wys&#322;ania poczty z konta na nieistniej&#261;cej domenie:&lt;/p&gt;


&lt;pre&gt;
mieki@mieki-laptop:~$ telnet mx.grono.net 25
Trying 193.33.58.136...
Connected to mx.grono.net.
Escape character is '^]'.
220 dakota.nemo.pl Microsoft ESMTP MAIL Service, Version: 6.0.3790.3959 ready at  Thu, 4 Oct 2007 23:51:24 +0200 
ehlo jakasdomena.pl
250-dakota.nemo.pl Hello [82.210.166.16]
250-TURN
250-SIZE
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-TLS
250-STARTTLS
250-X-EXPS GSSAPI NTLM LOGIN
250-X-EXPS=LOGIN
250-AUTH GSSAPI NTLM LOGIN
250-AUTH=LOGIN
250-X-LINK2STATE
250-XEXCH50
250 OK
mail from: piotr@jakasdomena.pl
250 2.1.0 piotr@jakasdomena.pl....Sender OK
rcpt to: p.milczarek@grono.net
250 2.1.5 p.milczarek@grono.net 
data
354 Start mail input; end with &amp;lt;CRLF&amp;gt;.&amp;lt;CRLF&amp;gt;
From: Piotr Z JakiejsDomeny &amp;lt;piotr@jakasdomena.pl&amp;gt;
Subject: Przyk&#322;adowa wiadomosc          

Tutaj tresc wiadomosci, czy to dojdzie ?

.
250 2.6.0 &amp;lt;DAKOTAogkJXrRjbDt3H000001ad@dakota.nemo.pl&amp;gt; Queued mail for delivery
quit
221 2.0.0 dakota.nemo.pl Service closing transmission channel
Connection closed by foreign host.
&lt;/pre&gt;

Dopiero po zajrzeniu w nag&#322;&#243;wki mo&#380;emy stwierdzi&#263;, &#380;e pole From jest sfa&#322;szowane. 
&lt;pre&gt;
Received: from jakasdomena.pl ([82.210.166.16]) by dakota.nemo.pl with Microsoft SMTPSVC(6.0.3790.3959);
         Thu, 4 Oct 2007 23:52:26 +0200

&lt;/pre&gt;
podczas gdy:

&lt;pre&gt;
mieki@mieki-laptop:~$ host jakasdomena.pl
jakasdomena.pl has address 83.133.126.177
jakasdomena.pl mail is handled by 0 jakasdomena.pl.
&lt;/pre&gt;

	&lt;p&gt;Czyli host 82.210.166.16 nie jest ani wpisem &lt;span class="caps"&gt;IN A&lt;/span&gt; dla jakasdomena.pl, ani wpisem MX w tej domenie (wyb&#243;r domeny by&#322; ca&#322;kowicie przypadkowy).&lt;/p&gt;


	&lt;p&gt;Aby zapobiec procederom tego typu jak powy&#380;szy, w Kwietniu 2006 powsta&#322; dokument &lt;a href="http://tools.ietf.org/html/rfc4408"&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt;&lt;/a&gt; opisuj&#261;cy jak definiowa&#263; na serwerach dns rekordy dotycz&#261;cych uprawnie&#324; wysy&#322;ania poczty.&lt;/p&gt;


	&lt;p&gt;Typ rekordu, w jakim definiujemy kt&#243;re serwery mog&#261; rozsy&#322;a&#263; poczt&#281; z danej domeny, a kt&#243;re nie, to &lt;span class="caps"&gt;TXT&lt;/span&gt;. Przyk&#322;adowy rekord dla przyk&#322;adowej domeny &lt;a href="http://grono.net"&gt;grono.net&lt;/a&gt; :-)&lt;/p&gt;


&lt;pre&gt;
mieki@mieki-laptop:~$ host -t txt grono.net
grono.net descriptive text "v=spf1 +ip4:193.33.58.0/23 -all" // o tym teraz
grono.net descriptive text "spf2.0/mfrom,pra +ip4:193.33.58.0/23 -all" // natomiast o tym troche p&#243;&#378;niej
&lt;/pre&gt;

	&lt;p&gt;Ten rekord oznacza deklaracje mechanizmu Sender Policy Framework dla domeny grono.net. Pierwszym elementem rekordu &lt;span class="caps"&gt;SPF&lt;/span&gt; jest deklaracja wersji czyli &lt;code&gt;"v=spf1"&lt;/code&gt;, nast&#281;pnie wyst&#281;puje lista element&#243;w dla kt&#243;rych ustalamy polityk&#281; rozsy&#322;ania poczty.&lt;/p&gt;


Ka&#380;dy taki element sk&#322;ada si&#281; z kilku cz&#281;&#347;ci.
Cz&#281;&#347;&#263; pierwsza &amp;#8211; kwalifikator &amp;#8211; jest to ma&#322;y znaczek od kt&#243;rego zaczyna si&#281; element, wskazuj&#261;cy co zrobi&#263; z poczt&#261; przychodz&#261;c&#261; od danego &lt;cite&gt;elementu&lt;/cite&gt;. Wszystkie poni&#380;sze elementy przedstawi&#322;em w maksymalnym uproszczeniu:
&lt;ul&gt;
 &lt;li&gt; &amp;#8221;+&amp;#8221; &amp;#8211; whitelisting &amp;#8211; czyli bezwarunkowe zaakceptowanie poczty i oznaczenie jej jako nie &lt;span class="caps"&gt;SPAM&lt;/span&gt;&lt;/li&gt;
 &lt;li&gt; &amp;#8221;-&amp;#8221; &amp;#8211; blacklisting &amp;#8211; oznaczenie poczty jako niechciana/niepo&#380;&#261;dana&lt;/li&gt;
 &lt;li&gt; &amp;#8221;&amp;tilde;&amp;#8221; &amp;#8211; greylisting &amp;#8211; w skr&#243;cie: zastosuj swoje mechanizmy filtrowania poczty i detekcji spamu&lt;/li&gt;
&lt;/ul&gt;
Istnieje jeszcze kwalifikator &amp;#8221;?&amp;#8221;, kt&#243;ry dzia&#322;a podobnie do &amp;#8221;&amp;tilde;&amp;#8221;, ale nie b&#281;dziemy si&#281; zag&#322;&#281;bia&#263; w szczeg&#243;&#322;y.

Cz&#281;&#347;&#263; druga &amp;#8211; typ obiektu:
&lt;ul&gt;
 &lt;li&gt; &amp;#8220;a&amp;#8221; &amp;#8211; rekord &lt;span class="caps"&gt;IN A&lt;/span&gt; w danej domenie np +a &amp;#8211; oznacza deklaracje o wysy&#322;aniu poczty z rekordu (b&#261;d&#378; rekord&#243;w) &lt;span class="caps"&gt;IN A&lt;/span&gt; dla samej domeny&lt;/li&gt;
 &lt;li&gt; &amp;#8220;ip4&amp;#8221; &amp;#8211; oznacza zakres host&#243;w przedstawiony w postaci &lt;span class="caps"&gt;CIDR&lt;/span&gt;, b&#261;d&#378; jeden host bez maski podsieci np. -ip4:193.33.58.0/23&lt;/li&gt;
 &lt;li&gt; &amp;#8220;mx&amp;#8221; &amp;#8211; oznacza wpis lub wpisy mx w danej domenie, na przyk&#322;ad -mx oznacza deklaracje, &#380;e z serwer&#243;w pocztowych nie rozsy&#322;amy poczty :&amp;gt;&lt;/li&gt;
 &lt;li&gt; &amp;#8220;all&amp;#8221; &amp;#8211; oznacza wszystkie inne niezdefiniowane w &lt;span class="caps"&gt;SPF&lt;/span&gt;&lt;/li&gt;

	&lt;p&gt;Cz&#281;&#347;&#263; trzecia (opcjonalna) &amp;#8211; warto&#347;&#263; parametru:
        W przypadku domeny grono.net u&#380;yty tylko raz &amp;#8211; chodzi o &amp;#8220;193.33.58.0/23&amp;#8221; &amp;#8211; czyli klas&#281; adres&#243;w IP kt&#243;r&#261; posiada Grono.net&lt;/p&gt;


&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;&lt;span class="caps"&gt;SPF&lt;/span&gt;&lt;/a&gt; przyj&#261;&#322; si&#281; jako standard je&#380;eli chodzi o polityk&#281; rozsy&#322;ania poczty. Jednak&#380;e istnieje sobie firma na &#347;wiecie o nazwie Microsoft, kt&#243;ra stwierdzi&#322;a, &#380;e stworzy sw&#243;j w&#322;asny mechanizm polityki walki z poczt&#261; &amp;#8211; SenderID. Do deklaracji tego mechanizmu s&#322;u&#380;y w&#322;a&#347;nie drugi rekord &lt;span class="caps"&gt;TXT&lt;/span&gt;. &lt;/p&gt;

	&lt;p&gt;Niestety, portale o kt&#243;rych wspomnia&#322;em na samym pocz&#261;tku wykorzystuj&#261; t&#281; drug&#261; technologi&#281;.(Nie wnikam ju&#380; kto jest rzeczonych serwis&#243;w). &lt;a href="http://en.wikipedia.org/wiki/Sender_ID"&gt;SenderID&lt;/a&gt; nie wnosi tak naprawd&#281; nic wi&#281;cej do walki ze spamem ni&#380; &lt;span class="caps"&gt;SPF&lt;/span&gt; (nawet sk&#322;adnia jest identyczna je&#380;eli chodzi o deklaracje obiekt&#243;w). Faktem jest, &#380;e wprowadza bardziej szczeg&#243;&#322;owe sprawdzanie nag&#322;&#243;wk&#243;w kt&#243;re pojawiaj&#261; si&#281; w poczcie (&lt;code&gt;From:&lt;/code&gt; i &lt;code&gt;Return Ptah:&lt;/code&gt;), oraz tego co jest podawane po &lt;code&gt;HELO/EHLO&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Niestety po mimo zastosowania si&#281; do rad potentata z Redmond, nie ma skutecznego sposobu na dostarczenie poczty do adresata, kt&#243;ry ma konto przyk&#322;adowo na serwisie &lt;a href="http://hotmail.com"&gt;hotmail.com&lt;/a&gt;.&lt;/p&gt;


Po d&#322;ugich i mozolnych testach uda&#322;o nam si&#281; zaobserwowa&#263; 2 zachowania serwisu:
&lt;ol&gt;
&lt;li&gt;Poczta l&#261;duje w folderze Junk, z kt&#243;rego jest automagicznie wywalana po 10 dniach&lt;/li&gt;
&lt;li&gt;Poczta wcale nie dociera do adresata.&lt;/li&gt;
&lt;/ol&gt;
W jednym i drugim przypadku serwer smtp hotmaila zwraca:

&lt;pre&gt;250 &amp;lt;BAY0-MC10-F5snIXriu0001e384@bay0-mc10-f5.bay0.hotmail.com&amp;gt; Queued mail for delivery&lt;/pre&gt;

&lt;p&gt;Je&#380;eli poczta wpadnie do folderu junk i sprytny u&#380;ytkownik j&#261; oznaczy, &#380;e spamem nie jest(kliknie w &amp;#8220;znam nadawc&#281;&amp;#8221;), kolejna poczta od tego adresata (z tego samego serwera pocztowego), nie jest wrzucana do folderu &amp;#8220;Junk&amp;#8221; ... ale tylko przez ok. tydzie&#324;.&lt;/p&gt;

&lt;p&gt;Po przewertowaniu zasob&#243;w Usenetu jestem w stanie wysnu&#263; tez&#281;, i&#380; serwery stosuj&#261;ce technologi&#281; SenderID zachowuj&#261; si&#281; zgo&#322;a niedeterministycznie, albo rz&#261;dzi nimi jaka&#347; mroczna logika rozmyta, do kt&#243;rej zwyk&#322;y &#347;miertelnik nie ma dost&#281;pu. Na domiar tego dodam, i&#380; ta cudowna technologia jest opatentowana oraz jej nie mo&#380;na stosowa&#263; bez zgody Microsoftu. Pr&#243;by kontaktu z kim&#347; ze strony MS s&#261; z g&#243;ry skazane na niepowodzenie. Na maile odpowiadaj&#261; automaty, albo nic nie odpowiada (w sumie nie dziwne, mo&#380;e im kto&#347; problem zg&#322;asza&#322;, &#380;e im nie dzia&#322;a poczta jak powinna &amp;#8211; drog&#261; w&#322;a&#347;nie pocztow&#261;). Po kilku telefonach do MS w pi&#281;knym kraju nad Wis&#322;&#261; nie uda&#322;o si&#281; znale&#378;&#263; osoby kompetentnej, kt&#243;ra by podpowiedzia&#322;a jak w/w problem rozwi&#261;za&#263;. Nawet wi&#281;cej, nie uda&#322;o si&#281; znale&#378;&#263; osoby, kt&#243;ra potrafi skontaktowa&#263; z person&#261; kompetentn&#261; w dziedzinie SenderID.&lt;/p&gt;

&lt;p&gt;Dla ciekawskich dodam, i&#380; by&#322;y zmieniane TTLe rekord&#243;w w dnsach, oraz wpisy &lt;span class="caps"&gt;PTR&lt;/span&gt; serwer&#243;w dns i pocztowych, z kt&#243;rych chcemy co&#347; skutecznie dostarczy&#263; do hotmaila &amp;#8211; efekt zawsze ten sam. Zrobili&#347;my to ju&#380; na wszystkie mo&#380;liwe sposoby &amp;#8211; zagl&#261;daj&#261;c nawet do nag&#322;&#243;wk&#243;w, poczty kt&#243;ra do hotmaila jakim&#347; cudem dotar&#322;a.&lt;/p&gt;

	&lt;p&gt;My chcemy tylko powiadomi&#263; o urodzinach znajomego&amp;#8230; a nie powi&#281;kszy&#263; pewn&#261; cz&#281;&#347;&#263; cia&#322;a.&lt;/p&gt;


	&lt;p&gt;Dla cierpliwych i szukaj&#261;cych wra&#380;e&#324; opis jak dzia&#322;a (albo jak powinno dzia&#322;a&#263;) SenderID mo&#380;na znale&#378;&#263; tutaj: &lt;a href="http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx"&gt;http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Fri, 30 Nov 2007 15:38:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:ba6ffaa5-add6-47cb-b808-0db50851e6be</guid>
      <author>mieki</author>
      <link>http://itblog.grono.net/articles/2007/11/30/walka-ze-spamfiltrami</link>
      <category>ciekawostki</category>
      <category>SPF</category>
      <category>SenderID</category>
      <category>SMTP</category>
      <category>SPAM</category>
      <category>filtering</category>
    </item>
    <item>
      <title>Co to jest &amp;lt;i&amp;gt;widget&amp;lt;/i&amp;gt;?</title>
      <description>&lt;p&gt;Oryginalnie, s&#322;owo &lt;em&gt;widget&lt;/em&gt; oznacza&#322;o element graficznego interfejsu u&#380;ytkownika. Dzi&#347; u&#380;ywamy ich wsz&#281;dzie &amp;#8211; s&#261; to pola wpisywania tekstu, listy z kt&#243;rych wybieramy pozycje, pola do zaznaczania opcji, suwaki, opuszczane menu itp. Pierwsze u&#380;ycie s&#322;owa widget w tym kontek&#347;cie datuje si&#281; na lata 80te.&lt;/p&gt;


	&lt;p&gt;Dzisiaj, o ile nadal w dziedzinie interakcji z u&#380;ytkownikiem, s&#322;owo &lt;em&gt;widget&lt;/em&gt; oznacza konstrukcje bardziej skomplikowane. W najog&#243;lniejszym znaczeniu, widget to graficzny element pozwalaj&#261;cy zrealizowa&#263; jakie&#347; funkcje lub prezentuj&#261;cy informacje. Przyk&#322;adem najprostszego widgeta jest zegarek w pasku zada&#324; na dole ekranu. Prezentuje bie&#380;&#261;cy czas oraz dat&#281; i pozwala na wykonanie kilku zwi&#261;zanych z tym czynno&#347;ci &#8211; mo&#380;emy ustawi&#263; godzin&#281;, dzie&#324;, miesi&#261;c, zmieni&#263; stref&#281; czasow&#261;, obejrze&#263; ca&#322;y kalendarz.&lt;/p&gt;


	&lt;p&gt;Ta definicja nie m&#243;wi nic o &#347;rodowisku, w kt&#243;rym widget jest prezentowany. Mo&#380;e by&#263; to zatem pulpit systemu operacyjnego, okno jakiego&#347; programu, a nawet strona internetowa. Typowe widgety prezentuj&#261; informacj&#281; w spos&#243;b ci&#261;g&#322;y, nie wymagaj&#261;c akcji ze strony u&#380;ytkownika. Je&#347;li zajrzymy do historii &amp;#8211; w 1996 roku Microsoft wypu&#347;ci&#322; zestaw &lt;a href="http://en.wikipedia.org/wiki/Microsoft_PowerToys#Windows_95_PowerToys"&gt;Power Toys&lt;/a&gt;, kt&#243;ry prezentowa&#322; zaawansowane mo&#380;liwo&#347;ci systemu Windows 95. Jednym z element&#243;w zestawu by&#322; program prezentuj&#261;cy czas, czyli zegar. Nowo&#347;ci&#261; by&#322; fakt, &#380;e &#243;w zegar nie mia&#322; prostok&#261;tnego okna i dzi&#281;ki temu wpasowywa&#322; si&#281; doskonale w ka&#380;dy pulpit. Mo&#380;emy wi&#281;c uzna&#263; go za wczesny przyk&#322;ad widgeta. Rok p&#243;&#378;niej, ta sama firma wypu&#347;ci&#322;a przegl&#261;dark&#281; Internet Explorer 4, a razem z ni&#261; funkcj&#281; &lt;a href="http://en.wikipedia.org/wiki/Active_Desktop"&gt;Active Desktop&lt;/a&gt;. Dzi&#281;ki niej pulpit stawa&#322; si&#281; hybryd&#261; klasycznego pulpitu oraz strony internetowej. Mo&#380;na by&#322;o na nim umieszcza&#263; fragmenty kodu, kt&#243;re prezentowa&#322;y np. kursy akcji, pogod&#281; czy na &#380;ywo, obliczane pozycje satelit&#243;w na orbicie Ziemi. Znowu &amp;#8211; widgety.&lt;/p&gt;


	&lt;p&gt;Dzi&#347; widgety obs&#322;ugiwane s&#261; przez wiele platform &amp;#8211; zar&#243;wno system&#243;w operacyjnych, program&#243;w jak i stron internetowych. Sztandarowym przyk&#322;adem pierwszego jest najnowszy Windows Vista, kt&#243;ry obs&#322;uguje widgety, nazwane tam &lt;em&gt;gadgetami&lt;/em&gt;, na pulpicie oraz w pasku bocznym (&lt;a href="http://www.microsoft.com/windows/products/windowsvista/features/details/sidebargadgets.mspx"&gt;Sidebar&lt;/a&gt;). Inne systemy operacyjne i &#347;rodowiska r&#243;wnie&#380; obs&#322;uguj&#261; widgety, wed&#322;ug tej definicji &amp;#8211; w Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; mamy &lt;a href="http://www.apple.com/downloads/dashboard/"&gt;Dashboard&lt;/a&gt;, w Linuksie jest to &lt;a href="http://netdragon.sourceforge.net/ssuperkaramba.html"&gt;SuperKaramba&lt;/a&gt; lub &lt;a href="http://www.gdesklets.de/"&gt;gDesklets&lt;/a&gt;, zale&#380;nie od u&#380;ywanego &#347;rodowiska graficznego. We wcze&#347;niejszych wersjach Windowsa mo&#380;emy u&#380;ywa&#263; Kapsules, &lt;a href="http://www.klipfolio.com/"&gt;Klipfolio&lt;/a&gt; (gdzie widgety nazywane s&#261; Klips), albo &lt;a href="http://desktop.google.com/"&gt;Google Desktop&lt;/a&gt;. Ten ostatni funkcjonuje r&#243;wnie&#380; pod Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; i Linuksem.&lt;/p&gt;


	&lt;p&gt;Je&#347;li chodzi o aplikacje, to na pierwszym miejscu wymieni&#263; nale&#380;y przegl&#261;dark&#281; &lt;a href="http://widgets.opera.com/"&gt;Opera&lt;/a&gt;, kt&#243;ra posiada ju&#380; du&#380;y zestaw widget&#243;w, oraz Firefoxa, kt&#243;ry poprzez rozszerzenie Firefoxit obs&#322;uguje &lt;em&gt;widgety&lt;/em&gt; w spos&#243;b zbli&#380;ony do wymienionego wcze&#347;niej Dashboarda. Inne rozszerzenia do Firefoxa r&#243;wnie&#380; mog&#261; by&#263; zakwalifikowane jako widgety &#8211; np. prezentuj&#261;ce pogod&#281;, najnowsze wiadomo&#347;ci z &lt;span class="caps"&gt;RSS&lt;/span&gt;, czy ranking ogl&#261;danej strony w pasku statusu.&lt;/p&gt;


	&lt;p&gt;Na stronach www, dawno temu &#8222;bajerem&#8221; by&#322; zegarek w tek&#347;cie strony lub w pasku statusu, zrealizowany Javascriptem. Kwalifikuje si&#281; jako prosty widget. Dzi&#347; te s&#261; bardziej rozbudowane &amp;#8211; cz&#281;sto w technologii Flash. Mo&#380;na na swojej stronie czy blogu umie&#347;ci&#263; gierki, graficzne zegarki, swoje najnowsze filmy wgrane na kt&#243;ry&#347; z serwis&#243;w. Mo&#380;na pozwoli&#263; u&#380;ytkownikom na zostawianie komentarzy g&#322;osowych, wy&#347;wietli&#263; sw&#243;j kalendarz, &lt;a href="http://www.widgetbox.com/widget/skype"&gt;status w Skype&lt;/a&gt;, umie&#347;ci&#263; quiz, rozmawia&#263; przez komunikatory albo ca&#322;y sw&#243;j blog zamieni&#263; w widget kt&#243;ry inni mog&#261; wstawi&#263; u siebie.&lt;/p&gt;


	&lt;p&gt;Istniej&#261; te&#380; strony internetowe b&#281;d&#261;ce swego rodzaju agregatorami widget&#243;w. U&#380;ytkownik mo&#380;e sam skomponowa&#263; stron&#281;, sk&#322;adaj&#261;c&#261; si&#281; z wybranych element&#243;w, np. czytnik&#243;w wiadomo&#347;ci &lt;span class="caps"&gt;RSS&lt;/span&gt; z r&#243;&#380;nych &#378;r&#243;de&#322;, swoim kalendarzem czy podgl&#261;dem poczty. Takimi miejscami s&#261; &lt;a href="http://www.google.com/ig"&gt;iGoogle&lt;/a&gt;, &lt;a href="http://www.netvibes.com/"&gt;Netvibes&lt;/a&gt;, &lt;a href="http://www.pageflakes.com/"&gt;Pageflakes&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Wszystkie wymienione wy&#380;ej kategorie s&#261;, w ramach &lt;a href="/articles/2007/10/03/widget"&gt;konkursu&lt;/a&gt;, widgetami. Akceptujemy wi&#281;c bardzo szeroki zakres prac, pod wiele platform i &#347;rodowisk, daj&#261;c wiele mo&#380;liwo&#347;ci w wykazaniu si&#281; umiej&#281;tno&#347;ciami oraz pomys&#322;em. Regulamin okre&#347;la, &#380;e najwa&#380;niejszymi kryteriami b&#281;dzie funkcjonalno&#347;&#263; i stopie&#324; wykorzystania zasob&#243;w Grona. Stawia za to niewiele ogranicze&#324; co do techniki realizacji projektu, zostawiaj&#261;c ogromne pole do popisu.&lt;/p&gt;


	&lt;p&gt;Wi&#281;cej informacji o konkursie na &lt;a href="http://apidoc.grono.net/articles/2007/10/02/widget"&gt;apidoc.grono.net&lt;/a&gt;, znajdziecie tam r&#243;wnie&#380; dokumentacj&#281; udost&#281;pnionych funkcji, przyk&#322;adowy kod pokazuj&#261;cy jak z nich korzysta&#263;, info o kontakcie i pomocy, oraz formularze zg&#322;aszania b&#322;&#281;d&#243;w.&lt;/p&gt;</description>
      <pubDate>Wed, 21 Nov 2007 11:36:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:cb6e6402-1c4d-44bc-91c6-630b982de04f</guid>
      <author>k3rni</author>
      <link>http://itblog.grono.net/articles/2007/11/21/co-to-jest-widget</link>
      <category>ciekawostki</category>
      <category>widget</category>
      <category>konkurs</category>
    </item>
    <item>
      <title>Poznaj...</title>
      <description>&lt;p&gt;Dzisiaj na nasze podchwytliwe pytania odpowie Depesz, czyli Hubert Lubaczewski.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://b50.grono.net/38/33/gallery-36185315-500x500.jpg" alt="" /&gt;&lt;br&gt;&lt;br&gt;
Q: Imi&#281;, nazwisko:&lt;br&gt;
A: depesz. podobno mam te&#380; imi&#281; i nazwisko (Hubert Lubaczewski), ale z drugiej strony &amp;#8211; nie wierz&#281; plotkom.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Data i miejsce urodzenia:&lt;br&gt;
A: Urodzi&#322;em si&#281; 18 lat temu (plus vat) w takim ma&#322;ym pokoju z lekarzami w Warszawie:) A tak na prawd&#281; mam 31 lat.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Stanowisko w Grono.net: &lt;br&gt;
A: Dba czyli bazodanowiec.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Wykszta&#322;cenie, uko&#324;czone kursy: &lt;br&gt;
A: ekhem. matury nawet nie mam.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W Grono.net pracuj&#281; od:&lt;br&gt;
A: 3 wrze&#347;nia 2007.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Obowi&#261;zki w Grono.net:&lt;br&gt;
A: Aby baza ros&#322;a w si&#322;&#281;, a zapytania by&#322;y szcz&#281;&#347;liwsze. Albo szybsze.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W jakich j&#281;zykach programujesz:&lt;br&gt;
A: G&#322;&#243;wnie w sql, perl. Dodatkowo, troch&#281; w shellu, php, ruby, C.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Dotychczasowe prace:&lt;br&gt;
A: By&#322;em m.in. spedytorem mi&#281;dzynarodowym, programist&#261; od wizualizacji wynik&#243;w referendum europejskiego w 2003 roku, bazodaniowcem/programist&#261; odpowiedzialnym za analizy rynku tytoniowego w Polsce.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W przysz&#322;o&#347;ci chc&#281;:&lt;br&gt;
A: &#379;y&#263; dniem i nie zastanawia&#263; si&#281; nad tym co przyniesie jutro.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Zainteresowania:&lt;br&gt;
A: Bazy danych (serio, ja naprawd&#281; to lubi&#281;), samochody (od strony u&#380;ytkownika, nie mechanika, bo na tym to si&#281; zupe&#322;nie nie znam).&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Zawsze znajd&#281; czas na&amp;#8230;&lt;br&gt;
A: Flame&amp;#8217;a. Na dowolny temat, po dowolnej ze stron konfliktu :)&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Nigdy nie znajd&#281; czasu na&amp;#8230;&lt;br&gt;
A: Ogl&#261;danie telenowel. Pr&#243;bowa&#322;em. Padam w okolicach 3 minuty.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: S&#322;ucham:&lt;br&gt;
A: Dobrej muzyki.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Ulubione strony internetowe: :-)&lt;br&gt;
A: http://www.google.com/reader/view/, http://osloskop.net/, http://hatak.pl&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Lubi&#281;:&lt;br&gt;
A: To bardzo og&#243;lne pytanie, wi&#281;c &amp;#8211; no c&#243;&#380;, uwielbiam filet mignon we &amp;#8220;fridays&amp;#8221;.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Nie lubi&#281;:&lt;br&gt;
A: Kontynuuj&#261;c tematyk&#281;: spaghetti, pasty, latanii i wszystkiego co w&#322;oskie (pizza taka jak&#261; jem jest ameryka&#324;ska, wi&#281;c si&#281; nie liczy:)).&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Podziwiam&amp;#8230;&lt;br&gt;
A: du&#380;o ludzi za du&#380;o rzeczy.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W &#380;yciu prywatnym dbam o:&lt;br&gt;
A: o to by by&#322;o fajnie.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Grono.net jest:&lt;br&gt;
A: Przyjemnie spokojne.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: M&#243;j ulubiony wsp&#243;&#322;pracownik to.. (dlaczego):&lt;br&gt;
A: A tu uchyl&#281; si&#281; od odpowiedzi poniewa&#380; by&#322;aby sprzeczna z moimi przekonaniami religijnymi :)&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 07 Nov 2007 18:00:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:489f5733-abd7-480b-a3e6-d8e39fdb4412</guid>
      <author>Kasia</author>
      <link>http://itblog.grono.net/articles/2007/11/07/poznaj-depesz</link>
      <category>ludzie</category>
    </item>
    <item>
      <title>Poznaj...</title>
      <description>&lt;p&gt;Tym razem kilka s&#322;&#243;w o sobie powie Marcin Winkler, Gronowy Release Manager.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://b62.grono.net/62/70/gallery-34718718-500x500.jpg" alt="" /&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Imi&#281;, nazwisko:&lt;br&gt;
A: Marcin Winkler&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Data i miejsce urodzenia:&lt;br&gt;
A: 22.06.1976 Wo&#322;omin &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Stanowisko w Grono.net:&lt;br&gt;
A: Release Manager &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Wykszta&#322;cenie, przebyte kursy:&lt;br&gt;
A: Wykszta&#322;cenie, na razie tylko &#347;rednie, ale w przysz&#322;o&#347;ci chc&#281; sko&#324;czy&#263; studia.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W Grono.net pracuj&#281; od: &lt;br&gt;
A: Od pocz&#261;tku 2007 roku.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Obowi&#261;zki w Grono.net:&lt;br&gt;
A: Opiekuj&#281; si&#281; kodem napisanym przez programist&#243;w, kt&#243;ry wrzucaj&#261; do repozytorium, przekazuj&#281; aplikacje do testowania i wrzucam je na Grono. Dbam, aby by&#322;o jak najmniej b&#322;&#281;d&#243;w oczywistych i takich kt&#243;re &amp;#8220;nigdy nie powinny si&#281; zdarzy&#263;&amp;#8221; wi&#281;c pilnuje wszystkiego od pocz&#261;tku do ko&#324;ca. &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W jakich j&#281;zykach programujesz:&lt;br&gt;
A: Najbardziej lubi&#281; programowa&#263; w j&#281;zyku Pyton, Php i Perl oraz w domieszkach bash&amp;#8217;a. &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Dotychczasowe prace:&lt;br&gt;
A: Pracowa&#322;em m.in. jako administrator, programista i bazodanowiec.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: W przysz&#322;o&#347;ci chc&#281;:&lt;br&gt;
A: Dalej si&#281; rozwija&#263;, podr&#243;&#380;owa&#263; oraz inwestowa&#263; w siebie i rodzin&#281;. &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Zainteresowania:&lt;br&gt;
A: Interesuje mnie inne spojrzenie na &#347;wiat: medytacja, paranauka, rozwijanie samego siebie. Poza tym&#8230; programowanie:)&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Zawsze znajd&#281; czas na&#8230;&lt;br&gt;
A: &#8230;odrobin&#281; pesymizmu.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Nigdy nie znajd&#281; czasu na&#8230;&lt;br&gt;
A: &#8230;spe&#322;nienie wszystkich marze&#324;. &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: S&#322;ucham: &lt;br&gt;
A: Cafe Del Mar, Zion Train, &lt;span class="caps"&gt;K44&lt;/span&gt; (ich stare piosenki s&#261; najlepsze),  Moby, Buddha Bar, preferuj&#281; mieszank&#281; Hip-Hopu i Ambientu z dodatkiem Chill Out, czasami muzyka jazzowa i rozrywkowa. &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Ulubione strony internetowe:&lt;br&gt;
A: info.onet.pl,  reader.google.com , blogi znajomych i w&#322;asny.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Lubi&#281;:&lt;br&gt;
A: Czasami, zje&#347;&#263; co&#347; s&#322;odkiego.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Nie lubi&#281;: &lt;br&gt;
A: Tych co nie lubi&#261; innych:) &lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Podziwiam&#8230;.&lt;br&gt;
A: Innych za konsekwentne realizowanie swoich cel&#243;w.&lt;br&gt;
Q: W &#380;yciu prywatnym dbam o:&lt;br&gt;
A: O rozw&#243;j osobisty, poniewa&#380; czuj&#281;, &#380;e ci&#261;gle nie jestem doskona&#322;y w tym co robi&#281;.&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: Grono.net jest: &lt;br&gt;
A: Dynamiczn&#261;, m&#322;od&#261; firm&#261; z du&#380;&#261; mo&#380;liwo&#347;ci&#261; rozwoju;)&lt;br&gt;&lt;/p&gt;


	&lt;p&gt;Q: M&#243;j ulubiony wsp&#243;&#322;pracownik to.. (dlaczego):&lt;br&gt;
A: Ka&#380;dy ma swoje wady i zalety lub zalety i wady. Wszystko zale&#380;y od punktu siedzenia.&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 19 Oct 2007 16:00:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:fdca1dbb-80e0-4638-8aee-68d543c30449</guid>
      <author>Kasia</author>
      <link>http://itblog.grono.net/articles/2007/10/19/poznaj-2</link>
      <category>ludzie</category>
    </item>
    <item>
      <title>Napisz widgeta i wygraj sta&#380; w Grono.net!</title>
      <description>&lt;p&gt;Proste zasady  &#8211; zwyci&#281;&#380;a 5 najciekawszych i pomys&#322;owych aplikacji, wykorzystuj&#261;cych zasoby i kod &lt;span class="caps"&gt;API&lt;/span&gt; Grono.net.&lt;/p&gt;


	&lt;p&gt;Freestyle &#8211; mo&#380;e to by&#263; widget na PC, Maca lub stron&#281; www.&lt;/p&gt;


	&lt;p&gt;&#379;adnych formalno&#347;ci &#8211; przesy&#322;asz aplikacj&#281; z opisem i swoje dane na adres &lt;a href="mailto:api@grono.net"&gt;api@grono.net&lt;/a&gt;, otrzymujesz potwierdzenie i jeste&#347; w konkursie.&lt;/p&gt;


&lt;span class="caps"&gt;DO WYGRANIA&lt;/span&gt;:
&lt;ul&gt;
&lt;li&gt;Sta&#380; w Dziale IT Grono.net&lt;/li&gt;
&lt;li&gt;Apple MacBook Pro&lt;/li&gt;
&lt;li&gt;Apple MacBook&lt;/li&gt;
&lt;li&gt;3 iPody&lt;/li&gt;
&lt;li&gt;Wieczna s&#322;awa tw&#243;rcy ulubionego widgeta dla ponad 1,3 miliona naszych u&#380;ytkownik&#243;w!&lt;/li&gt;
&lt;/ul&gt;

	&lt;p&gt;&lt;br&gt;
Zg&#322;oszenia przyjmujemy
od 1 pa&#378;dziernika do 30 listopada 2007
&lt;br&gt;&lt;br&gt;
&lt;span class="caps"&gt;WSZYSTKO CZEGO POTRZEBUJESZ ZNAJDZIESZ NA&lt;/span&gt;
&lt;a href="http://apidoc.grono.net/articles/2007/10/02/widget"&gt;apidoc.grono.net&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 03 Oct 2007 14:05:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:bc7a70b9-b2bb-4b82-a075-4c8c56f21035</guid>
      <author>Kasia</author>
      <link>http://itblog.grono.net/articles/2007/10/03/widget</link>
      <category>ciekawostki</category>
      <category>konkurs</category>
      <category>API</category>
      <category>widget</category>
    </item>
    <item>
      <title>Test macierzy Dell powervault md1000</title>
      <description>Ostatnio dostali&#347;my now&#261; zabawk&#281; do test&#243;w - nowiutkiego &lt;a href="http://www1.euro.dell.com/content/products/productdetails.aspx/pvaul_md1000?c=uk&amp;l=en&amp;s=bsd&amp;cs=ukbsdt1"&gt;della
powervault md1000&lt;/a&gt;. Co to takiego, zapytacie? Ot&#243;&#380; jest to ca&#322;kiem mi&#322;y "das" (direct attached storage, czyli, upraszczaj&#261;c troch&#281;, po prostu macierz) od Dell'a.&lt;br&gt;

Egzemplarz, kt&#243;ry testowali&#347;my mia&#322; 15 dysk&#243;w sas, ka&#380;dy o pojemno&#347;ci 72gb i pr&#281;dko&#347;ci obrotowej 15000 rpm.

Macierz ma by&#263; u&#380;ywana jako no&#347;nik dla bazy danych, wi&#281;c zanim zostanie u&#380;yta musieli&#347;my przeprowadzi&#263; testy (by wiedzie&#263; co i jak podzieli&#263; na poszczeg&#243;lne dyski logiczne).

Pod&#322;&#261;czyli&#347;my j&#261; do wolnego serwera (tak&#380;e Dell'a, ale nieu&#380;ywanego), kt&#243;rego parametry s&#261; "ca&#322;kiem, ca&#322;kiem" :

&lt;ul&gt;
&lt;li&gt;4 dwurdzeniowe xeon'y (3.4ghz)&lt;/li&gt;
&lt;li&gt;32gb ram&lt;/li&gt;
&lt;li&gt;2 wewn&#281;trzne dyski, sas, 72gb, 15000 rpm, 72g zestawione w raid1&lt;/li&gt; &lt;/ul&gt;

Testy przeprowadzili&#347;my przy pomocy bonnie++, procedura testowa by&#322;a prosta:

&lt;ol&gt;
&lt;li&gt;zestawienie nowego raida&lt;/li&gt;
&lt;li&gt;mke2fs -j (ext3)&lt;/li&gt;
&lt;li&gt;zamontowanie partycji z opcjami noatime i nodiratime&lt;/li&gt; &lt;li&gt;uruchomienie bonnie++ z tymi opcjami:"-u nobody:nobody -f -s 65000,8192 -n 0 -x 3" (8192 gdy&#380; taka jest wielko&#347;&#263; strony w postgresie)&lt;/li&gt; &lt;li&gt;rezultaty dla ka&#380;dego raida (-x 3!) by&#322;y u&#347;rednione&lt;/li&gt; &lt;/ol&gt;

Wiedzieli&#347;my, &#380;e docelowo zostanie u&#380;yty raid10, wi&#281;c testowali&#347;my g&#322;&#243;wnie r&#243;&#380;ne jego kombinacje.

Przeprowadzili&#347;my 2 oddzielne serie test&#243;w:

&lt;ol&gt;
&lt;li&gt;raid 10, czysto sprz&#281;towy, u&#380;ywaj&#261;c 2, 4, 6, 8, 10, 12 i 14 dysk&#243;w&lt;/li&gt; &lt;li&gt;raid 10, mieszany sprz&#281;towo/software'owy - sprz&#281;t by&#322; u&#380;yty do zrobienia 7 oddzielnych dysk&#243;w logicznych, ka&#380;dy z u&#380;yciem 2 dysk&#243;w fizycznych spi&#281;tych w raid1, ale potem by&#322;y one sk&#322;adane w jeden dysk logiczny przy pomocy software'owego raida (linux, raid0) w urz&#261;dzenie na 4, 6, 8, 10, 12 i 14 dyskach fizycznych&lt;/li&gt;
&lt;/ol&gt;

Testy przeprowadzono z wy&#322;&#261;czeniem read-aheada, zapisy by&#322;y w trybie write-back, gdy&#380; macierz jest wyposa&#380;ona w pami&#281;&#263; z podtrzymaniem bateryjnym.

Rezultaty s&#261; troch&#281; dziwne (czerwona linia - raid10 czysto sprz&#281;towy, zielona linia - rozwi&#261;zanie mieszane: sprz&#281;t/software):
&lt;br&gt;&lt;br&gt;

&lt;a href='http://www.depesz.com/wp-content/uploads/2007/09/write.png' 
title='write.png'&gt;
&lt;img src='http://www.depesz.com/wp-content/uploads/2007/09/write.png' 
alt='write.png' /&gt;
&lt;/a&gt;

&lt;a href='http://www.depesz.com/wp-content/uploads/2007/09/rewrite.png' 
title='rewrite.png'&gt;&lt;img
src='http://www.depesz.com/wp-content/uploads/2007/09/rewrite.png' 
alt='rewrite.png' /&gt;&lt;/a&gt;
&lt;a href='http://www.depesz.com/wp-content/uploads/2007/09/read.png' 
title='read.png'&gt;&lt;img
src='http://www.depesz.com/wp-content/uploads/2007/09/read.png' 
alt='read.png' /&gt;&lt;/a&gt;
&lt;a href='http://www.depesz.com/wp-content/uploads/2007/09/seeks.png' 
title='seeks.png'&gt;&lt;img
src='http://www.depesz.com/wp-content/uploads/2007/09/seeks.png' 
alt='seeks.png'/&gt;&lt;/a&gt;
&lt;br&gt;
Je&#347;li wolisz wyniki w postaci tabelek:
&lt;br&gt;&lt;br&gt;
&lt;table border="1"&gt;
    &lt;tr&gt; &lt;th&gt;name&lt;/th&gt; &lt;th&gt;put_block&lt;/th&gt; &lt;th&gt;put_block_cpu&lt;/th&gt; &lt;th&gt;rewrite&lt;/th&gt; &lt;th&gt;rewrite_cpu&lt;/th&gt; &lt;th&gt;get_block&lt;/th&gt; &lt;th&gt;get_block_cpu&lt;/th&gt;
        &lt;th&gt;seeks&lt;/th&gt; &lt;th&gt;seeks_cpu&lt;/th&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;2xraid1&lt;/th&gt; &lt;td&gt;34820&lt;/td&gt; &lt;td&gt;12&lt;/td&gt; &lt;td&gt;25105&lt;/td&gt; &lt;td&gt;6&lt;/td&gt; &lt;td&gt;97459&lt;/td&gt; &lt;td&gt;9&lt;/td&gt; &lt;td&gt;436&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;4xraid10&lt;/th&gt; &lt;td&gt;95427&lt;/td&gt; &lt;td&gt;37&lt;/td&gt; &lt;td&gt;65661&lt;/td&gt; &lt;td&gt;19&lt;/td&gt; &lt;td&gt;246490&lt;/td&gt; &lt;td&gt;23&lt;/td&gt; &lt;td&gt;615&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;6xraid10&lt;/th&gt; &lt;td&gt;100367&lt;/td&gt; &lt;td&gt;39&lt;/td&gt; &lt;td&gt;70955&lt;/td&gt; &lt;td&gt;20&lt;/td&gt; &lt;td&gt;288188&lt;/td&gt; &lt;td&gt;27&lt;/td&gt; &lt;td&gt;672&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;8xraid10&lt;/th&gt; &lt;td&gt;165980&lt;/td&gt; &lt;td&gt;66&lt;/td&gt; &lt;td&gt;98887&lt;/td&gt; &lt;td&gt;29&lt;/td&gt; &lt;td&gt;423983&lt;/td&gt; &lt;td&gt;39&lt;/td&gt; &lt;td&gt;737&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;10xraid10&lt;/th&gt; &lt;td&gt;164195&lt;/td&gt; &lt;td&gt;64&lt;/td&gt; &lt;td&gt;96039&lt;/td&gt; &lt;td&gt;28&lt;/td&gt; &lt;td&gt;394442&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;618&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;12xraid10&lt;/th&gt; &lt;td&gt;185671&lt;/td&gt; &lt;td&gt;72&lt;/td&gt; &lt;td&gt;103271&lt;/td&gt; &lt;td&gt;30&lt;/td&gt; &lt;td&gt;414942&lt;/td&gt; &lt;td&gt;38&lt;/td&gt; &lt;td&gt;686&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;14xraid10&lt;/th&gt; &lt;td&gt;195349&lt;/td&gt; &lt;td&gt;76&lt;/td&gt; &lt;td&gt;104087&lt;/td&gt; &lt;td&gt;30&lt;/td&gt; &lt;td&gt;439088&lt;/td&gt; &lt;td&gt;40&lt;/td&gt; &lt;td&gt;821&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;2s0@2h1&lt;/th&gt; &lt;td&gt;86651&lt;/td&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;61836&lt;/td&gt; &lt;td&gt;18&lt;/td&gt; &lt;td&gt;251109&lt;/td&gt; &lt;td&gt;24&lt;/td&gt; &lt;td&gt;618&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;3s0@2h1&lt;/th&gt; &lt;td&gt;110977&lt;/td&gt; &lt;td&gt;42&lt;/td&gt; &lt;td&gt;79381&lt;/td&gt; &lt;td&gt;24&lt;/td&gt; &lt;td&gt;356231&lt;/td&gt; &lt;td&gt;34&lt;/td&gt; &lt;td&gt;708&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;4s0@2h1&lt;/th&gt; &lt;td&gt;120232&lt;/td&gt; &lt;td&gt;45&lt;/td&gt; &lt;td&gt;91988&lt;/td&gt; &lt;td&gt;28&lt;/td&gt; &lt;td&gt;391041&lt;/td&gt; &lt;td&gt;37&lt;/td&gt; &lt;td&gt;748&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;5s0@2h1&lt;/th&gt; &lt;td&gt;131024&lt;/td&gt; &lt;td&gt;50&lt;/td&gt; &lt;td&gt;92403&lt;/td&gt; &lt;td&gt;28&lt;/td&gt; &lt;td&gt;556601&lt;/td&gt; &lt;td&gt;55&lt;/td&gt; &lt;td&gt;788&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;6s0@2h1&lt;/th&gt; &lt;td&gt;123812&lt;/td&gt; &lt;td&gt;47&lt;/td&gt; &lt;td&gt;93563&lt;/td&gt; &lt;td&gt;28&lt;/td&gt; &lt;td&gt;482090&lt;/td&gt; &lt;td&gt;47&lt;/td&gt; &lt;td&gt;778&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;7s0@2h1&lt;/th&gt; &lt;td&gt;137513&lt;/td&gt; &lt;td&gt;53&lt;/td&gt; &lt;td&gt;100083&lt;/td&gt; &lt;td&gt;31&lt;/td&gt; &lt;td&gt;657221&lt;/td&gt; &lt;td&gt;65&lt;/td&gt; &lt;td&gt;839&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;2s0@6h10&lt;/th&gt; &lt;td&gt;160090&lt;/td&gt; &lt;td&gt;61&lt;/td&gt; &lt;td&gt;104375&lt;/td&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;482106&lt;/td&gt; &lt;td&gt;46&lt;/td&gt; &lt;td&gt;716&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;2s1@2h1&lt;/th&gt; &lt;td&gt;44373&lt;/td&gt; &lt;td&gt;16&lt;/td&gt; &lt;td&gt;25972&lt;/td&gt; &lt;td&gt;6&lt;/td&gt; &lt;td&gt;99071&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;651&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;13xraid5&lt;/th&gt; &lt;td&gt;222225&lt;/td&gt; &lt;td&gt;87&lt;/td&gt; &lt;td&gt;113040&lt;/td&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;392238&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;806&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;14xraid5&lt;/th&gt; &lt;td&gt;222690&lt;/td&gt; &lt;td&gt;87&lt;/td&gt; &lt;td&gt;114142&lt;/td&gt; &lt;td&gt;33&lt;/td&gt; &lt;td&gt;398201&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;809&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;/table&gt;
&lt;br&gt;
Znaczenie kolumny name:

&lt;ul&gt;
&lt;li&gt;(\d+)xraid(\d+) - $1 dysk&#243;w w czysto sprz&#281;towym raidzie $2. przyk&#322;adowo - 6xraid10 oznacza 6 dysk&#243;w w sprz&#281;towym raidzie 10&lt;/li&gt;
&lt;li&gt;(\d+)s0@2h1 - $1 dysk&#243;w logicznych (gdzie ka&#380;dy dysk logiczny, to 2 dyski fizyczne spi&#281;te w sprz&#281;towy raid1) po&#322;&#261;czone w software'owy raid0. 
przyk&#322;adowo 5s0@2h1 oznacza 5 dysk&#243;w logicznych (ka&#380;dy z 2 nap&#281;d&#243;w, w raid1) po&#322;&#261;czonych, daj&#261;c razem raid 10 na 10 dyskach w uk&#322;adzie mieszanym sprz&#281;towo/software'owym&lt;/li&gt; &lt;li&gt;2s0@6h10 - 2 dyski logiczne, ka&#380;dy sk&#322;adaj&#261;cy si&#281; z 6 dysk&#243;w fizycznych po&#322;&#261;czonych w sprz&#281;towy raid10, po&#322;&#261;czone w software'owy raid 0&lt;/li&gt;
&lt;li&gt;2s1@2h1 - 2 dyski logiczne, ka&#380;dy b&#281;d&#261;cy 2 dyskowym, sprz&#281;towym, raidem 1, po&#322;&#261;czone w software'owy raid1. daje to 4 dyskowa macierz o pojemno&#347;ci pojedynczego dysku.&lt;/li&gt; &lt;/ul&gt;

Jak wida&#263;, przetestowali&#347;my kilka uk&#322;ad&#243;w wi&#281;cej niz pokazane jest to na wykresach powy&#380;ej, ale wszystkie pozosta&#322;e by&#322;y jedynie testowe, bez realnego wp&#322;ywu na jakiekolwiek decyzje.

Dziwna sprawa - czysto sprz&#281;towy raid wykazuje "schodki" w wydajno&#347;ci zapis&#243;w (i przepisywania danych). Przyrost wydajno&#347;ci by&#322; tylko wtedy, gdy ilo&#347;&#263; dysk&#243;w by&#322;a pot&#281;g&#261; 2. W raidach mieszanych (sprz&#281;t/software) nie by&#322;o takiego efektu.

Poniewa&#380; macierz ma 15 dysk&#243;w, zdecydowali&#347;my si&#281; na u&#380;ycie takiego layoutu:

&lt;ul&gt;
&lt;li&gt;1 dysk jako globalny hot-spare&lt;/li&gt;
&lt;li&gt;2 diskowy raid1 (sprz&#281;towy) na logi postgresa&lt;/li&gt;
&lt;li&gt;8 dyskowy raid10 (sprz&#281;towy) jako g&#322;&#243;wna przestrze&#324; (tablespace) bazodanowa&lt;/li&gt;
&lt;li&gt;4 dyskowy raid10 (sprz&#281;towy) jako dodatkowa przestrze&#324; bazodanowa&lt;/li&gt;&lt;/ul&gt;

Teoretycznie uk&#322;ad ten powinien zapewni&#263; najlepsz&#261; wydajno&#347;&#263;, czy tak by&#322;o?

Po stworzeniu macierzy, za&#322;o&#380;eniu system&#243;w plik&#243;w, przetestowali&#347;my wydajno&#347;&#263; wszystkich 3 dysk&#243;w logicznych jednocze&#347;nie.

Wynik&#243;w nie rozrysowywali&#347;my, gdy&#380; i tak nie mia&#322;oby to zbyt du&#380;ego sensu. Ale wyniki z testu mo&#380;na poda&#263; tabelarycznie:&lt;br&gt;&lt;br&gt;

&lt;table border="1"&gt;
    &lt;tr&gt; &lt;th&gt;name&lt;/th&gt; &lt;th&gt;put_block&lt;/th&gt; &lt;th&gt;put_block_cpu&lt;/th&gt; &lt;th&gt;rewrite&lt;/th&gt; &lt;th&gt;rewrite_cpu&lt;/th&gt; &lt;th&gt;get_block&lt;/th&gt; &lt;th&gt;get_block_cpu&lt;/th&gt;
        &lt;th&gt;seeks&lt;/th&gt; &lt;th&gt;seeks_cpu&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt;&lt;th&gt;2xraid1&lt;/th&gt; &lt;td&gt;30875&lt;/td&gt; &lt;td&gt;12&lt;/td&gt; &lt;td&gt;15438&lt;/td&gt; &lt;td&gt;5&lt;/td&gt; &lt;td&gt;39867&lt;/td&gt; &lt;td&gt;5&lt;/td&gt; &lt;td&gt;224&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;2xraid1&lt;/th&gt; &lt;td&gt;32489&lt;/td&gt; &lt;td&gt;14&lt;/td&gt; &lt;td&gt;24037&lt;/td&gt; &lt;td&gt;7&lt;/td&gt; &lt;td&gt;99700&lt;/td&gt; &lt;td&gt;9&lt;/td&gt; &lt;td&gt;389&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;2xraid1&lt;/th&gt; &lt;td&gt;35096&lt;/td&gt; &lt;td&gt;13&lt;/td&gt; &lt;td&gt;24708&lt;/td&gt; &lt;td&gt;6&lt;/td&gt; &lt;td&gt;96969&lt;/td&gt; &lt;td&gt;9&lt;/td&gt; &lt;td&gt;383&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;4xraid10&lt;/th&gt; &lt;td&gt;41343&lt;/td&gt; &lt;td&gt;18&lt;/td&gt; &lt;td&gt;31910&lt;/td&gt; &lt;td&gt;11&lt;/td&gt; &lt;td&gt;61798&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;td&gt;109&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;4xraid10&lt;/th&gt; &lt;td&gt;80630&lt;/td&gt; &lt;td&gt;34&lt;/td&gt; &lt;td&gt;35707&lt;/td&gt; &lt;td&gt;12&lt;/td&gt; &lt;td&gt;137488&lt;/td&gt; &lt;td&gt;18&lt;/td&gt; &lt;td&gt;306&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;4xraid10&lt;/th&gt; &lt;td&gt;40136&lt;/td&gt; &lt;td&gt;17&lt;/td&gt; &lt;td&gt;38388&lt;/td&gt; &lt;td&gt;12&lt;/td&gt; &lt;td&gt;147282&lt;/td&gt; &lt;td&gt;16&lt;/td&gt; &lt;td&gt;255&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;8xraid10&lt;/th&gt; &lt;td&gt;42376&lt;/td&gt; &lt;td&gt;18&lt;/td&gt; &lt;td&gt;37513&lt;/td&gt; &lt;td&gt;13&lt;/td&gt; &lt;td&gt;155740&lt;/td&gt; &lt;td&gt;19&lt;/td&gt; &lt;td&gt;302&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;8xraid10&lt;/th&gt; &lt;td&gt;156044&lt;/td&gt; &lt;td&gt;65&lt;/td&gt; &lt;td&gt;34153&lt;/td&gt; &lt;td&gt;11&lt;/td&gt; &lt;td&gt;177690&lt;/td&gt; &lt;td&gt;22&lt;/td&gt; &lt;td&gt;338&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;8xraid10&lt;/th&gt; &lt;td&gt;146096&lt;/td&gt; &lt;td&gt;61&lt;/td&gt; &lt;td&gt;71307&lt;/td&gt; &lt;td&gt;25&lt;/td&gt; &lt;td&gt;29568&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;154&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;&lt;/tr&gt; &lt;/table&gt;
&lt;br&gt;
(pokazano tu wyniki ka&#380;dego testu, czyli po 3 wyniki dla ka&#380;dej z partycji).

Jak wida&#263;, wyniki s&#261; ni&#380;sze od oczekiwanych. Dodatkowo, analiz&#281; utrudnia fakt, i&#380; test macierzy 8xraid10 sko&#324;czy&#322; si&#281; jako pierwszy (bo jest najszybsza), 4xraid10 sko&#324;czy&#322; si&#281; troch&#281; p&#243;&#378;niej, a 2xraid1 trwa&#322; i trwa&#322;, i trwa&#322;:)
&lt;br&gt;
My&#347;l&#281;, &#380;e wybrali&#347;my rozwi&#261;zanie optymalne przy tej macierzy i kontrolerze, ale tak czy inaczej zastanawiaj&#261;ce jest czemu wydajno&#347;&#263; tak mocno jest powi&#261;zana z pot&#281;gami dw&#243;jki.</description>
      <pubDate>Thu, 27 Sep 2007 17:04:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:36c87337-ecaa-44f4-9a1c-bf52033cc7b8</guid>
      <author>depesz</author>
      <link>http://itblog.grono.net/articles/2007/09/27/test-macierzy</link>
      <category>ciekawostki</category>
      <category>Dell</category>
      <category>macierz</category>
    </item>
    <item>
      <title>Poznaj...</title>
      <description>&lt;p&gt;Dzi&#347; spotkanie z Kamilem Za&#322;&#281;skim, Kierownikiem Dzia&#322;u Wersji J&#281;zykowych.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://b88.grono.net/29/46/gallery-33045489-500x500.jpg" alt="" /&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;
Q: Imi&#281;, nazwisko:&lt;br&gt;
A: Kamil Za&#322;&#281;ski&lt;br&gt;&lt;br&gt;
Q: Data i miejsce urodzenia: &lt;br&gt;
A: 23.02.1986, Pruszk&#243;w&lt;br&gt;&lt;br&gt;
Q: Stanowisko w Grono.net:&lt;br&gt;
A: Kierownik Dzia&#322;u wersji j&#281;zykowych &lt;br&gt;&lt;br&gt;
Q: Wykszta&#322;cenie, kursy: &lt;br&gt;
A: Wy&#380;sza Szko&#322;a Technologii Informatycznych, specjalizacja &amp;#8211; Bazy Danych&lt;br&gt;&lt;br&gt;
Q: W Grono.net pracuj&#281; od: &lt;br&gt;
A: pa&#378;dziernika 2006&lt;br&gt;&lt;br&gt;
Q: Obowi&#261;zki w Grono.net: &lt;br&gt;
A: Przygotowuj&#281; wersje j&#281;zykowe Grona. Dbam o otwarcie Grona na zagranicznych u&#380;ytkownik&#243;w&lt;br&gt;&lt;br&gt;
Q: W jakich j&#281;zykach programujesz: &lt;br&gt;
A: Python, Ruby, Javascript, &lt;span class="caps"&gt;PHP&lt;/span&gt;&lt;br&gt;&lt;br&gt;
Q: Dotychczasowe prace: &lt;br&gt;
A: G&#322;&#243;wnie freelance, a bezpo&#347;rednio przed Gronem agencja interaktywna Prospekta &lt;br&gt;&lt;br&gt;
Q: W przysz&#322;o&#347;ci chc&#281;: &lt;br&gt;
A; Tajemnica :P&lt;br&gt;&lt;br&gt;
Q: Zainteresowania: &lt;br&gt;
A: Programowanie, web usability, ogl&#261;danie seriali (Soprano, Lost, Jericho,...):)&lt;br&gt;&lt;br&gt;
Q: Zawsze znajd&#281; czas na&#8230; &lt;br&gt;
A: Czytanie Google Readera&lt;br&gt;&lt;br&gt;
Q: Nigdy nie znajd&#281; czasu na&#8230; &lt;br&gt;
A: Posprz&#261;tania biurka&lt;br&gt;&lt;br&gt;
Q: S&#322;ucham: &lt;br&gt;
A: Wsiowych hit&#243;w w samochodzie Sebka, a z wykonawc&#243;w to: Fatboy Slim, Moby, Chemical Brothers, Rammstein, Prodi&#380;y&lt;br&gt;&lt;br&gt;
Q: Ulubione strony internetowe:&lt;br&gt;
A: joemonster.org, digg.com&lt;br&gt;&lt;br&gt;
Q: Lubi&#281;: &lt;br&gt;
A: Hamburgery w &lt;span class="caps"&gt;HRC&lt;/span&gt;&lt;br&gt;&lt;br&gt;
Q: Nie lubi&#281;: &lt;br&gt;
A: Je&#378;dzi&#263; komunikacja zbiorow&#261; i takich kwestionariuszy&lt;br&gt;&lt;br&gt; 
Q: Podziwiam&#8230;&lt;br&gt;
A: Ludzi kt&#243;rzy potrafi&#261; konsekwentnie realizowa&#263; swoje cele&lt;br&gt;&lt;br&gt;
Q: W &#380;yciu prywatnym dbam o: &lt;br&gt;
A: O ludzi mi bliskich i to co dla mnie wa&#380;ne &lt;br&gt;&lt;br&gt;
Q: Grono.net jest: &lt;br&gt;
A: Pe&#322;ne bardzo kumatych ludzi od kt&#243;rych wiele si&#281; ucz&#281;&lt;br&gt;&lt;br&gt;
Q: M&#243;j ulubiony wsp&#243;&#322;pracownik to&amp;#8230; (dlaczego): &lt;br&gt;
A: Nie lubi&#281; nikogo wyr&#243;&#380;nia&#263;&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 27 Sep 2007 14:01:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:b4982c1a-e868-49bf-b465-6a2a152e6d47</guid>
      <author>Kasia</author>
      <link>http://itblog.grono.net/articles/2007/09/27/poznaj</link>
      <category>ludzie</category>
      <category>Kamil</category>
    </item>
  </channel>
</rss>
