<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.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>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Ruby, Python i natywne w&#261;tki systemu operacyjnego</title>
    <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Ruby, Python i natywne w&#261;tki systemu operacyjnego</title>
      <description>&lt;p&gt;Wiele si&#281; m&#243;wi o tym, &#380;e Ruby jak i Python nie posiadaj&#261; obs&#322;ugi natywnych w&#261;tk&#243;w systemu operacyjnego. Wbudowane, tzw. &lt;em&gt;green threads&lt;/em&gt;, nie s&#261; w stanie wykorzysta&#263; zalet maszyn wyposa&#380;onych w procesory wielordzeniowe. Istniej&#261; jednak implementacje obu j&#281;zyk&#243;w w czystej Javie. Czy ich u&#380;ycie daje jakie&#347; znacz&#261;ce przy&#347;pieszenie?&lt;/p&gt;


	&lt;p&gt;Wszystkie testy by&#322;y wykonywane na MacBook Pro Core2 Duo 2.16GHZ, 4GB &lt;span class="caps"&gt;RAM&lt;/span&gt; i systemie Mac &lt;span class="caps"&gt;OS X 10&lt;/span&gt;.5.4 Leopard + zainstalowana Java 1.6.0_05.&lt;/p&gt;


	&lt;h2&gt;Python&lt;/h2&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;random&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;threading&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Thread&lt;/span&gt;
&lt;span class="ident"&gt;rand&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;&lt;span class="punct"&gt;().&lt;/span&gt;&lt;span class="ident"&gt;randint&lt;/span&gt; &lt;span class="comment"&gt;# alias&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test(Thread):&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__init__&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
      &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;__init__&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Starting %s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getName&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
      &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sort&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
      &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;%s finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getName&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;      

&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Start&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;start&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;100000&lt;/span&gt;
&lt;span class="ident"&gt;threads&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;             
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;append&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;     
&lt;span class="keyword"&gt;while&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;isAlive&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;]:&lt;/span&gt;
    &lt;span class="ident"&gt;pass&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Time: %s s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Dla powy&#380;szego kodu Python i Jython uzyska&#322;y wyniki:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Jython 2.2.1 = 12.15 s.&lt;/li&gt;
		&lt;li&gt;Python 2.5.2 = 14.24 s.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Ro&#380;nica jako&#347; podejrzanie ma&#322;a wskazuj&#261;ca na wci&#261;&#380; jeszcze niedojrza&#322;&#261; implementacj&#281; Jythona. Dla pewno&#347;ci, zmodyfikowa&#322;em kod tak, aby korzysta&#322; z natywnych bibliotek Javy.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;random&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;
&lt;span class="ident"&gt;rand&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;&lt;span class="punct"&gt;().&lt;/span&gt;&lt;span class="ident"&gt;randint&lt;/span&gt; &lt;span class="comment"&gt;# alias&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;java&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;lang&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Runnable&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test(Runnable):&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__init__&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
      &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Starting %s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;         
      &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sort&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;  
      &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;%s finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;

&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Start&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;start&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;100000&lt;/span&gt;    
&lt;span class="ident"&gt;threads&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;             
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;())&lt;/span&gt;              
    &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;append&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;     
&lt;span class="keyword"&gt;while&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;isAlive&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;]:&lt;/span&gt;
    &lt;span class="ident"&gt;pass&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Time: %s s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Tym razem&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Jython 2.2.1 = 11.96 s.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;R&#243;&#380;nica jest minimalna. Na dodatek panuje troch&#281; zamieszania co do sposobu odpalania w&#261;tk&#243;w w Jythonie &amp;#8211; &lt;a href="http://aspn.activestate.com/ASPN/Mail/Message/Jython-users/2034708"&gt;m&#281;tna sk&#322;adnia i za du&#380;o mo&#380;liwych sposob&#243;w&lt;/a&gt; uzyskania tego samego efektu. Po SQLAlchemy, Jython jest kolejnym przyk&#322;adam ca&#322;kowitej ignorancji za&#322;o&#380;e&#324; j&#281;zyka Python (o istnieniu jednej, oczywistej drogi do tego samego celu). Na domiar z&#322;ego, m&#243;j pierwotny test zak&#322;ada&#322; testowanie miliona liczb do sortowania. Jython nie by&#322; w stanie tego testu wykona&#263; z powodu braku pami&#281;ci dla Javy. Ruszy&#322; dopiero jak mu zaalokowa&#322;em 1GB (s&#322;ownie: jeden gigabajt pami&#281;ci) za pomoc&#261; opcji (-Xmx1024M), co jest po prostu chore! Po wymianie pierwotnego &lt;code&gt;range()&lt;/code&gt; na generatorowy &lt;code&gt;xrange()&lt;/code&gt; zapotrzebowanie na pami&#281;&#263; wyra&#378;nie zmala&#322;o i wystarczy&#322;a ju&#380; opcja -Xmx256M. Jednak&#380;e kod si&#281; wykonywa&#322;&#160;tak koszmarnie wolno, &#380;e nie starczy&#322;o mi cierpliwo&#347;ci i zmniejszy&#322;em ilo&#347;&#263; iteracji do 100 tys.&lt;/p&gt;


	&lt;h2&gt;Ruby&lt;/h2&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;thread&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;100_000&lt;/span&gt;

