

<?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; concurrency</title>
	<atom:link href="http://www.kumpera.net/blog/index.php/category/concurrency/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>As fantásticas threads do Ruby 1.9</title>
		<link>http://www.kumpera.net/blog/index.php/2007/05/25/as-fantasticas-threads-do-ruby-19/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/05/25/as-fantasticas-threads-do-ruby-19/#comments</comments>
		<pubDate>Sat, 26 May 2007 02:57:24 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[shared-memory]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/05/25/as-fantasticas-threads-do-ruby-19/</guid>
		<description><![CDATA[
Fico realmente desapontado quando vejo noticias como essa. Quando pessoas supostamente esclarecidas tomam decisões incrivelmente estúpidas. Usar threads nativas porém sincronizando o acesso ao interpretador é aviltante. Por favor, se é para ter threads, que seja para valer, não repetir a mesma tentativa fracassada do python. Não quer suportá-las ótimo, também acho uma péssima abstração, [...]]]></description>
			<content:encoded><![CDATA[<p>
Fico realmente desapontado quando vejo <a href="http://www.infoq.com/news/2007/05/ruby-threading-futures">noticias como essa</a>. Quando pessoas supostamente esclarecidas tomam decisões incrivelmente estúpidas. Usar threads nativas porém sincronizando o acesso ao interpretador é aviltante. Por favor, se é para ter threads, que seja para valer, não repetir a mesma tentativa fracassada do python. Não quer suportá-las ótimo, também acho uma péssima abstração, mas então tenha suporte de primeira classe a processos.
</p>
<p>
Agora o problema todo não se a resume a green-threads são naturalmente ruim, eu até já <a href="http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/">falei anteriormente sobre isso</a>, mas a questão é garantir que todas threads executem apenas código gerenciado ou código nativo. Essa garantia é suficiente para permitir um sistema escalável é livre dos problemas habituais. Tudo bem que a interface nativa fica muito mais complicada, não é mais um wrapper para o código externo e sim um protocolo de IPC.
</p>
<p>
Espero pelo menos que esse tipo de discussão sirva para alertar do fato que threading é um mecanismo complicado demais para ser efetivamente utilizado, enquanto troca de mensagens entre processos leves é um paradigma igualmente poderoso com garantias de segurança muito maiores. Quando não existe memória compartilhada e necessidade de locking, concorrência é um problema resolvido localmente por cada processo/ator envolvido. Protocolos são criados e definidos que representam de maneira muito mais clara e lógica o que seria de outra maneira representada por uma estrutura de dados compartilhada e seus monitores.
</p>
<p>
Enfim, enquanto se discutir o assunto, ainda existe esperança, mesmo que decisões muito erradas sejam tomadas. Não é uma questão simplesmente de nos preparar para um futuro com sistemas com muitos núcleos, mas sim facilitar a construção de software muito mais seguro e confiável. As provas e evidencias estão por toda parte, ao alcance de todos dispostos a abrir os olhos para o futuro.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/05/25/as-fantasticas-threads-do-ruby-19/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Green threads &#8211; idéia ruim ou implementações péssimas?</title>
		<link>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/#comments</comments>
		<pubDate>Thu, 12 Apr 2007 15:10:20 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/</guid>
		<description><![CDATA[ Todo lugar que se prese a falar sobre modelos de threading, native x green, fala que não existe razão para ter threads implementadas em user-space, chamadas de green-threads, se o SO possuir uma boa implementação nativa. Bom, se olharmos em volta, como  neste blog, nas listas de discussão do JikesRVM, do Ruby ou [...]]]></description>
			<content:encoded><![CDATA[<p> Todo lugar que se prese a falar sobre modelos de threading, native x green, fala que não existe razão para ter threads implementadas em user-space, chamadas de green-threads, se o SO possuir uma boa implementação nativa. Bom, se olharmos em volta, como <a href=" http://ciaranm.org/show_post/110"> neste blog</a>, nas listas de discussão do JikesRVM, do Ruby ou do JRockit da época de 2004, vamos notar que todos reclamam muito das limitações e problemas impostos pelo uso de green-threads. As falhas apontadas são tantas que cria uma duvida se existe alguma justa razão em usá-las.
</p>
<p> Para entender melhor a situação, vejamos o modelo de execução que todo sistema operacional espera de seus processos. Um processo possui uma ou mais threads, cada thread possui apenas uma linha de execução* e faz chamadas bloqueantes ao kernel. Ou seja, cada uma deve seguir executando por apenas um caminho e deve parar enquanto uma chamada ao sistema não completa. Contrastemos agora com modelo de green-threads, que pode ser visto da seguinte forma: um processo possui uma ou mais threads, cada uma administra varias linhas de execução e uma chamada ao kernel não impede prosseguir com as demais.
</p>
<p> Essa diferença de funcionamento gera dois problemas. Primeiro de identidade, já que cada thread não possui somente uma linha de execução associada, então primitivas de locking não funcionam pois duas green-thread vão aparecer para o kernel como uma só. O segundo está relacionado ao comportamento do kernel, uma chamada bloqueante partindo de uma linha de execução vai causar várias outras pararem junto.</p>
<p> Ambos problemas dificultam muito a integração com bibliotecas externas, que podem usar o mecanismo de locking do sistema operacional, ou então bloquear indevidamente demais threads. Por exemplo, no Gtk+, o acesso aos widgets é protegido por locks nativos, que em um ambiente com green-threads vai por água abaixo e acaba corrompendo o estado, também tem o fato que executar processamento pesado fora da thread de eventos não ajuda, pois se uma bloqueia, todas bloqueiam. Por fim, tem a questão da escalabilidade, já que várias threads são bloqueadas sem precisar.</p>
<p> Existem alguns sistemas que conseguiram transpor essas barreiras, mas não sem um alto custo associado. Passam, primeiro, a adotar uma primitiva de mais alto nível que uma thread, como um ator, que é muito mais simples de utilizar. Depois fazem o trabalho pesado, criam um mecanismo de execução assíncrona das tarefas bloqueantes, seja fazendo offload para threads nativas auxiliares, ou usando aio e/ou multiplexação. Por fim, partem para as medidas radicais, definindo uma interface para código estrangeiro que garante a semântica e o comportamento das green-threads.
</p>
<p> A interface de integração com código estrangeiro, também conhecida por FFI (Foreign Function Interface), é o elemento mais crítico e problemático, pois precisa impor uma forma diferente de trabalho aos integradores, normalmente via troca assíncrona de mensagens entre uma thread com o código &#8216;perigoso&#8217; e as demais gerenciadas. Uma versão muito mais cabeluda do JNI, para quem conhece.</p>
<p> Das linguagens que implementam efetivamente userland threading, que eu conheço são<br />
Erlang, Scheme e Factor. Elas permitem o uso de milhares de thread leves que consomem poucos recursos e não fazem o escalonador do SO entrar em parafuso. A JVM da BEA, JRockit, uma época suportou green-threads, mas devido a dificuldade de implementar a parte GUI do Java e não criar caos durante chamadas nativas, desistiram do projeto quando o linux passou a ter suporte nativo descente.</p>
</p>
<p>* Por linha de execução entenda o conjunto de registradores e a pilha de funções.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Java continuations e NIO, o casamento perfeito</title>
		<link>http://www.kumpera.net/blog/index.php/2006/10/12/29/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/10/12/29/#comments</comments>
		<pubDate>Thu, 12 Oct 2006 04:04:20 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[concurrency]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/10/12/29/</guid>
		<description><![CDATA[Eu estava quase perdendo as esperanças de conseguir utilizar NIO para um servidor. Sempre achei muito dificil programar utilizando um socket não-bloqueante, o parsing de qualquer protocolo um mais dificil é um inferno. Eu resolvi então experimentar escrever um servidor usando continuation-passing-style e o resultado foi supreendemente facil, intuitivo e escalavel.
Minha vontade de usar CPS [...]]]></description>
			<content:encoded><![CDATA[<p>Eu estava quase perdendo as esperanças de conseguir utilizar NIO para um servidor. Sempre achei muito dificil programar utilizando um socket não-bloqueante, o parsing de qualquer protocolo um mais dificil é um inferno. Eu resolvi então experimentar escrever um servidor usando continuation-passing-style e o resultado foi supreendemente facil, intuitivo e escalavel.</p>
<p>Minha vontade de usar CPS veio das minhas brincadeiras com Erlang, processos são tão leves nessa linguagem que me leva a acreditar que threads em user-land com scheduling (pseudo)cooperativo são a melhor receita para escalabilidade e facilidade de programação. Quem lembra do windows 3.1, vai me afirmar que cooperative threading é uma enorme roubada e eu concordo, que para aplicações desktop, não funciona bem. Agora pensando em web-application, que basicamente se resume a fazer pequenas tarefas e esperar um tempão pelas operações de I/O completarem, cada thread decidir quando pausar não soa ruim.</p>
<p>Bom, vou descrever um pouco a solução que eu adotei. Utilizei o commons-javaflow para suportar continuations em Java. A biblioteca ainda é experimental, mas já estavel e usavel o suficiente para brincar. O ruim é que você precisa brincar com classloading ou pos-processamento dos arquivos .class. Fora isso uso o feijão com arroz de io multiplexado. Que é manter um Selector para verificar a disponibilidade de todos os sockets e I/O não bloqueante para transmissão de dados.</p>
<p>A grande sacada de usar i/o não bloqueante e continuations é até que simples, sempre que uma operação falhar por não ter dados disponiveis (leitura), ou falta de buffer (escrita), você registra o socket junto ao selector e da yield na continuation (suspende a execução dela). Depois disso, quando a operação ficar disponível, você simplesmente retoma a continuation. Eu implementei um servidor de echo, o código que implementa isso no servidor se resume a:</p>
<p><code><br />
public void run() {<br />
    try {<br />
        String line;<br />
        while ((line = reader.readLine()) != null) {<br />
            writer.write(line);<br />
            writer.write("\n");<br />
            writer.flush();<br />
        }<br />
        socket.close();<br />
    } catch (Exception e) {<br />
        e.printStackTrace();<br />
    }<br />
}<br />
</code></p>
<p>O código parece o mesmo que se usarmos um socket normal e i/o bloqueante, de fato é, com a diferença que as classe de streams são customizadas. O código que se utiliza de continuations não é muito complicado, bem diferente de vários frameworks como mina ou seda, como mostro a seguir o método que faz a escrita usando NIO. O método current() retorna uma referencia a uma classe que controla a interface com o selector e o escalonador.</p>
<p><code><br />
public void write(byte[] b, int off, int len) throws IOException {<br />
    ByteBuffer buff = ByteBuffer.wrap(b, off, len);<br />
    while (buff.remaining() > 0) {<br />
        channel.write(buff);<br />
        if (buff.remaining() == 0)<br />
            break;<br />
        current().register(channel, SelectionKey.OP_WRITE);<br />
        current().ioSuspend();<br />
    }<br />
}<br />
</code></p>
<p>Eu ainda estou começando a bricandeira, ainda pretendo colocar um bom parser de HTTP para funcionar nesse esquema, algum driver opensource para banco de dados e, finalmente, file I/O assíncrono. A partir deste ponto já fica possivel realmente contribuir um sistema com essa tecnologia. Para quem ficou curioso, os links são: <a title="commons-javaflow" href="http://www.kumpera.net/uploads/javaflow.jar">commons-javaflow</a>   e meu <a title="exemplo" href="http://www.kumpera.net/uploads/continuations.zip">exemplo</a>. Para quem gostou, pode ter certeza que vem muito mais por ai.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/10/12/29/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Levando I/O escalavel para mortais</title>
		<link>http://www.kumpera.net/blog/index.php/2006/09/22/levando-io-escalavel-para-mortais/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/09/22/levando-io-escalavel-para-mortais/#comments</comments>
		<pubDate>Fri, 22 Sep 2006 13:54:08 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[network programming]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/09/22/levando-io-escalavel-para-mortais/</guid>
		<description><![CDATA[Esses dias eu tive uma idéia de como usar java NIO de forma facil. Essa API permite programar usando I/O não bloqueante com sockets e multiplexação. Ambas as técnicas são muito dificeis de serem usadas. Eu pensei em usar um pouco de mágicas de engenharia de bytecodes e introduzir continuations em Java. Sim, é perfeitamente [...]]]></description>
			<content:encoded><![CDATA[<p>Esses dias eu tive uma idéia de como usar java NIO de forma facil. Essa API permite programar usando I/O não bloqueante com sockets e multiplexação. Ambas as técnicas são muito dificeis de serem usadas. Eu pensei em usar um pouco de mágicas de engenharia de bytecodes e introduzir continuations em Java. Sim, é perfeitamente possível fazer isso.</p>
<p>Existem artigos que explicam como é possivel transformar um trecho de código para permitir utilizar continuations. A grosso modo, a mecânica é bem simples, introduzimos um parâmetros em todas funções que é a continuação corrente e nela está embutido o conhecimento necessário para determinar o fluxo de execução a ser tormado. Esse <a href="http://www.ps.uni-sb.de/~duchier/python/continuations.html">texto</a> fala bem disso, mostrando como fazer isso em python.</p>
<p>Permitir continuações resolve somente mentade do problema, a outra é introduzir uma API que opere de modo bloquante, mas por traz dos panos esteja usando NIO e continuations. Essa parte eu ainda não me decidi, se simplesmente deve ter cara de um stream normal, ou se permitir que uma interface seja transformada em um autômato finito. Essa, por sinal, seria outra maneira de programar com a linguagem, descrevendo a gramática dos dados recebidos e permitindo que ela fosse compilada para código que utilize NIO de forma não bloqueante.</p>
<p>Eu gostaria de seguir com a idéia de transformar código Java e não ter uma linguagem separada, pois essa parece ser a alternativa que garantiria a melhor produtividade ao desenvolvedor, vide como o Google Web Toolkit faz &#8211; ele recompila tua aplicação em javascript, por que não recompilar então em um autômato ou passar para CPS? Certa vez escrevi um protótipo da idéia de um um DFA, vou ver de desenterro e dou um tapa nele, quanto a continuations, alguém sabe em qual estado está o RIFE Continuations?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/09/22/levando-io-escalavel-para-mortais/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Futuro da programação concorrente</title>
		<link>http://www.kumpera.net/blog/index.php/2006/09/07/futuro-da-programacao-concorrente/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/09/07/futuro-da-programacao-concorrente/#comments</comments>
		<pubDate>Fri, 08 Sep 2006 02:45:18 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[concurrency]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[shared-memory]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/09/07/futuro-da-programacao-concorrente/</guid>
		<description><![CDATA[Programação concorrente é dificil, mais dificil que acordar cedo em pleno inverno. Arrumar gente que entenda e saiba escrever corretamente aplicações multi-threaded é muito dificil. O pior que é bem razoavel esperar isso, afinal acompanhar mentalmente o fluxo de várias threads em paralelo no mínimo faz o cérebro doer. Ou resolvemos isso logo, ou estaremos [...]]]></description>
			<content:encoded><![CDATA[<p>Programação concorrente é dificil, mais dificil que acordar cedo em pleno inverno. Arrumar gente que entenda e saiba escrever corretamente aplicações multi-threaded é muito dificil. O pior que é bem razoavel esperar isso, afinal acompanhar mentalmente o fluxo de várias threads em paralelo no mínimo faz o cérebro doer. Ou resolvemos isso logo, ou estaremos nos condenando a passar os próximos anos apenas tentando arrumar esse embrólio.</p>
<p>O grande problema é o modelo que as linguagens que usamos, tais como Java, C ou Ruby, tem essa coisa horrivel que é memória compartilhada entre as várias linhas de execução, nossas queridas threads. O Joe Armstrong, um guru nesta área argumenta sobre isso <a href="http://armstrongonsoftware.blogspot.com/2006/09/why-i-dont-like-shared-memory.html">neste artigo</a> e defende o porque de ser um problema muito bem.</p>
<p>O Joe também fala que apenas usando múltiplos procesos e passagem de mensagens entre eles é possivel conseguir o mesmo resultado, só que de forma muito mais facil e confiavel, ele ainda sugere usar Erlang. A um tempo <a href="http://www.kumpera.net/blog/index.php/2006/07/28/construindo-sistemas-multi-threaded-de-forma-facil/">escrevi um artigo</a> falando um pouco sobre como Erlang funciona e ainda continuo firme que o seu modelo de execução é muito superior ao que temos nas linguagens mainstream &#8211; mas peca por ser uma linguagem dificil de usar.</p>
<p>Mas quais são as característica que tornam Erlang tão interessantes? Primeiro, seu suporte a processos super leves, manter um milhão deles executando em paralelo é perfeitamente possivel, já que para criar um basta pouco mais de 1kb de memória e o tempo de alocá-la &#8211; compare isso com o tempo e o uso de memória para subir uma JVM. Depois temos uma sintaxe especial para troca de mensagens assíncronas entre processos &#8211; que é uniforme em relação a localização de cada um. Cada processo possui sua área propria de memória, se um processo fizer muita meleca e morrer, nada interfere no funcionamento dos demais. Essa resiliência torna Erlang uma linguagem muito mais segura e confiavel que as demais.</p>
<p>Por isso que eu acredito que o próximo Java vai ser a linguagem que suportar um ambiente de execução semelhante ao do Erlang. Esse me parece ser o avanço técnológico que justificaria uma adoção em massa, e para entender isso bastar olharmos para tras. Gerenciamento manual de memória é facil de explicar e fazer um estagiário entender, ele vai saber que quando terminar de usar um pedaço de memória, ele deve ser liberado &#8211; apesar disso excelentes desenvolvedores gastam muito tempo caçando memory-leaks em código C/C++. Programação concorrente com memória compartilhada é dificil achar plenos/seniors que são capazes de entender direito. Java introduziu gerenciamento automático de memória para as massas, agora precisamos uma linguagem que faça o mesmo com processos leves e passagem de mensagens.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/09/07/futuro-da-programacao-concorrente/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
