Monthly Archives: May 2011

My experience with GNOME 3 so far

You know, GNOME Shell and I are not really strangers to each other for a long time now. I have been using it almost daily as my main desktop since late 2009, when I started shipping it to Debian experimental. That means that I had ample opportunity to both get used to it and witness the huge improvements it had with every new release.

My general feeling towards GNOME 3 is this: ♥. Yes, I love it! I love the new themes, I love the window borders, I love the top panel, the overview, the dynamic workspaces, I love the Me menu, I love the clock and the calendar, the system indicators with the beautiful symbolic icons, being able to search for applications in such a nice way, the window animations, the multi-screen support, the new nautilus, the dash, looking glass. It’s hard for me to even express how thankful I am and how much admiration I have for the awesome folks who helped bring this to life. Thanks so much!

My GNOME3 desktop

My GNOME 3 desktop

After all this time, there are only two things I can say I dislike about GNOME3, apart from some minor wishlists: the alt-tab behaviour and the message tray. Let me expand on those.

Message Tray

Of the very few things I dislike, there is only 1 I hate and cannot see myself living with: the accordion animation in the message tray. No, really, it’s such a terrible, terrible idea. Every single time I try to use that thing I overshoot while moving the mouse to the left, then overshoot again moving the mouse to the right because the frigging icon has moved. It’s no good knowing that I can click in the text or in the empty area to its right, it feels wrong. It’s terrible that my actual target is moving at all. Every single time I use it is a small frustration for me – it’s as if the message tray was playing games with me, laughing at me for not having good enough mouse pointer driving skills – even more than the infamous sub-menus used to. And I had to go through that penance whenever I wanted to find the person I was chating with to resume the conversation.

I wrote an extension that disables the accordion animation by simply not showing the title at all when you hover the icon, and I patched GNOME Shell’s CSS to make the icons a bit bigger, so that it’s easier for me to hit them with the mouse. It’s clearly not ideal, and you still have to click the various “people” icons to figure out which of your friends who were lazy enough to not add a picture to their IM profiles is that one, but it’s still much better than chasing the (smaller) ones around to figure that out. Perhaps we should have the icons be bigger and always have the title bellow them? I don’t know, I trust the awesome designers who designed the awesomess that’s everywhere else will come up with a great idea.

My Message Tray

My message tray with bigger icons and no accordion animation.

Alt Tab

The number 1 feature of workspaces for me has always been locality – being able to not see all of the other applications and windows that are open elsewhere. This lowers the amount of noise when I’m trying to find something. The overview is very nice in this matter – only windows in the current workspace are shown, and even when you have an extra screen, the windows in there appear in that screen.

The alt-tab behaviour, on the other hand, of showing all windows and apps, even with the separator, bothers me. It’s really useful to have when you want to go to a specific window no matter where it is (I usually use the dash for that, though), but it adds noise when you want to go to a specific window _in this_ workspace, which is the most common use case for my usage. So I copied the alt-tab code over to an extension and modified it so that only windows in the current workspace would be considered.

In addition to that, with the windows in the extra screen always being there no matter what workspace you’re in (which I think is an awesome idea), they are effectively in all workspaces, so they add constant noise even with my extension. It’s also weird to have to look at the main screen to switch to a window in the extra screen. There’s a huge discontinuity. What I would prefer is having alt-tab to follow the mouse regarding screens – only show windows in the extra screen if you hit alt-tab in there, making sure the selector thing appears in there as well.

“Porque eu aprendi na faculdade que alocar memória é caro”

Mais um exemplo interessante a respeito daquilo que falei num post anterior. Recentemente uma pessoa que começou a trabalhar em um projeto em que eu trabalho há algum tempo me pediu que opinasse a respeito de um patch dele. O patch original dele havia sido revisado por um colega de projeto e além de umas bobagenzinhas de estilo havia uma única preocupação: “por quê você quer fazer essa mudança?” A mudança era bastante simples: evitava que uma variável fosse liberada e realocada em alguns casos específicos.

Nesse projeto uma das coisas que as pessoas menos gostam é de otimizações cegas. Se você faz uma mudança, essa mudança tem chances de introduzir bugs e de aumentar a complexidade do código. Se você vai incorrer nesse risco, é melhor saber que está de fato fazendo alguma diferença. Por isso, otimizações em geral só são bem-vindas se forem acompanhadas de um teste de desempenho que mostra melhoria. Se não melhora nada, pra que mudar? É claro que há excessões à regra e algumas mudanças acabam simplificando o código e são bem-vindas mesmo se o único resultado for não piorar o desempenho.