&lt;span class="ident"&gt;start&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Start&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;threads&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="constant"&gt;THREADS&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Starting Thread-&lt;span class="expr"&gt;#{i}&lt;/span&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;e&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)}&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sort!&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Thread-&lt;span class="expr"&gt;#{t}&lt;/span&gt; ended&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;while&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;lt&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;lt&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alive?&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt; 
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Time: &lt;span class="expr"&gt;#{Time.now - start}&lt;/span&gt; s.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Pierwsze, co mi si&#281; od razu rzuca w oczy, to o wiele czytelniejsza, zgrzebniejsza sk&#322;adnia Rubiego, kt&#243;ry tu korzysta z blok&#243;w kodu. Po drugie, wyniki s&#261; dosy&#263; ciekawe:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Ruby 1.9.0 = 1.11 s&lt;/li&gt;
		&lt;li&gt;Ruby Enterprise = 2.77 s&lt;/li&gt;
		&lt;li&gt;JRuby 1.1.2 = 3.53 s&lt;/li&gt;
		&lt;li&gt;Ruby 1.8.7 = 21.82 s.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Ruby okaza&#322; si&#281; najwolniejszy w tym zestawieniu. Python by&#322; tylko troch&#281; szybszy. JRuby, korzystaj&#261;cy z javowych w&#261;tk&#243;w systemowych, zdeklasowa&#322; Rubiego, Pythona i niedojrza&#322;ego Jythona. Jednak&#380;e to nie JRuby okaza&#322; si&#281; tu zwyci&#281;zc&#261;. Nie trzeba czeka&#263; na Ruby 2.0, wersja 1.9 posiada ju&#380; natywn&#261; obs&#322;ug&#281; w&#261;tk&#243;w &lt;span class="caps"&gt;POSIX&lt;/span&gt; i jest dodatkowo nie&#378;le zoptymalizowana. Ruby 1.9 pokaza&#322;, &#380;e jest tu prawie 4x szybszy od JRuby. Nie s&#261;dz&#281;, &#380;e t&#261; szybko&#347;&#263; uzyska&#322; na lepszej implementacji w&#261;tk&#243;w od Javy. Raczej ma mocno zoptymalizowany kod kt&#243;ry by&#322; wykonywany w ka&#380;dym z w&#261;tk&#243;w.&lt;/p&gt;


	&lt;p&gt;Bardzo dobrze poradzi&#322; sobie te&#380; &lt;a href="http://www.rubyenterpriseedition.com/"&gt;Ruby Enterprise&lt;/a&gt;, zoptymalizowana wersja Ruby 1.8.6 przez tw&#243;rc&#243;w &lt;a href="http://www.modrails.com/"&gt;Passengera&lt;/a&gt;! Nie wiem jakim cudem Ruby Enterprise pobi&#322;&#160;JRubiego&amp;#8230; no chyba, &#380;e jego tw&#243;rcy dodali mu obs&#322;ug&#281; natywnych w&#261;tk&#243;w systemu operacyjnego. Inaczej nie mog&#281; sobie wyt&#322;umaczy&#263; tak dobrego wyniku.&lt;/p&gt;


	&lt;h2&gt;Updated&lt;/h2&gt;


	&lt;p&gt;Dla pe&#322;niejszego obrazu uruchomi&#322;em testy dla 1 w&#261;tku. Poprawi&#322;em te&#380; b&#322;&#261;d z ilo&#347;ci&#261; list do sortowania faworyzuj&#261;c&#261; Rubiego. Ostateczne podsumowanie wygl&#261;da tak:&lt;/p&gt;


	&lt;p&gt;1 thread, 2,000,000 iterations&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Ruby 1.9 = 1.69 s.   &lt;/li&gt;
		&lt;li&gt;Ruby Enterprise = 3.38 s.&lt;/li&gt;
		&lt;li&gt;JRuby 1.1.2 = 7.06 s.&lt;/li&gt;
		&lt;li&gt;Jython 2.2.1 = 17.29 s.&lt;/li&gt;
		&lt;li&gt;Python 2.5.2 = 18.06 s.&lt;/li&gt;
		&lt;li&gt;Ruby 1.8.7 = 22.37 s.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;20 threads * 100,000 iterations&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Ruby 1.9 = 1.54 s.   &lt;/li&gt;
		&lt;li&gt;Ruby Enterprise = 3.01 s.           &lt;/li&gt;
		&lt;li&gt;JRuby 1.1.2 = 5.82 s.&lt;/li&gt;
		&lt;li&gt;Jython 2.2.1 = 11.86 s.&lt;/li&gt;
		&lt;li&gt;Python 2.5.2 = 12.32 s.                                                  &lt;/li&gt;
		&lt;li&gt;Ruby 1.8.7 = 22.68 s.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Czasy, kiedy Python by&#322;&#160;zawsze szybszy od Rubiego, to ju&#380; przesz&#322;o&#347;&#263;. Z wynik&#243;w wynika, &#380;e to nie obs&#322;uga w&#261;tk&#243;w zadecydowa&#322;a o wynikach. Ruby 1.9 pobi&#322;&#160;wszystkich zar&#243;wno w te&#347;cie 1 jak i wielu w&#261;tk&#243;w.&lt;/p&gt;


	&lt;h2&gt;Updated 2008-07-30&lt;/h2&gt;


	&lt;p&gt;Poprawi&#322;em troch&#281; test, aby nie zu&#380;ywa&#322; tyle pami&#281;ci. Wyrzuci&#322;em wi&#281;c generowanie list i sortownie. Zosta&#322;o samo generowanie losowych liczb. Doda&#322;em te&#380; kod dla Javy dla por&#243;wnania.&lt;/p&gt;


	&lt;h3&gt;Java&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;import java.util.Random;

