

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

<channel>
	<title>Rodrigo Kumpera Weblog &#187; mono</title>
	<atom:link href="http://www.kumpera.net/blog/index.php/category/mono/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kumpera.net/blog</link>
	<description>Meus achados sobre tecnologia</description>
	<lastBuildDate>Thu, 10 Jun 2010 04:33:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Implementando Haskell em VMs tradicionais (parte 2)</title>
		<link>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/</link>
		<comments>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 23:30:36 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=149</guid>
		<description><![CDATA[Retomando a questão sobre como implementar Haskell em VMs tradicionais, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado [...]]]></description>
			<content:encoded><![CDATA[<p>Retomando a questão sobre <a href="http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/">como implementar Haskell em VMs tradicionais</a>, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado quando for usado, mesmo entre chamadas funções. Vejamos um exemplo simples:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">square a <span style="color: #339933; font-weight: bold;">=</span> a <span style="color: #339933; font-weight: bold;">*</span> a
&nbsp;
square<span style="color: #339933; font-weight: bold;">_</span>of<span style="color: #339933; font-weight: bold;">_</span>sum a b <span style="color: #339933; font-weight: bold;">=</span> square <span style="color: green;">&#40;</span>a <span style="color: #339933; font-weight: bold;">+</span> b<span style="color: green;">&#41;</span></pre></div></div>

<p>Nesse exemplo, quando square_of_sum chama square, o parâmetro passado não é o resultado de a + b, mas sim algo próximo a uma closure que irá calcular a + b. Quando square for avaliada, ela precisará do valor de &#8216;a&#8217;, então usará a closure que recebeu como parâmetro para tal. Ou melhor, funciona quase assim, Haskell implementa um mecanismo chamado call-by-need, que resolve o valor uma única vez na primeira vez que for necessário memorizando o resultado. Isso significa que no caso de square &#8216;a&#8217; será avaliada uma única vez. Por conta da memorização, não usamos o termo closure, mais sim thunk para descrever o que uma função passa para outra.</p>
<p>Outro detalhe importante, chamadas de função também são lazy evaluated, então tanto square, quanto square_of_sum na verdade retornam thunks para os valores em questão. Essa coisa toda pode parecer extremamente ineficiente a primeira vista e de fato é. Tanto que o GHC gera código sem uso de thunk sempre que conseguir provar que um pedaço de código pode ser strict evaluated [1].</p>
<p>Antes de imaginar como implementar isso em uma VM como a CLR, vamos traduzir nosso exemplo para C# [2]:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
<span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">bool</span> resolved<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> Thunk <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>resolved<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				resolved <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_of_sum <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a_plus_b <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">+</span> b.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">return</span> square <span style="color: #000000;">&#40;</span>a_plus_b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Já que square produz um thunk, não precisamos criar outro.</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Bem confuso, de certo. Primeiro a implementação de Thunk, simples e direta, já square_of_sum precisa de uma variável local para ficar minimamente legível. Uma coisa é fato, C# não foi feita para ser usada com lazy evaluation.</p>
<p>Existe alguns problema quanto a eficiencia de fazer dessa forma. O maior deles é como lidar quando alguns valores já estão resolvidos e temos ainda assim criar um thunk para satisfazer o função chamada. A forma como GHC lida isso é passando todos parâmetros boxed de forma que é possível misturar thunks e valores sem problema. A função square, do nosso exemplo anterior ficaria assim:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #FF0000;">int</span> val<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>a <span style="color: #008000;">is</span> <span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>a<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">else</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#41;</span>a<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
		<span style="color: #0600FF;">return</span> val <span style="color: #008000;">*</span> val<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Outra forma de também lidar com esse problema é criar duas versões da mesma função, uma que recebe valores resolvidos e outra apenas thunks. Fazer dessa forma é vantagem quando podemos provar o uso estrito dos valores em questão. Por fim, acho que o maior problema ser achar uma forma de representar um thunk usando o mínimo possível de memória.</p>
<p>No nosso exemplo, em uma plataforma 32bits, Trunk<T> usa 20 bytes, Func<T> usa mais 40 e outros 8 da closure[3]. Ou seja, começa usando 68, coisa pacas. Podemos fazer algumas mudanças nisso. Dado que não existe null em Haskell podemos remover o atributo resolved e simplesmente verificar se closure é ou não null. Segundo, em vez criar 1 delegate toda vez podemos fazer caching dele e armazenar as variáveis capturadas no próprio thunk. Algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">abstract <span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">public</span> abstract T Value <span style="color: #000000;">&#123;</span> get<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> ThunkWithVars<span style="color: #008000;">&lt;</span>T,V<span style="color: #008000;">&gt;</span> <span style="color: #008000;">:</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>V, T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	V vars<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> ThunkWithVars <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>V,T<span style="color: #008000;">&gt;</span> closure, V vars<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">vars</span> <span style="color: #008000;">=</span> vars<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>closure <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span>vars<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
				vars <span style="color: #008000;">=</span> <span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>V<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">static</span> Func<span style="color: #008000;">&lt;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span>, <span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_resolve <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>a<span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> ThunkWithVars<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span>, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;&gt;</span> <span style="color: #000000;">&#40;</span>square_resolve, a<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Usando essa codificação Thunk continua usando 20 bytes porém nos livramos dos demais objetos, um ganho de 70% no final das contas. Poderíamos economizar outros 4 se juntarmos as variáveis closure e value em uma só caso T fosse do tipo referência &#8211; ou manter o resultado boxed. Mesmo sem isso, 20 bytes já é um valor razoável, conseguir o mesmo em uma JVM é basicamente impossível sem muita ginástica.</p>
<p>Qual a performance dessa solução? Segundo o pessoal do GHC, em média 95%-98% dos thunks gerados são resolvidos. Com um generational GC, a maioria vira lixo efêmero. Ou seja, não existe muita razão para uma VM tradicional ser mais lenta que a do GHC, o principal fator nesse caso é, sem dúvida, o compilador, que pode gerar pedaços de código inteiros sem uso de thunk.</p>
<p>[1] É muito comum em Haskell gerar código que não funciona sem lazy evaluation, como geradores de listas infinitas.<br />
[2] Nesse exemplo vou trapacear e tornar as funções mono-mórficas e usar int no lugar de Number para simplificar o código.<br />
[3] Nesse caso estou ignorando quanto de memória as variáveis capturadas usam.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementando Haskell em VMs tradicionais (parte 1)</title>
		<link>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:49:24 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[clr]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=138</guid>
		<description><![CDATA[Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir [...]]]></description>
			<content:encoded><![CDATA[<p>Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir um deles, type classes.</p>
<p>Uma type class para os acostumados com OO pode ser vista como uma interface cuja implementações são externas aos tipos que estão atrelados. Um exemplo bem simples é Eq, que permite compar objetos do mesmo tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">class</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">==</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">/=</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">::</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: #cccc00; font-weight: bold;">Bool</span>
    x <span style="color: #339933; font-weight: bold;">/=</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">==</span> y<span style="color: green;">&#41;</span>
    x <span style="color: #339933; font-weight: bold;">==</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">/=</span> y<span style="color: green;">&#41;</span></pre></div></div>

<p>Para nos não iniciado em Haskell, linha um define a classe Eq e diz que ela possui um parâmetro polimófico; linha 2 diz que Eq tem 2 funções, &#8220;==&#8221; e &#8220;/=&#8221; cuja assinatura são dois valores do tipo &#8216;a&#8217; e retorna um booleano; por fim, linhas 3 e 4 são implementações padrão das funções. Seria o equivalente, em pseudo-C#, ao seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">==</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">!=</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">!=</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">==</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Uma das vantagens de type classes no Haskell é que elas podem fornecer implementações padrão para alguns de seus métodos. Bom, agora que temos Eq definida, para dizer que Listas a implementa usamos algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">instance</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #339933; font-weight: bold;">=&gt;</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> <span style="color: green;">&#91;</span>a<span style="color: green;">&#93;</span> <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> True
    <span style="color: green;">&#40;</span>x:xs<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#40;</span>y:ys<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> x<span style="color: #339933; font-weight: bold;">==</span>y <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> xs<span style="color: #339933; font-weight: bold;">==</span>ys
    <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">=</span> False</pre></div></div>

<p>Aqui vemos uma das melhores características do Haskell é explorada, que é pattern matching &#8211; e isso também é assunto para outro artigo. Como pode se notar, uma implementação de uma dada type class não está embutida na definição do tipo em questão, ou seja, não podemos interfaces como a CLR ou a JVM suportam.</p>
<p>A idéia é representar type classes de forma semelhante a como o ghc faz, usando dictionary passing[1], que é bem simples de entender e implementar. Para cada type class que uma função recebe nos seus parâmetros, passamos junto um objeto que representa as operações em questão. Em C# teríamos:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> dict, T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>dict.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Existe alguns problemas aqui, primeiro que estamos passando um parâmetro extra e segundo que não é possível eliminar a verificar por null pointer caso op_eq seja inlined. A solução é razoavelmente simples no caso do C#:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">struct</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T, TD<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> where TD<span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>TD<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>A grande mudança aqui é tornar a instância da typeclass um valuetype e construir um valor default para satisfazer o compilador. É uma pena que não podemos simplesmente chamar um método estático e TD, o que é uma limitação boba da CLR. Essa solução não é possível na JVM devido a inexistência de valuetypes e generics.</p>
<p>E quanto a performance dessa solução? Bom, no caso do mono, o JIT&#8217;er reconhece as chamadas como não virtuais e é capaz de fazer inline de forma bem agressiva &#8211; exatamente como desejado. Eu pensei em fazer um comparativo dessa solução com o equivalente em Java, mostrando como a CLR permite codificar tipos muito mais ricos e interessantes que a JVM &#8211; e como isso se traduz em performance. Mas realmente não estou afim de criar motivo para um flamewar por parte dos javeiros de plantão.</p>
<p>[1]Esse é o paper original que descreve type classes e a técnica utilizada: http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lançado Mono 2.2 com estréia de Mono.Simd</title>
		<link>http://www.kumpera.net/blog/index.php/2009/01/14/lancado-mono-22-com-estreia-de-monosimd/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/01/14/lancado-mono-22-com-estreia-de-monosimd/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 01:36:43 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[mono simd programming performance]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=125</guid>
		<description><![CDATA[Acabou de ser lançado versão 2.2 do Mono. Foram vários meses de trabalho e muito suor em corrigir centenas de bugs para podermos fazer nosso melhor release de todos os tempos. Dentro das novidades gostaria de destacar duas relativa ao time que participo. A primeira é o novo JIT baseado em uma representação intermediaria linear, [...]]]></description>
			<content:encoded><![CDATA[<p>Acabou de ser l<a href="http://www.mono-project.com/Release_Notes_Mono_2.2">ançado versão 2.2 do Mono</a>. Foram vários meses de trabalho e muito suor em corrigir centenas de bugs para podermos fazer nosso melhor release de todos os tempos. Dentro das novidades gostaria de destacar duas relativa ao time que participo. A primeira é o novo JIT baseado em uma representação intermediaria linear, os ganhos de performance podem chegar em até 50% e, também importante, o código do JIT ficou muito mais simples e extensível.  A segunda novidade, resultado da maior flexibilidade do mono, é a disponibilização preliminar da biblioteca Mono.Simd, que permite usar a unidade vetorial de processadores modernos.</p>
<p>A impossibilidade utilizar a unidade vetorial a partir de linguagens gerenciadas sempre foi uma das principais críticas dos desenvolvedores C e C++ sob a viabilidade em utilizá-las para código rico em calculo matemático. Isso agora é passado e usando mono e C# é possível gerar código com de alta performance similar ao possível com linguagens de baixo nível.</p>
<p>Para se ter uma ideia das possibilidades, um simples exemplo que transforma uma série de vetores com uma mesma matriz chega a ser 3x mais rápido usando Mono.Simd que o código não vetorial em C, Java ou C#. Isso sem perder as vantagens de se utilizar uma linguagem de alto nível e segura. Mas vamos ao código:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008080; font-style: italic;">//Primeiro transformação usando ponto flutuante normal</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Transform <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> Matrix matrix, <span style="color: #0600FF;">ref</span> Vector vector, <span style="color: #0600FF;">ref</span> Vector result<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        result.<span style="color: #0000FF;">x</span> <span style="color: #008000;">=</span> vector.<span style="color: #0000FF;">x</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m00</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">y</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m01</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">z</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m02</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">w</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m03</span><span style="color: #008000;">;</span>
        result.<span style="color: #0000FF;">y</span> <span style="color: #008000;">=</span> vector.<span style="color: #0000FF;">x</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m10</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">y</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m11</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">z</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m12</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">w</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m13</span><span style="color: #008000;">;</span>
        result.<span style="color: #0000FF;">z</span> <span style="color: #008000;">=</span> vector.<span style="color: #0000FF;">x</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m20</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">y</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m21</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">z</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m22</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">w</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m23</span><span style="color: #008000;">;</span>
        result.<span style="color: #0000FF;">w</span> <span style="color: #008000;">=</span> vector.<span style="color: #0000FF;">x</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m30</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">y</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m31</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">z</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m32</span> <span style="color: #008000;">+</span> vector.<span style="color: #0000FF;">w</span> <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">m33</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #008080; font-style: italic;">//Agora usando Mono.Simd</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Transform <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> Matrix4f matrix, <span style="color: #0600FF;">ref</span> Vector4f vector, <span style="color: #0600FF;">ref</span> Vector4f result<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        Vector4f v <span style="color: #008000;">=</span> vector<span style="color: #008000;">;</span>
&nbsp;
        Vector4f r0 <span style="color: #008000;">=</span> v.<span style="color: #0000FF;">Shuffle</span> <span style="color: #000000;">&#40;</span>ShuffleSel.<span style="color: #0000FF;">XFromX</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">YFromX</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">ZFromX</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">WFromX</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        Vector4f r1 <span style="color: #008000;">=</span> v.<span style="color: #0000FF;">Shuffle</span> <span style="color: #000000;">&#40;</span>ShuffleSel.<span style="color: #0000FF;">XFromY</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">YFromY</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">ZFromY</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">WFromY</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        Vector4f r2 <span style="color: #008000;">=</span> v.<span style="color: #0000FF;">Shuffle</span> <span style="color: #000000;">&#40;</span>ShuffleSel.<span style="color: #0000FF;">XFromZ</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">YFromZ</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">ZFromZ</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">WFromZ</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        Vector4f r3 <span style="color: #008000;">=</span> v.<span style="color: #0000FF;">Shuffle</span> <span style="color: #000000;">&#40;</span>ShuffleSel.<span style="color: #0000FF;">XFromW</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">YFromW</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">ZFromW</span> <span style="color: #008000;">|</span> ShuffleSel.<span style="color: #0000FF;">WFromW</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
        r0 <span style="color: #008000;">=</span> r0 <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">row0</span><span style="color: #008000;">;</span>
        r1 <span style="color: #008000;">=</span> r1 <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">row1</span><span style="color: #008000;">;</span>
        r2 <span style="color: #008000;">=</span> r2 <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">row2</span><span style="color: #008000;">;</span>
        r3 <span style="color: #008000;">=</span> r3 <span style="color: #008000;">*</span> matrix.<span style="color: #0000FF;">row3</span><span style="color: #008000;">;</span>
&nbsp;
        result <span style="color: #008000;">=</span> r0 <span style="color: #008000;">+</span> r1 <span style="color: #008000;">+</span> r2 <span style="color: #008000;">+</span> r3<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span></pre></div></div>

<p>O código usando Mono.Simd fica um pouco mais complexo, principalmente até se entender como Shuffle e outros combinadores funcionam. Porém quando executado, a versão tradicional precisa executar 16 operações de multiplicação e 12 de soma contra 4 multiplicações 3 somas simd na versão vetorizada. A diferença é clara e o números também.</p>
<p>O release 2.2 foi o resultado de muito esforço pelo time por traz do mono e todos seus contribuidores. Esse release, porém, é especial para mim pois Mono.Simd é resultado de alguns meses de trabalho meu e fiquei muito feliz com a repercussão positiva que recebemos &#8211; vários projetos estão estudando como implementar bibliotecas de matemática vetorial usando ela.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/01/14/lancado-mono-22-com-estreia-de-monosimd/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Como fazer uma linguagem dinâmica ser rápida?</title>
		<link>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/#comments</comments>
		<pubDate>Thu, 22 May 2008 05:09:16 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/</guid>
		<description><![CDATA[Muito se fala em como as implementações de Ruby estão ficando rápidas, que estão evoluindo rapidamente. Porém não consigo pensar em como todas elas parecem mas preocupadas em repetir o caminho das pedras que outras linguagens dinâmicas passaram em décadas passadas.
Hoje a maioria ainda está no estágio de possuir um interpretador razoável e estar começando [...]]]></description>
			<content:encoded><![CDATA[<p>Muito se fala em como as implementações de Ruby estão ficando rápidas, que estão evoluindo rapidamente. Porém não consigo pensar em como todas elas parecem mas preocupadas em repetir o caminho das pedras que outras linguagens dinâmicas passaram em décadas passadas.</p>
<p>Hoje a maioria ainda está no estágio de possuir um interpretador razoável e estar começando a investir em algum mecanismo primitivo de compilação para código nativo. Talvez a única diferença seja o uso de inline caches para resolução de nomes, que foi uma contribuição significativa do pessoal do Self no começo dos anos 90. Porém os principais resultados obtivos por pesquisas a um bom tempo, como tracing, especialização e especulação não deram as caras ainda.</p>
<p>Inline caching é uma optimização no qual o resultado da resolução de nomes, para dispatch de método por exemplo, é armazenado entre ativações distintas. O truque é introduzir uma clausula de guarda que verifica o tipo do objeto seletor e sua versão. Caches devem ser invalidados sempre que alguém alterar uma classe. Temos dois tipos de cache, os monomórficos que fazem caching de apenas uma invocação e os polimórficos, que armazenam uma série de resultados. Para melhor vamos exemplificar com pseudo código:</p>
<p><code><br />
//ruby<br />
def test (a)<br />
    a.foo<br />
end</p>
<p>//pseudo-código gerado em C# para um cache monomórfico</p>
<p>class CallSite {<br />
    Type type;<br />
    MethodInfo method;<br />
    int version;<br />
}</p>
<p>static CallSite test_site_0;</p>
<p>object test(object a) {<br />
    //guarda do cache monomórfico verifica tipo e versão<br />
    if (test_site_0.type == a.Type &#038;&#038; test_site_0.version == A.Type.version)<br />
        return method (a);<br />
    else<br />
        //ResolveAndInvoke resolve o método "foo", invoca ele e atualiza o cache<br />
        return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código gerado em C# para um cache polimórfico<br />
delegate object InlineCacheNoArg (object this_);</p>
<p>static InlineCacheNoArg test_site_0;</p>
<p>object test(object a) {<br />
    return test_site_0 (a);<br />
}</p>
<p>//pseudo-código inicial do delegate de test_site_0<br />
object test_site_0_v0 (object _this) {<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código do delegate depois de chamarmos test (99)<br />
object test_site_0_v1 (object _this) {<br />
    if (_this.Type == typeof (int) &#038;&#038; _this.version == 1)<br />
        //o dispatch aqui pode ser via um delegate dependendo da resolução<br />
        return ((int)_this).foo ();<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código do delegate depois de chamarmos test ("str")<br />
object test_site_0_v2 (object _this) {<br />
    if (_this.Type == typeof (int) &#038;&#038; _this.version == 1)<br />
        return ((int)_this).foo ();<br />
    if (_this.Type == typeof (string) &#038;&#038; _this.version == 1)<br />
        return ((string)_this).foo ();<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}<br />
</code></p>
<p>Como fica claro pelo exemplo, um cache polimórfico tem uma performance superior pois usa literais e funciona muito melhor no caso de não existir um tipo dominante entre as ativações. Aqui fica clara a limitação de uma das implementações, o JRuby não pode se dar ao luxo de gerar tantos métodos pois cada um precisa de uma classe e um classloader novos, ou seja, abusa da PermGen do Java.</p>
<p>Apesar de inline caches resultarem em ganho expressivo de performance, estão longe de produzirem algo razoável. O grande problema continua sendo o enorme custo de dispatch para código simples. A chave disso é fazer inferência dos tipos, de forma a conseguir eliminar por completo o overhead dos caches e resolução de nomes. As atuais implementações não implementam se quer inferência estática, ou seja, código como &#8220;123.to_s&#8221; é executado sem qualquer conhecimento prévio de 123.</p>
<p>O grande avanço ocorre se fizemos inferência em tempo de execução. Ou seja, instrumentamos o código para coletar os tipos que aparecem pelo código durante a execução e baseado nisso a máquina virtual gera versões mais eficientes do código. Existem duas técnicas bastante difundidas de como fazer isso, uma é via especialização parcial de métodos e a outra é via trace-based optimization.</p>
<p>Trace-based optimization é a tecnologia adotada pela Tamarin, a próxima VM de Javascript da Mozilla. De maneira sucinta, essa técnica consiste em gravar os trechos, e os tipos encontrados, que executam mais freqüentemente e gerar código eficiente baseado nessa informação. Os trechos gravados costumam incluir vários métodos diferentes e suas ativações juntas. Suas principais vantagens é a conseguir fazer inlining de métodos de maneira muito eficiente e normalmente gastar menos tempo no JIT. Porém existem uma enorme quantidade de problemas complexos de serem resolvidos como limitar expansão descontrolada da quantidade de código gerado.</p>
<p>Especialização parcial de métodos também leva em conta os métodos que executam mais freqüentemente. Os tipos dos parâmetros e valores de retorno<br />
são armazenados e posteriormente utilizados para gerar versões especializadas dos métodos em questão. Sua principal vantagem é a maior simplicidade<br />
e o fato de existir muito mais literatura e ferramentas para gerar código eficiente nestes casos. Para se ter uma idéia do poder dessa técnica um exemplo cai bem:</p>
<p><code><br />
//ruby<br />
def fun (a, b)<br />
    2 * a - b<br />
end</p>
<p>//fun é sempre chamada com números como argumento, "fun (1,2)" por exemplo.</p>
<p>//pseudo-código C# gerado inicialmente (sem usar caches)<br />
object fun_v0 (object a, object b) {<br />
    object tmp = Invoke (2, "*", a"); //_this, nome do método, argumentos<br />
    return Invoke (tmp, "-", b);<br />
}</p>
<p>//pseudo-ćodigo C# gerado após especialização:<br />
int fun_int_int (int a, int b) {<br />
    int tmp = 2 * a; //o método que implementava multiplicação foi inlined<br />
    return tmp - b;<br />
}</p>
<p>object fun_v1 (object a, object b) {<br />
    if (a.Type == typeof (int) &#038;&#038; b.Type == typeof (int) &#038;&#038; typeof (int).version == 1)<br />
        return fun_int_int ((int)a, (int)b);<br />
    object tmp = Invoke (2, "*", a"); //_this, nome do método, argumentos<br />
    return Invoke (tmp, "-", b);<br />
}<br />
</code></p>
<p>Não precisa ir muito longe para imaginar a diferença de performance entre as duas versões. Porém entre descobrir os métodos as serem especializados e gerar código de máquina existe um Just-In-Time compiler que é, surpresa, surpresa, muito trabalhoso de ser escrito para executar rapidamente e gerar código eficiente.</p>
<p>Possui um bom JIT é atualmente um grande dilema entre as implementações de ruby. Pois ao usar o JIT de máquinas virtuais maduras, como HotSpot ou mono, a implementação fica limitada ao que é possível a linguagens gerenciadas. Em contrapartida, ao não utilizá-las, construções de baixo nível como profiler e interpretador podem ser implementadas de forma muito mais eficiente.</p>
<p>Apesar de do futuro parecer muito legal, futuras VMs terão o trabalho adicional de educar a comunidade de desenvolvedores sobre como escrever código rápido em ruby. Coisas como monkey patching furam qualquer esquema de caching ou especialização pois cada objeto passa a ter uma singleton class distinta.</p>
<p>Não existe solução fácil e todas implementações tem muito chão pela frente até Ruby ter uma performance competitiva com outras linguagens dinâmicas. Soluções como as aqui apresentadas devem conseguir melhorias de uma ordem de magnitude tranquilamente, de acordo com os resultados já encontrados. Performance é um problema que é resolvido via muito suor, com uma contínua série de melhoras, atacando um pouco por vez.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Eu sobrevivi a Campus Party</title>
		<link>http://www.kumpera.net/blog/index.php/2008/02/19/eu-sobrevivi-a-campus-party/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/02/19/eu-sobrevivi-a-campus-party/#comments</comments>
		<pubDate>Wed, 20 Feb 2008 01:59:21 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[mono]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/02/19/eu-sobrevivi-a-campus-party/</guid>
		<description><![CDATA[Semana passada ocorreu a primeira edição da CampusParty brasileira aqui em São Paulo. Resolvi participar pois seria uma ótima oportunidade para reencontrar alguns amigos e mexer com coisas que não faço normalmente. Fora as pessoas que encontrei e conheci, acabei fazendo bastante coisa interessante.
No primeiro dia, vale a pena contar, que estávamos discutindo sobre a [...]]]></description>
			<content:encoded><![CDATA[<p>Semana passada ocorreu a primeira edição da CampusParty brasileira aqui em São Paulo. Resolvi participar pois seria uma ótima oportunidade para reencontrar alguns amigos e mexer com coisas que não faço normalmente. Fora as pessoas que encontrei e conheci, acabei fazendo bastante coisa interessante.</p>
<p>No primeiro dia, vale a pena contar, que estávamos discutindo sobre a abertura do evento e lembrei de toda palhaçada envolvendo o pagamento de cartões de crédito pelo ministro hacker Gilberto Gil a seus assessores diretos. Disso veio a idéia de protestarmos e surgiu o <a href="http://circuitointegrado.folha.blog.uol.com.br/arch2008-02-10_2008-02-16.html#2008_02-12_12_36_01-126780737-0">&#8220;Paga meu visa também&#8221;</a>. Minha contribuição se resumiu ao &#8220;MEU&#8221; e dar pilha aos mais criativos que estávamos comigo. Nenhum de nós imaginou que isso geraria qualquer repercussão, mas fico feliz de saber que foi o contrário.</p>
<p>Continuando, participei da criação de um pong usando Quartz Composer com o <a href="http://www.lixo.org">Villela</a> e <a  href="http://br.youtube.com/watch?v=xOC3fKSu4tU">o Fabricio</a>. Foi bem divertido e me abriu os olhos para essa ferramenta &#8211; definitivamente irei brincar mais com ela.Além disso, aprendi um pouco como usar o pure data, não consegui fazer nada razoavelmente audível, mas é um começo. Aproveitei para ajudar um desenvolvedor do Inkscape com uns problemas relacionados ao C++.</p>
<p>Fora isso descobri que escrever um seletor de instruções na mão é muito penoso e resolvi gerar o código dele a partir de um script escrito em Ruby com várias dicas do Phillip. Assim que o projeto amadurecer e tiver algo para mostrar com certeza irei escrever um artigo sobre o resultado desse experimento.</p>
<p>No geral foi uma semana muito produtiva e divertida. Fiquei inclusive com vontade de ir na edição espanhola do evento. Aos que não foram, a cobertura da imprensa poder dar uma boa idéia da dimensão que foi o CampusParty.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/02/19/eu-sobrevivi-a-campus-party/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MonoSummit2007</title>
		<link>http://www.kumpera.net/blog/index.php/2007/12/09/monosummit2007/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/12/09/monosummit2007/#comments</comments>
		<pubDate>Sun, 09 Dec 2007 19:21:51 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[mono]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/12/09/monosummit2007/</guid>
		<description><![CDATA[Semana passada ocorreu a MonoSummit2007, evento para conhecer os colegas do time, membros da comunidade, discutir sobre o mono e, principalmente, nos planejar. O evento foi uma ótima oportunidade de conhecer gente muito interessante e discutir sobre tópicos que não é normalmente possível nos eventos que acontecem por ai.
Tive o prazer de conhecer o Rodrigo [...]]]></description>
			<content:encoded><![CDATA[<p>Semana passada ocorreu a MonoSummit2007, evento para conhecer os colegas do time, membros da comunidade, discutir sobre o mono e, principalmente, nos planejar. O evento foi uma ótima oportunidade de conhecer gente muito interessante e discutir sobre tópicos que não é normalmente possível nos eventos que acontecem por ai.</p>
<p>Tive o prazer de conhecer o Rodrigo Oliveira, autor da linguagem boo. Fiquei feliz em vez que finalmente implementaram code quotation, ou quasi-quotations para quem preferir, e pattern matching, de maneira a tornar divertido o uso macros e não a tarefa penosa que era antes disso. Discutindo com ele sobre o DB4O, fiquei muito interessado na forma como eles pretendem implementar transações usando STM. Pessoalmente acho que sistemas prevalentes, o prevayler em especial, são implementações patéticas de um problema que não existe. Por outro lado, com Software Transactional Memory é possivel eliminar aquela coisa horrivel que é a exigência de toda mutação ocorrer através de comandos.</p>
<p>Discuti, ou melhor, tive uma aula com o Massi sobre como fazer a transição para forma SSA de maneira barata e quase linear, além disso ele me apresentou ao conceito de HSSA (Hashed Static Single Assignment), que permite realizar enumeração global de valores enquanto faz a renomeação para SSA &#8211; que permite eliminar redundâncias de forma mais agressiva que via CSE. Fora isso ele falou da idéia de que é viável construir um bom alocador de registradores como um passo unificado ao que sai do formato SSA, aproveitando que SSA dá quase que de graça use-def e liveness.</p>
<p>Conheci o Jim Purbrick, o cara da LidenLabs que está usando mono para executar as bilhões de linhas de código de LSL do Second Life. O &#8220;pequeno&#8221; problema que eles tem é que são dezenas de milhares de scripts executando em paralelo em um mesmo simulador &#8211; algo que não é fácil de fazer usando threads. A solução que eles adotaram foi implementar um compilador que transforma todos IL em Continuation Passing Style. Basicamente criando suporte a micro-threading e scheduling cooperativo. Não é algo para quem tem estomago fraco, mas funciona e eles esperam ganhos de performance de duas ordens de magnitude.</p>
<p>Foi muito interessante discutir com meus colegas que também contribuem no runtime e pude verificar que não sou o único que acha que generics é uma coisa extremamente complexa. Em breve estará sendo publicada o roadmap do projeto para o ano de 2008 e tem muita coisa legal adiante &#8211; aguardem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/12/09/monosummit2007/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Compilando mono svn para o open moko</title>
		<link>http://www.kumpera.net/blog/index.php/2007/12/07/compilando-mono-svn-para-o-open-moko/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/12/07/compilando-mono-svn-para-o-open-moko/#comments</comments>
		<pubDate>Sat, 08 Dec 2007 01:49:42 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[mono]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/12/07/compilando-mono-svn-para-o-open-moko/</guid>
		<description><![CDATA[Hoje novamente precisei compilar o mono do zero para o openmoko, uma experiência não muito agradável eu diria. A receita não é tão difícil, mas exige uma doze enorme de paciência. Esse artigo é mais uma nota mental de como fazer novamente do que algo que alguém tenha interesse em ler. Este guia é para [...]]]></description>
			<content:encoded><![CDATA[<p>Hoje novamente precisei compilar o mono do zero para o openmoko, uma experiência não muito agradável eu diria. A receita não é tão difícil, mas exige uma doze enorme de paciência. Esse artigo é mais uma nota mental de como fazer novamente do que algo que alguém tenha interesse em ler. Este guia é para o OpenSuse 10.3, então ajustes serão necessários para outras versões ou distros.</p>
<p>Primeiro instalar o toolchain do OpenMoko segundo essa <a href="http://wiki.openmoko.org/wiki/MokoMakefile">página do wiki</a>. Lembrando que o monotone por algum motivo não aparece no repositório padrão de pacotes, então tem que baixar via <a href="http://benjiweber.co.uk:8080/webpin/index.jsp?searchTerm=monotone&#038;distro=openSUSE_103">software search</a>. Instalado isso, basta seguir as instruções do wiki e esperar &#8220;um pouco&#8221; &#8211; umas 12 horas em uma workstation rápida.</p>
<p>Agora que o ambiente básico está instalado, importe as variáveis de ambiente do script &#8220;setup-env&#8221; que está no diretório raiz do toolchain. Instale os pacotes devshell, glib-2.0 e perl-native via bitbake.</p>
<p>Pronto, agora execute a devshell, que deve estar em &#8220;tmp/deploy/glibc/addons/&#8221;. Vá para o diretório onde está sua árvore do mono que acabou de dar checkout e aplique o patch &#8220;/openembedded/packages/mono/files/configure-svnr87352.patch&#8221;. Feito isso coloque as autotools para funcionar com &#8220;./autogen.sh &#8211;without-tls &#8211;disable-mcs-build &#8211;host=arm-angstrom-linux&#8221; e com um pouquinho de sorte o configure executará com sucesso.</p>
<p>Feito isso é só make e &#8220;make install DESTDIR=&#8230;&#8221; para instalar o mono no diretório de destino desejado. Copie para o dispositivo ou o emulador e aproveite!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/12/07/compilando-mono-svn-para-o-open-moko/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hackweek &#8211; último dia</title>
		<link>http://www.kumpera.net/blog/index.php/2007/06/29/hackend-ultimo-dia/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/06/29/hackend-ultimo-dia/#comments</comments>
		<pubDate>Fri, 29 Jun 2007 20:32:34 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[mono]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/06/29/hackend-ultimo-dia/</guid>
		<description><![CDATA[
Essa semana foi bem divertida, nosso time conseguiu criar 13 desklets, muito mais do que imaginamos no início. A maioria deles não passa de uma prova de conceito, mas mostra o potencial do produto. Por exemplo, já temos integração com Picasa e Google Calendar. Quem quiser pode ir no site da HackWeek e votar no [...]]]></description>
			<content:encoded><![CDATA[<p>
Essa semana foi bem divertida, nosso time conseguiu criar 13 desklets, muito mais do que imaginamos no início. A maioria deles não passa de uma prova de conceito, mas mostra o potencial do produto. Por exemplo, já temos integração com Picasa e Google Calendar. Quem quiser pode ir no <a href="http://idea.opensuse.org/content/">site da HackWeek</a> e votar no <a href="http://idea.opensuse.org/content/ideas/implement-a-client-javascript-for-gtk-andor-moonlight">nosso projeto</a>. Abaixo deixo algumas imagens do nosso trabalho. Foi realmente bem legal trabalhar esses dias com o Everaldo Canuto, Andreia Gaita, Marek Habersack (Grendel), Rafael Fumasa, o Chris Toshok e o Miguel de Icaza.</p>
<p><img src="http://lh4.google.com/everaldo.canuto/RoLwjwxKTRI/AAAAAAAAALI/xX4zioVCVr0/s400/glassy-blue.jpg" alt="Nosso primeiros desklets" /><br />
<img src="http://lh6.google.com/everaldo.canuto/RoVQxgxKTWI/AAAAAAAAAME/KeFqp6j3uXc/s400/desklets2.jpg" alt="Painel com vários Desklets" /><br />
<img src="http://lh6.google.com/everaldo.canuto/RoVa4gxKTdI/AAAAAAAAAM8/WI6_EqdQtNY/s400/allthepeople.jpg" alt="Time de desenvolvimento" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/06/29/hackend-ultimo-dia/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hackweek dia Um</title>
		<link>http://www.kumpera.net/blog/index.php/2007/06/26/hackweek-dia-um/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/06/26/hackweek-dia-um/#comments</comments>
		<pubDate>Tue, 26 Jun 2007 11:59:19 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[mono]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/06/26/hackweek-dia-um/</guid>
		<description><![CDATA[
Ontem o progresso do nosso projeto na HackWeek foi fabuloso, primeiro veio o Miguel e escreveu no seu blog falando do assunto. Isso foi mais que suficiente para atrair bastante gente para falar conosco sobre o assunto. Temos até um membro da comunidade nos ajudando com um desklet, o que foi uma grande vitória. No [...]]]></description>
			<content:encoded><![CDATA[<p>
Ontem o progresso do nosso projeto na HackWeek foi fabuloso, primeiro veio o Miguel e <a href="http://tirania.org/blog/archive/2007/Jun-25-1.html">escreveu no seu blog</a> falando do assunto. Isso foi mais que suficiente para atrair bastante gente para falar conosco sobre o assunto. Temos até um membro da comunidade nos ajudando com um desklet, o que foi uma grande vitória. No geral conseguimos muito mais do que eu esperava, já temos alguns desklets funcionando e uma pessoa criando o desklet manager e a API.</p>
<p>
Eu fiquei por conta de criar um Desklet de calendário e até que me saí bem, dado que desconhecia o WPF pro completo até ontem. Ele ainda tem alguns ajustem a serem feitos e gostaria de se der tempo integrar com o Google Calendar. Por isso se alguém souber como fazer essa integração usando C# por favor entre em irc.gnome.org #desklets e nos ajude a fazer isso, vamos ser muito gratos por isso. ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/06/26/hackweek-dia-um/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