Quando eu falei que não é legal fazer otimizações cegas ele me disse: “Cega ou não, estou fazendo a mudança porque aprendi na faculdade que alocações são caras, principalmente porque causam chamadas de sistema e por isso devem ser evitadas”. Opa. Alocações de memória de fato envolvem o kernel, mas será que todas as alocações de memória causam chamadas de sistema e a consequente (e cara) troca de contexto para modo kernel?

Fácil testar isso. Se for verdade que cada alocação gera uma chamada de sistema o seguinte programa vai exibir 100 milhões de chamadas de sistema quando o executarmos através do strace:


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    int i;
    char* data;

    printf("START\n");
    for (i = 0; i < 100000000; i++)
        data = malloc(10);
    printf("END\n");

    return 0;
}

Vejamos:

[...]
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbe62175000
write(1, "START\n", 6START
)                  = 6
brk(0)                                  = 0x1b83000
brk(0x1ba4000)                          = 0x1ba4000
write(1, "END\n", 4END
)                    = 4
exit_group(0)                           = ?

Mas hein? Duas chamadas de sistema entre os dois writes? Pois é. Acontece que o pessoal que escreveu a malloc() já sabe que pedir memória pro kernel é caro e fizeram a libc pré-alocar uma quantidade maior de memória de uma vez e ir entregando pedaços dessa memória conforme a aplicação pede. Isso significa que alocação de memória não é cara? Não. É razoavelmente cara mesmo que não haja troca de contexto, afinal de contas a libc precisa fazer um tanto de trabalho pra saber quanto tem alocado e saber qual o tamanho de cada pedaço de memória que foi alocado para poder liberar depois com free(). Se ao invés de fazer malloc 100 milhões de vezes eu fizer uma só e fizer 100 milhões de memset() o programinha fica 10 vezes mais rápido.

Isso significa que nós devemos evitar qualquer alocação que seja possível evitar? Depende. Pra começo de conversa esse é um teste extremo, não uma carga de trabalho real. Testes são sempre melhores em cargas reais (ou mais parecidas com algo real). Mas principalmente, se for pra piorar muito a legibilidade do código, torná-lo mais complexo, manter memória comprometida por mais tempo que o necessário, é importante que haja um ganho em desempenho para contrabalancear. E esse ganho tem que ser medido, não imaginado =).

Scale Fail

Hoje foi publicado no site Linux Weekly News um artigo de Josh Berkus chamado Scale Fail (part 1) é preciso ser assinante da LWN ou esperar uma semana para que o artigo seja tornado público, mas enquanto isso você pode assistir a uma apresentação que o Josh Berkus fez aqui. O assunto não só é interessante como tem muito a ver com o tema de que eu tratei no meu último post =). O Josh Berkus é um dos principais desenvolvedores do PostgreSQL e também fez uma palestra muito interessante na Linux Foundation Collaboration Summit do ano passado sobre como evitar que seu projeto gere uma comunidade. Recomendo fortemente. Se interessar, também recomendo a palestra seguinte, do Chris DiBona do Android.

Mesa redonda

Anos atrás trabalhei num ambiente em que todos os usuários praticamente conheciam o hostname do servidor de arquivos. Usuários saberem hostnames de servidores de arquivos quase nunca é um bom sinal. Todos reclamavam constantemente do tal servidor, falando sempre de como era lento o acesso aos arquivos. Assim que entrei me informaram das medidas que já haviam sido tomadas: sempre que a reclamação ficava muito grande o administrador de rede colocava uma placa de rede de 100Mbps nova no servidor, mas isso parecia pouco resolver.

Alguns anos mais tarde trabalhei em outro lugar em que havia uma aplicação web acessada por um número bastante grande de usuários de todo o Brasil. Havia um grande porém. Apesar de eu fazer parte da equipe de infraestrutura, todo o ambiente de produção dessa instituição ficava sob a responsabilidade de uma outra empresa. A tal aplicação começou a exibir graves problemas de desempenho e como havia prazos relacionados ao preenchimento de dados na aplicação, cada dia que passava sem que muitos usuários conseguissem fazer qualquer coisa no sistema gerava um aumento considerável na preocupação dos gestores.