public class Main {

  static Integer SIZE,  ITERATIONS;

  public static void main(String[] args) throws Exception {
    Integer[] threads_nr = {1, 10, 50, 100};
    SIZE = Integer.parseInt(args[1]);
    System.out.println(args[0]);
    for(Integer nr: threads_nr) {
      ITERATIONS = SIZE / nr;
      System.out.printf(&amp;quot; %3d thread(s) x %9s = &amp;quot;, nr, ITERATIONS);
      long start = System.currentTimeMillis();
      Thread[] threads = new Thread[nr];
      for(int i = 0; i &amp;lt; threads.length; i++) {
        threads[i] = new ThreadTest();
        threads[i].start();
      }
      while(threadsAlive(threads)) {}
      System.out.printf(&amp;quot;%s s.\n&amp;quot;, (System.currentTimeMillis() - start) / 1000.0);
    }
  }

  public static boolean threadsAlive(Thread[] threads) {
    for(Thread t: threads)
      if(t.isAlive())
        return true;
    return false;
  }

  static class ThreadTest extends Thread {

    @Override
    public void run() {
      Random rnd = new Random();
      for(int i = 0; i &amp;lt; ITERATIONS; i++)
        rnd.nextInt(SIZE);
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Test:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ java Main &amp;quot;`java -version`&amp;quot; 10000000
java version &amp;quot;1.6.0_05&amp;quot;
Java(TM) SE Runtime Environment (build 1.6.0_05-b13-120)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_05-b13-52, mixed mode)
  1 thread(s) x  10000000 = 0.361 s.
 10 thread(s) x   1000000 = 0.18 s.
 50 thread(s) x    200000 = 0.186 s.
100 thread(s) x    100000 = 0.189 s.  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Java, co nie dziwi, jest najszybsza. Nie ma znacz&#261;cej r&#243;&#380;nicy mi&#281;dzy 10 czy 10 w&#261;tkami, bo m&#243;j procesor posiada tylko dwa rdzenie.&lt;/p&gt;


	&lt;h3&gt;Ruby/JRuby&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;thread&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;to_i&lt;/span&gt;  
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;   
&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;50&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;100&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;nr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;iterations&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="ident"&gt;nr&lt;/span&gt;
  &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; %3d thread(s) x %9s = &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;nr&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;start&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt;
  &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="ident"&gt;nr&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;start&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ten sam kod w Ruby/JRuby wygl&#261;da znacznie kr&#243;cej (i &#322;adniej) ale kosztem wydajno&#347;ci. To te&#380; nie dziwi. Ruby jest bardzo produktywnym j&#281;zykiem, lecz oczywi&#347;cie nie tak szybkim jak Java.&lt;/p&gt;


	&lt;p&gt;Wyniki test&#243;w:&lt;/p&gt;


	&lt;p&gt;Ruby 1.9:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ ruby1.9 main.rb &amp;quot;`ruby1.9 -v`&amp;quot; 10_000_000
ruby 1.9.0 (2008-06-20 revision 17482) [i686-darwin9.4.0]
  1 thread(s) x  10000000 = 2.858588
 10 thread(s) x   1000000 = 2.832928
 50 thread(s) x    200000 = 2.845377
100 thread(s) x    100000 = 2.852745&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;JRuby:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ jruby main.rb &amp;quot;`jruby -v`&amp;quot; 10_000_000
jruby 1.1.3 (ruby 1.8.6 patchlevel 114) (2008-07-28 rev 6586) [x86_64-java]
   1 thread(s) x  10000000 = 3.58
  10 thread(s) x   1000000 = 3.4290000000000003
  50 thread(s) x    200000 = 3.442
 100 thread(s) x    100000 = 3.516&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ruby Enterprise:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ ruby-enterprise main.rb &amp;quot;`ruby-enterprise -v`&amp;quot; 10_000_000
ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin9.4.0]
  1 thread(s) x  10000000 = 3.510694
 10 thread(s) x   1000000 = 3.552756
 50 thread(s) x    200000 = 3.586885
100 thread(s) x    100000 = 3.574564&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ruby 1.8.6 (installed with Leopard):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ /usr/bin/ruby main.rb &amp;quot;`/usr/bin/ruby -v`&amp;quot; 10_000_000
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
   1 thread(s) x  10000000 = 6.586917
  10 thread(s) x   1000000 = 6.78801
  50 thread(s) x    200000 = 6.951003
 100 thread(s) x    100000 = 6.907087&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ruby 1.8.7 (installed from MacPorts):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ ruby main.rb   &amp;quot;`ruby -v`&amp;quot; 10_000_000
ruby 1.8.7 (2008-06-20 patchlevel 22) [i686-darwin9.4.0]
   1 thread(s) x  10000000 = 36.329174
  10 thread(s) x   1000000 = 36.808753
  50 thread(s) x    200000 = 36.715717
 100 thread(s) x    100000 = 36.499772   &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;To co niepokoi, to koszmarnie wolna praca Ruby 1.8.7 w por&#243;wnaniu do Ruby 1.8.6. To jest bardzo podejrzana sprawa. Cieszy za to dobra wydajno&#347;&#263; Ruby Enterprise.&lt;/p&gt;


