<?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: Tag jython</title>
    <link>http://blog.zabiello.com/articles/tag/jython</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>S&#322;oneczna przysz&#322;o&#347;&#263; dla Jythona</title>
      <description>&lt;p&gt;Od czasu odej&#347;cia &lt;a href="http://hugunin.net/story_of_jython.html"&gt;tw&#243;rcy Jythona&lt;/a&gt;, Jima Hugginsa, do firmy Microsoft (do prac na &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython"&gt;IronPythonem&lt;/a&gt;), rozw&#243;j &lt;a href="http://en.wikipedia.org/wiki/Jython"&gt;Jythona&lt;/a&gt; , (javowej implementacji &lt;a href="http://python.org"&gt;Pythona&lt;/a&gt;) mocno zwolni&#322; i zosta&#322; sporo w tyle za wychodz&#261;cymi kolejnymi wersjami CPythona. Dlatego sympatycy Pythona z pewno&#347;ci&#261; si&#281; uciesz&#261; wiadomo&#347;ci&#261; o tym, &#380;e &lt;a href="http://headius.blogspot.com/2008/03/welcome-pythonistas-to-sun.html"&gt;firma Sun zatrudni&#322;a&lt;/a&gt; na pe&#322;en etat &lt;a href="http://fwierzbicki.blogspot.com/"&gt;Franka Wierzbickiego&lt;/a&gt;, b&#281;d&#261;cego g&#322;&#243;wnym developerem Jythona od grudnia 2005. Jest zatem spora szansa &#380;e projekt nabierze porz&#261;dnego rozp&#281;du tak, jak to si&#281; sta&#322;o z &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Od jakiego&#347; czasu developerzy &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; tak&#380;e pracuj&#261; nad uruchomieniem swego frameworka &lt;a href="http://fwierzbicki.blogspot.com/2008/01/django-beginning-to-work-on-jython.html"&gt;pod Jythonem&lt;/a&gt;. Niestety aktualnie Jython jest zgodny ze starym Pythonem 2.2 i z tego powodu raczej nie zanosi si&#281; aby szybko podobne dzia&#322;ania podj&#281;li developerzy frameworka &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt; (kt&#243;ry wymaga do pracy minimum Pythona 2.4). Ale to wszystko mo&#380;e si&#281;&#160;wkr&#243;tce zmieni&#263;, skoro Jython dosta&#322; si&#281; pod skrzyd&#322;a Suna.&lt;/p&gt;</description>
      <pubDate>Mon, 03 Mar 2008 17:15:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:2927111d-047f-4dcb-8c90-089c05a3f55f</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/03/sun-jython</link>
      <category>python</category>
      <category>jython</category>
    </item>
    <item>
      <title>Django on Jython</title>
      <description>&lt;p&gt;Pythonistas chyba pozazdro&#347;cili mo&#380;liwo&#347;ci odpalenia &lt;a href="http://rubyonrails.org"&gt;Rails&#243;w&lt;/a&gt; w &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;. Trwaj&#261; prace nad uruchomieniem frameworka &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; w &lt;a href="http://www.jython.org/Project/index.html"&gt;Jythonie&lt;/a&gt;, implementacji Pythona w czystej Javie.&lt;/p&gt;


	&lt;p&gt;Zapyta&#322;em si&#281; na kanale &lt;a href="irc://irc.eu.freenode.net/pylons"&gt;#pylons&lt;/a&gt; odno&#347;nie podobnego ruchu ze strony &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;, ale okazuje si&#281; &#380;e Jython jest dosy&#263; zacofany. Od czasu przej&#347;cia jego tw&#243;rcy do Microsoftu i pracy na &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython"&gt;IronPythonem&lt;/a&gt; projekt dosy&#263; powoli si&#281; rozwija. Jython zatrzyma&#322; si&#281; na implementacji Pythona 2.2. To dosy&#263; stara wersja zwa&#380;aj&#261;c, &#380;e w mi&#281;dzyczasie wysz&#322;y wersje 2.3, 2.4 i 2.5. Pylons wymaga zgodno&#347;ci min. z Pythonem 2.4. Nie wiem jak ten problem rozwi&#261;&#380;&#261; przy przenoszeniu Django, bo co&#347; nie chce mi si&#281; wierzy&#263; &#380;e jest w pe&#322;ni zgodny ze starym Pythonem 2.2.&lt;/p&gt;</description>
      <pubDate>Tue, 08 Jan 2008 04:34:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:4159d4c3-fcd0-442c-9d15-f96ae24099ea</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/01/08/django-on-jython</link>
      <category>django</category>
      <category>python</category>
      <category>jython</category>
      <category>java</category>
    </item>
    <item>
      <title>Jython 2.2beta1</title>
      <description>&lt;p&gt;Pog&#322;oski o przedwczesnej &#347;mierci Jythona (javowej implementacji &lt;a href="http://python.org"&gt;Pythona&lt;/a&gt;),  s&#261; chyba przesadzone. W&#322;a&#347;nie wysz&#322;a kolejna wersja &lt;a href="http://www.jython.org/Project/index.html"&gt;2.2 beta1&lt;/a&gt;. Instalacja:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;java&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;jar&lt;/span&gt; &lt;span class="ident"&gt;jython_installer&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="number"&gt;2.2&lt;/span&gt;&lt;span class="ident"&gt;b1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;jar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 09 Feb 2007 22:51:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:aac669f6-93d2-4f57-93d6-df464b92030d</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2007/02/09/jython-2-2beta1</link>
      <category>jython</category>
      <category>java</category>
      <category>python</category>
    </item>
  </channel>
</rss>