Ao contrário do administrador do primeiro lugar a solução da equipe responsável pela TI dessa segunda instituição era menos mão-na-massa: fazíamos reuniões em torno de uma mesa em que eram debatidas as diversas possibilidades e sugeridas possíveis soluções. Alguns achavam que o problema era que a aplicação era lenta, outros que o servidor web estava mal configurado, outros que era falta de banda. Houve quem sugerisse que se substituísse a aplicação web por uma aplicação que rodasse na máquina dos usuários, com acesso direto ao banco de dados, o que supostamente reduziria o uso de banda.

O que há de errado em ambas as histórias? Ninguém nunca havia pensado em coletar dados, medir, saber o que havia de errado para depois atacar o problema. Eles preferiam fazer o pior tipo de tratamento de problemas de desempenho: imaginar qual seria o problema e chutar soluções que pudessem saná-los.

No primeiro caso, logo depois que entramos eu e um colega, a primeira coisa que esse colega fez foi instalar um monitoramento razoavelmente completo de indicadores de desempenho de todo o ambiente de rede com o cacti. Não demorou muito para que nós descobríssemos que o problema do nosso querido servidor de arquivos estava longe de ser banda. A carga de transferência de dados nunca passava dos 30Mbps, o que é muito menos que os 100Mbps que uma única placa de rede comum à época conseguiria de desempenho nominal. Adicionar placas de rede não adiantava absolutamente nada. Nem me lembro exatamente qual era o problema, provavelmente uma soma de fatores que incluíam uma configuração pra lá de absurda do Samba e uma configuração de raid que não fazia sentido, mas isso não vem ao caso. O importante dessa história é que o remédio que estava sendo dado para nosso paciente não ajudava em nada a melhorar a doença que ele tinha ;) .

O segundo caso é um pouco mais triste: depois de algumas semanas tentando brigar com a estrutura burocrática para nos permitir acessar os servidores e saber o que estava acontecendo chegamos a um indicador bastante interessante: a carga média de 1 minuto do servidor de banco de dados estava em torno de 70. A máquina se não me engano tinha somente um processador. A carga média no Linux indica o número de processos que estão na fila para usar o processador ou bloqueados por espera de I/O, em médias de 1, 5 e 15 minutos. Como nós já havíamos investigado (e até tomado o controle) dos servidores de aplicação, nossa investigação sobre qual era o gargalo naquele momento parecia ter chegado a uma conclusão: o banco de dados e/ou o que a aplicação pedia dele precisava de amor e carinho. Acontece que não adiantou nada nós termos descoberto isso: continuamos por mais algumas semanas com todo mundo correndo em círculos como galinhas sem cabeça e sem ninguém com conhecimentos adequados chegar perto de analizar o banco de dados e as consultas feitas, até que finalmente alguém mais de cima decidiu mandar todos os nossos chefes embora e fazer uma intervenção.

Depois de algumas semanas batendo cabeça do mesmo jeito, com mais reuniões inúteis em torno de mesas (mas dessa vez com outros personagens) finalmente conseguimos que alguém com poder de agir nos escutasse e consertasse o banco de dados, embora nossa demanda por melhorias na aplicação (que nossas pesquisas paralelas e sem nenhuma ajuda do DBA indicaram colocar mais peso no banco do que o necessário) tenham caído em ouvidos surdos. As mudanças feitas no banco (otimização de queries, criação de índices e views materializadas, essencialmente, pelo que minha leiguice captou) acabaram dando gás para que o sistema sobrevivesse mais algum tempo sem uma intervenção mais estrutural, que acabamos fazendo quando finalmente assumimos o controle do servidor de banco de dados também, mas essa já é uma história pra outro post de blog.

Problemas de desempenho e otimizações são aquele tipo de coisa em que a pior coisa que você pode fazer é sentar em volta de uma mesa e tentar tirar qual o problema do ar. Agir com soluções de senso comum também só dá certo se você for sortudo. Esse assunto me interessa e por isso estou pensando em fazer alguns posts falando de problemas de desempenho e otimizações prematuras que demonstram que nem sempre o que é intuitivo é a realidade e que mesmo que você tenha uma hipótese bastante plausível é melhor investigar antes de torná-la uma crença. Alguém tem histórias interessantes pra compartilhar? =)

Nota: essa é uma obra de ficção baseada em fatos reais; algumas simplificações foram feitas sem prejuízo do caso em geral