	&lt;h3&gt;Python/Jython&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;random&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;argv&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;threading&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Thread&lt;/span&gt;
&lt;span class="ident"&gt;rand&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Random&lt;/span&gt;&lt;span class="punct"&gt;().&lt;/span&gt;&lt;span class="ident"&gt;randint&lt;/span&gt; &lt;span class="comment"&gt;# alias&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ThreadTest(Thread):&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__init__&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
      &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;__init__&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;              
      &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;iterations&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;iterations&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
      &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="constant"&gt;SIZE&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;

&lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;nr&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;50&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;100&lt;/span&gt;&lt;span class="punct"&gt;]:&lt;/span&gt;
  &lt;span class="ident"&gt;iterations&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SIZE&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="ident"&gt;nr&lt;/span&gt;
  &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; %3d thread(s) x %9s = &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;nr&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt;
  &lt;span class="ident"&gt;start&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;threads&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
  &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;nr&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
     &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ThreadTest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;iterations&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
     &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;append&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
     &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;threads&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
     &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;%s s.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Test:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ python main.py &amp;quot;`python -V`&amp;quot; 10000000
Python 2.5.2
  1 thread(s) x  10000000 =  34.5188429356 s.
 10 thread(s) x   1000000 =  52.3496830463 s.
 50 thread(s) x    200000 =  53.9406650066 s.
100 thread(s) x    100000 =  58.3923280239 s.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Co ciekawe, Python 2.5.2 okaza&#322; si&#281; najwolniejszy. Im wi&#281;cej w&#261;tk&#243;w tym jeszcze wolniej dzia&#322;a&#322;. By&#322; wolniejszy nawet od (dziwnie wolnego) Ruby 1.8.6. Ale, by&#263; mo&#380;e to jest wina bardzo wolnej biblioteki generowania losowych liczb. Ech, jak tu cokolwiek por&#243;wnywa&#263; mi&#281;dzy j&#281;zykami jak takie odkrywa si&#281; takie babole w bibliotece standardowej Pythona.&lt;/p&gt;


	&lt;p&gt;Jython by&#322;&#160;jeszcze wolniejszy. Dla 10 mln. iteracji, mimo &#380;e nie by&#322;y tworzone w pami&#281;ci &#380;adne listy, wl&#243;k&#322; si&#281; tak wolno, &#380;e przerwa&#322;em test. Po zmniejszeniu iteracji o rz&#261;d wielko&#347;ci (do 1 miliona) uzyska&#322; wyniki takie jak Ruby 1.8.6 dla 10 milion&#243;w iteracji. Jython jest najwyra&#378;niej jeszcze bardzo s&#322;abo zoptymalizowany. Pomys&#322;y aby na nim odpala&#263; frameworki takie jak Django, to na razie raczej przedwczesny pomys&#322;.&lt;/p&gt;


	&lt;p&gt;Iterations: 1,000,000 instead of 10,000,000:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ jython main.py &amp;quot;`jython --version`&amp;quot; 1000000
Jython 2.2.1 on java1.6.0_05

  10 thread(s) x    100000 =  6.391000032424927 s.
  50 thread(s) x     20000 =  4.368000030517578 s.
 100 thread(s) x     10000 =  4.352999925613403 s.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 26 Jul 2008 13:22:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:f3cdd08b-0fa8-4545-aa1a-8a2fcb4903ca</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python</link>
      <category>ruby</category>
      <category>python</category>
      <category>jruby</category>
      <category>jython</category>
      <category>java</category>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@Hawkerb: &lt;a href="http://redmine.ruby-lang.org/repositories/annotate/ruby-19/thread.c" rel="nofollow"&gt;Ruby 1.9 potrafi ju&#380;&lt;/a&gt; wykorzystywa&#263; natywne w&#261;tki systemu operacyjnego.&lt;/p&gt;</description>
      <pubDate>Thu, 23 Oct 2008 12:07:54 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:647a84ab-0186-4898-8c99-bdf440694b16</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1842</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Hawkerb</title>
      <description>&lt;p&gt;Ten caly test to jakas kpina i przejaw ignorancji. Jakim cudem niby ten test ma m&#243;wi&#263; o pr&#281;dko&#347;ci w&#261;tk&#243;w w rubym 1.8 i 1.9 skoro OBIE implementacje maj&#261; global interpreter lock, czyli &lt;strong&gt;nigdy&lt;/strong&gt; dwa w&#261;tki nie s&#261; uruchomione jednocze&#347;nie (nawet na 2,4 czy 16 rdzeniach)?! Zreszt&#261;, przecie&#380; to WIDAC w wynikach &amp;#8211; czas ruby1.9 jest prawie identyczny dla 1 watku i 20.&lt;/p&gt;


	&lt;p&gt;O tym, ze dane autor uzywa puts w benchmarku, mierzy czas za pomoca Time.now i stosuje random w glownej petli, nie bede pisal, bo nie ma po co.&lt;/p&gt;


	&lt;p&gt;Jednym zdaniem, jesli chodzi o porownywanie wydajnosci implementacji rubiego, to ten artykul nie ma zadnej wartosci (a co do innych jezykow, to szkoda mi czasu analize).&lt;/p&gt;</description>
      <pubDate>Sun, 19 Oct 2008 16:20:40 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:07b23203-5b4b-4e04-8598-e20c5ff06aed</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1835</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;Przyk&#322;ad z w&#261;tkami raczej nie nadaje si&#281; na pierwszy rzut dla kogo&#347; kto nie zna j&#281;zyka. Ruby jest bardziej skomplikowanym j&#281;zykiem od Pythona, wiadomo. Ale jak ju&#380; si&#281; go opanuje to Ruby potrafi by&#263; bardziej zwarty i pi&#281;kniejszy od Pythona.&lt;/p&gt;</description>
      <pubDate>Tue, 02 Sep 2008 18:39:52 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:d5e7e411-d32f-4f93-bc5e-55613c29789b</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1787</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by salmon</title>
      <description>&lt;p&gt;Mo&#380;liwe, ale ten Tw&#243;j przyk&#322;ad z w&#261;tkami jest dla mnie ma&#322;o czytelny, a w przypadku Pythona potrafi&#322;em zrozumie&#263; dzia&#322;anie programu, nie znaj&#261;c jeszcze tego j&#281;zyka :)&lt;/p&gt;</description>
      <pubDate>Mon, 01 Sep 2008 17:45:41 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:19763c89-efa4-49f6-9596-fcafabfef74e</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1781</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@salmon: Zale&#380;y co. Polemizowa&#322;bym. Ruby potrafi by&#263; r&#243;wnie&#380; czytelniejszy od Pythona.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Sep 2008 15:23:11 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:eea0d1d1-3486-4342-95b8-b2ead952bcbb</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1780</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by salmon</title>
      <description>&lt;p&gt;&amp;gt;Po drugie, to Ruby pozwala na pisanie kr&#243;tszego kodu od Pythona, a nie odwrotnie.&lt;/p&gt;


	&lt;p&gt;Ale nie jest taki czytelny :p&lt;/p&gt;</description>
      <pubDate>Mon, 01 Sep 2008 14:27:02 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:46fe5f11-5cb7-49e8-b494-cffc185985ad</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1779</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@rmz: Po pierwsze, tw&#243;j zarzut co do benchmarka jest bez sensu, co do generowania liczb losowych Python u&#380;ywa &lt;strong&gt;takiego samego algorytmu&lt;/strong&gt;, co Ruby (Mersenne Twister). Po drugie, to Ruby pozwala na pisanie kr&#243;tszego kodu od Pythona, a nie odwrotnie.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Aug 2008 15:53:30 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:4e790876-5ca2-4dec-a99d-cb4318dadb2a</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1774</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by rmz</title>
      <description>&lt;p&gt;1. Si&#322;&#261; Pythona nie jest jego szybko&#347;&#263;, jest wr&#281;cz wolny, ale ma inne zalety dla kt&#243;rych go stosuj&#281;, a jak co&#347; ma dzia&#322;a&#263; wydajnie to mo&#380;na to dopisa&#263; np. w C lub asemblerze
2. Benchmark jest zrobiony beznadziejnie, algorytm generowania liczb losowych w tych j&#281;zykach jest na pewno r&#243;&#380;ny, a kt&#243;ry lepszy? nie wiem ale wygl&#261;da &#380;e w Rubym widocznie jest gorsz bo szybszy
3. Wg mnie jedn&#261; zalet Pythona jest to &#380;e kod mo&#380;na zapisa&#263; w mniejszej ilo&#347;ci ni&#380; w innych j&#281;zykach. 10 w Pythonie 100 w Rubym?(Nie znam Rubiego &amp;#8211; zgaduj&#281;)
Za jaki&#347; czas pewnie i tak si&#281; oka&#380;e &#380;e to w jakim j&#281;zyk piszemy jest bez znaczenia bo czy napiszemy to w j&#281;zyku A, B, C czy D i tak ostatecznie da si&#281; skompilowa&#263; do tego samego &amp;#8220;czego&#347;&amp;#8221; co da nam taki sam efekt ko&#324;cowy lub dowolnie i automatycznie przet&#322;umaczy&#263; z j&#281;zyka A do B a potem do Y. To tylko kwestia odpowiednich kompilator&#243;w i edytor&#243;w u&#322;atwiaj&#261;cych prac&#281;. Ale to tylko moje przypuszczenia.&lt;/p&gt;</description>
      <pubDate>Fri, 22 Aug 2008 13:25:19 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:c20b6b01-c988-46d9-9e90-3a8a78d9cf19</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1773</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by lopex</title>
      <description>&lt;p&gt;Lepsza wydajno&#347;&#263; 2.5.1a to g&#322;&#243;wnie praca nad runtimem. ASM wnosi tylko tyle &#380;e po refactoringu i u&#380;yciu api ASM kod jest czytelniejszy, wcze&#347;niej w &#378;r&#243;d&#322;ach jythona by&#322;y tragiczne addByte(234), itp.&lt;/p&gt;</description>
      <pubDate>Wed, 20 Aug 2008 15:27:54 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:d3a30a1d-7304-4c7b-8c10-09a02c4d7a07</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1772</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by jellonek</title>
      <description>&lt;p&gt;uzywanie jythona 2.2.1 w czasie gdy nie jest od dobrych kilku miesiecy rozwijany jest conajmniej dziwne&amp;#8230; trzeba bylo probowac 2.5.1a, choc teraz mozna spokojnie wersji z trunka sprobowac (dopiero &amp;#8220;na dniach&amp;#8221; wersja 2.5.1 przeszla do trunka z branch/asm).
roznica jest ogromna, nawet przy tescie specjalnie przygotowanym by pokazac wyzszosc ruby nad pythonem ;)
tak wiec &amp;#8211; czekam na aktualizacje, tudziez nowy wpis do bloga ;)&lt;/p&gt;</description>
      <pubDate>Wed, 20 Aug 2008 11:32:20 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:340f532c-7c1b-44e1-b4d0-1f5279fb8938</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1771</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by lopex</title>
      <description>&lt;p&gt;@iddqd &amp;#8220;Generator liczb losowych Ruby jest stosunkowo ma&#322;o losowy&amp;#8221;. Jak to ? MT to jeden z najlepszych generator&#243;w pseudolosowych jakie istniej&#261; (o ile nie najlepszy w swojej klasie) i przeszed&#322; wszystkie die hard testy i cho&#263; nie przydaje si&#281; w kryptografi, znakomicie sprawdza si&#281; cho&#263;by w Monte Carlo.&lt;/p&gt;</description>
      <pubDate>Tue, 19 Aug 2008 13:30:06 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:8171c4f8-1391-4efa-bc2d-d31b43c73825</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1770</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by iddqd</title>
      <description>&lt;p&gt;Spoko blog ale za przeprowadzanie test&#243;w to raczej si&#281; nie bierz bo wygl&#261;da na to, &#380;e g&#243;ry zak&#322;adasz wynik i nie znasz wystarczaj&#261;co bebech&#243;w.&lt;/p&gt;


	&lt;p&gt;Generator liczb losowych Ruby jest stosunkowo ma&#322;o losowy( w por&#243;wnaniu do Pythona) a przez to szybki. 
Produkcja takich test&#243;w i takich &lt;a href="http://blog.zabiello.com/articles/2007/04/02/postgresql-vs-mysql-vs-mssql2k" rel="nofollow"&gt;http://blog.zabiello.com/articles/2007/04/02/postgresql-vs-mysql-vs-mssql2k&lt;/a&gt; obni&#380;a warto&#347;&#263; bloga.&lt;/p&gt;</description>
      <pubDate>Mon, 18 Aug 2008 14:56:31 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:4be2cc7e-d81a-4323-acd1-bffc9bc4cd9b</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1769</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@rmz: Zdecydowanie ci si&#281; pomiesza&#322;o. Jest dok&#322;adnie odwrotnie. Istnienie &amp;#8220;jednej drogi&amp;#8221; to filozofia Pythona, a nie Rubiego. Zobacz &lt;a href="http://www.python.org/dev/peps/pep-0020/" rel="nofollow"&gt;PEP20&lt;/a&gt;, pkt.13.&lt;/p&gt;</description>
      <pubDate>Mon, 18 Aug 2008 06:29:11 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a9a5bb9f-d69e-43cb-8e90-316fa7140ceb</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1768</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by rmz</title>
      <description>&lt;p&gt;1. Test jest skopany, generowanie liczb losowych to nie taka prosta sprawa, test mo&#380;e tylko rodzi&#263; przypuszczenie &#380;e w Pythonie zastosowano lepszy algorytm a w Rubym gorszy do generowania liczb losowych. (Mo&#380;e w Rubym jest skopany?) Element losowy nale&#380;y w tego rodzaju testach wyeliminowa&#263;. Zrozumia&#322; bym gdyby&#347; np. testowa&#322; bazy danych a tylko zestaw danych przyk&#322;adowych by&#322; by generowany.&lt;/p&gt;


	&lt;p&gt;2. Od kiedy to &amp;#8220;Jython jest kolejnym przyk&#322;adam ca&#322;kowitej ignorancji za&#322;o&#380;e&#324; j&#281;zyka Python (o istnieniu jednej, oczywistej drogi do tego samego celu)&amp;#8221; my&#347;la&#322;em &#380;e &amp;#8220;istnienie jednej drogi&amp;#8221; to filozofia Rubiego a nie Pythona, ale mo&#380;e co&#347; przeoczy&#322;em.&lt;/p&gt;</description>
      <pubDate>Sun, 17 Aug 2008 17:15:04 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:2aae4e85-8677-4ffe-968b-11e6ad66c9ae</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1767</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by lopex</title>
      <description>&lt;p&gt;W tej chwili java.util.Random (MRI u&#380;ywa Mersenne Twister&amp;#8217;a kt&#243;ry, btw, jest du&#380;o szybszy &amp;#8211; shufluje du&#380;e s&#322;owo co 624 wo&#322;a&#324; a normalnie robi 4 xory i 4 przesuni&#281;cia co powoduje doskona&#322;&#261; utylizacj&#281; cache&amp;#8217;a). W tej chwili JRuby nie u&#380;ywa arity split dla Kernel#rand (a wi&#281;c jest narzut sprawdzania arno&#347;ci i bardzo du&#380;y narzut &amp;#8220;boxingu&amp;#8221; w tablic&#281; argument&#243;w). W wolnej chwili zakomituj&#281; javow&#261; wersj&#281; MT i &lt;em&gt;du&#380;o&lt;/em&gt; szybszy dispatch w Kernel#rand (w zasadzie to on jest w&#261;skim grad&#322;em tutaj a nie generator).&lt;/p&gt;</description>
      <pubDate>Tue, 12 Aug 2008 14:41:49 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:ff87c132-4eb3-4b25-a481-d5208a62477e</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1765</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by jc</title>
      <description>&lt;p&gt;&amp;#8220;Jython jest najwyra&#378;niej jeszcze bardzo s&#322;abo zoptymalizowany. Pomys&#322;y aby na nim odpala&#263; frameworki takie jak Django, to na razie raczej przedwczesny pomys&#322;.&amp;#8221; &amp;#8211; nie sprawdza&#322;em i nie wiem, jak dzia&#322;a Django na Jythonie, ale wysnuwanie takich wniosk&#243;w na podstawie mikrotestu generatora liczb losowych jest co najmniej komiczne ;)&lt;/p&gt;


	&lt;p&gt;Tak z ciekawo&#347;ci, jakiego algorytmu u&#380;ywa Ruby/JRuby do generowania liczb losowych?&lt;/p&gt;</description>
      <pubDate>Tue, 12 Aug 2008 13:56:42 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a236cb82-e4a6-40e4-8ba7-cbb70ae69a8a</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1764</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by wysek</title>
      <description>&lt;p&gt;&amp;#8220;Co nie wybra&#263;, to problem.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Ano, nie ma letko;)
Testowanie to nie jest taka prosta czynno&#347;&#263;, &#380;e si&#281; napisze test i odpali.
Trzeba jeszcze czasem troch&#281; pomy&#347;le&#263; ;)&lt;/p&gt;</description>
      <pubDate>Tue, 12 Aug 2008 10:01:41 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:00d15fa7-f100-407d-968f-ee92e6d3f8ab</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1763</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@Marek Kubica: co z tego, &#380;e Python u&#380;ywa w&#261;tk&#243;w skoro GIL nie pozwala im wykorzysta&#263; pe&#322;ni mo&#380;liwo&#347;ci maszyn wieloprocesorowych/wielordzeniowych?&lt;/p&gt;


	&lt;p&gt;@JO: Widz&#281;, &#380;e&#347; nie zauwa&#380;y&#322;, &#380;e w update do tekstu zmieni&#322;em kod i ju&#380; nie ma sortowania. Zosta&#322;o samo generowanie liczb losowych. Niestety, jak nie urok to sraczka. Okaza&#322;o si&#281; &#380;e tym razem Python ma (pono&#263;) wolny generator liczb losowych. Co nie wybra&#263;, to problem. Panie Oboza, sam sobie napisz dok&#322;adne i obiektywne testy jak masz na to czas.&lt;/p&gt;


	&lt;p&gt;Z innej beczki.
Zapu&#347;ci&#322;em ostatnio ten m&#243;j kod na Solarisie (Sparc, 32GB, 64 rdzeni) Mam tam tylko Jav&#281; i JRuby wi&#281;c ograniczy&#322;em si&#281; do tego. Zauwa&#380;y&#322;em, &#380;e JRuby nie wykorzystuje pe&#322;nych zasob&#243;w maszyny. Java, bez problemu poch&#322;on&#281;&#322;a pe&#322;ne 100% czasu rdzeni.&lt;/p&gt;</description>
      <pubDate>Thu, 31 Jul 2008 11:23:48 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:b1a97a74-c517-4461-895d-b7cc586f59ce</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1761</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by JO</title>
      <description>&lt;p&gt;Ps. Ten test polega na samym sortowaniu i roznice / zyski sa na poziomie 10%-14% to oznacza ze pana test panie Zabie&#322;&#322;o jest &#322;adnie pisz&#261;c do bani, bo implementacja sort mo&#380;e by&#263; r&#243;&#380;na proponuje aby wykorzysta&#322; pan jakis text albo strone i j&#261; parsowa&#322; jakas swoja metoda kt&#243;ra jest powtarzalna i katuj&#261;ca mocno dla procesora, wtedy b&#281;dzie mo&#380;na efekty porownywa&#263;.&lt;/p&gt;


	&lt;p&gt;Jak u nas ktos na programowaniu rownoleglym przyniosl program ktory po zrownolegleniu mial przyrost szybkosci &amp;lt; 25% to w ogole prowadzacy mowil mu &amp;#8220;nara&amp;#8221; :)))&lt;/p&gt;


	&lt;p&gt;Prosze poprawic test !!!&lt;/p&gt;</description>
      <pubDate>Wed, 30 Jul 2008 10:40:53 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:33365b3b-2ab9-4fdd-9446-e7be5fe89fdb</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1759</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Marek Kubica</title>
      <description>&lt;p&gt;Jeszcze wymienie ze Python uzywa juz od dawna watki POSIX:&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://docs.python.org/lib/module-thread.html" rel="nofollow"&gt;http://docs.python.org/lib/module-thread.html&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 30 Jul 2008 07:36:24 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:0449110f-9894-4a1a-906c-f4d45a4065d4</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1758</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@Adam Olsen: I have updated the article. 
I got rid off sorting and list creation. I have only random number generation. But as David Koblas pointed out, it looks like Python has slow random number generator.&lt;/p&gt;


	&lt;p&gt;@Peter Cooper: I have no idea why Ruby 1.8.7 is so slow. On my MBP Core2Duo, 2.16 GHz &amp;#38; Mac OS X 10.5.4, Ruby 1.8.7 is even 6x slower than Ruby 1.8.6!&lt;/p&gt;</description>
      <pubDate>Wed, 30 Jul 2008 03:09:51 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:11b57540-acd4-4dcd-b17f-acc38f23b341</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1757</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by david koblas</title>
      <description>&lt;p&gt;Wrote a blog post, but most of the performance difference in this benchmark is because random is a native python library which is slow.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.skitoy.com/p/python-vs-ruby-performance/172" rel="nofollow"&gt;http://www.skitoy.com/p/python-vs-ruby-performance/172&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 29 Jul 2008 23:12:18 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:c5dfbc43-e08a-4d18-8afe-1aa4c470eb33</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1756</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Peter Cooper</title>
      <description>&lt;p&gt;I&amp;#8217;m confused why Ruby 1.8.7 is so slow on this. I get similar numbers to you for the Python version, but my Ruby 1.8.6 (which is little different to 1.8.7) gets 2.85s.&lt;/p&gt;</description>
      <pubDate>Tue, 29 Jul 2008 16:26:49 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:efcf4e31-a613-4b50-b4ae-424a40045d75</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1755</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by Adam Olsen</title>
      <description>&lt;p&gt;I apologize for commenting in english, but I&amp;#8217;ve a few points I believe are important.&lt;/p&gt;


	&lt;p&gt;1.  The random implementation may be the dominant cost here.  Creating a random list before creating the child threads, and having them copy it, should help mitigate it.  You could also eliminate the threads and the sorting, just benchmarking the random number generation.
2.  In the python versions the main loop is busy-waiting, which could be soaking up a lot of CPU time (although I doubt it matters much here).  Use &amp;#8220;for t in threads: t.join()&amp;#8221; instead.
3.  You should try disabling python&amp;#8217;s tracing GC (gc.disable()).  It behaves quite badly under certain conditions.&lt;/p&gt;</description>
      <pubDate>Mon, 28 Jul 2008 23:22:17 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:ba26f569-6af4-45ea-8477-1412bd86aa88</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1753</link>
    </item>
    <item>
      <title>"Ruby, Python i natywne w&#261;tki systemu operacyjnego" by sprae</title>
      <description>&lt;p&gt;Niedawno Jaros&#322;aw Zabie&#322;&#322;o dokona&#322; testu wydajno&#347;ci r&#243;&#380;nych interpreter&#243;w Pythona i Ruby w natywnych w&#261;tkach systemu operacyjnego. Zabrak&#322;o mi tam test&#243;w IronPythona, kt&#243;ry natywne w&#261;tki jest w stanie obs&#322;u&#380;y&#263; w ramach tradycyjnej biblioteki Pythona.
&lt;a href="http://sprae.jogger.pl/2008/07/28/python-vs-ironpython-vs-watki/" rel="nofollow"&gt;http://sprae.jogger.pl/2008/07/28/python-vs-ironpython-vs-watki/&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 28 Jul 2008 18:47:58 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:df26dee0-2d57-4bae-8522-72d1c213eef3</guid>
      <link>http://blog.zabiello.com/articles/2008/07/26/threads-ruby-python#comment-1752</link>
    </item>
  </channel>
</rss>
