Links about High Availability and NoSQL

January 27th, 2010 1 comment

I’m reading many links about High Availability, Elastic Systems and NoSQL alternatives. It’s all about alternatives for scaling a system where a RDBMS can’t fill it needs.

We are putting them below, with some messages and images. It’s a pleasure to read for anyone that works with Distributed Systems:

NOSQL Patterns – How we can build a distributed database


This article describes the principal NoSQL alternatives and how to split a table/dataset by key an put them into many servers, how map reduce occurs in the cluster nodes, all with beautiful diagrams.

RoadMap to SaaS


How to convert a standard web application in to a SaaS with Facade class with RESTFul services, moving processes for diferents JVM’s, cache tiers and much more…

Observers: Making ZooKeeper Scale Even Further


Maybe you won’t know about Zookeeper, yet. But you can be interested in what you can do to scale servers who depend on distributed communication and synchronization. That is a big trouble: How much more computers you put in the cluster, more messages to coordinate the distributed lock between them. The throughput decreases. But not for this guy’s using followers and observers!

Categories: computação Tags:

Olha a lâmpada “original” que a Govesa colocou em meu carro!

January 8th, 2010 No comments

No dia que comprei meu “possante” identifiquei que a lâmpada do lado esquerdo estava com a luz baixa queimada. Como era a revisão pré-entrega, o pessoal da Govesa trocou na hora a lâmpada.

Alguém diria: “Nada mais que a obrigação, entregar o carro funcionando completamente!” ou então: “Puxa, ótimo serviço. Eles fazem revisão e se algo estiver errado trocam na hora.”.

Pois é… veja o que aconteceu com ela nas fotos abaixo, pouco tempo depois. Uma concessionária autorizada Volks, colocando lâmpada “sem marca” nos veículos (Do outro lado é PHILIPS).

Ativando DRI no OpenChrome para P4M900

December 18th, 2009 1 comment

Muitas placas compartilham os mesmos recursos ou são evoluções de outras mantendo o conjunto de recursos da anterior ou ainda o modo de compatibilidade. A placa gráfica VIA P4M900 é um caso destes. Ela é encontrada em computadores mais baratos, principalmente alguns modelos de notebooks da Itautec.

O driver AGP/DRM do kernel não reconhece esta placa, por um mero detalhe: ele não tem o pci_id da mesma na listagem de placas suportadas e por isso o DRI não é ativado por padrão.

Consegui ativar o DRI seguindo os passos abaixo e então resolvi compartilhar. Isso não ativa o modo 3D da placa, já que o próprio OpenChrome ainda não tem suporte a 3D. Apenas o DRI é ativado.

O kernel que estou utilizando é o 2.6.29. O driver openchrome instalado no X foi obtido diretamente do repositório do projeto e compilado. Mas acredito que funcione com versões já existentes nas distribuições.

A placa que tenho é listada pelo comando lspci da seguinte forma:

# lspci|grep VGA
01:00.0 VGA compatible controller: VIA Technologies, Inc. CN896/VN896/P4M900 [Chrome 9 HC] (rev 01)

Para conseguir ativar o DRI é necessário um Kernel com os fontes, possivelmente já compilado. É necessário alterar o arquivo /usr/src/linux/include/drm/drm_pciids.h, incluindo no mesmo o id 0×1106, 0×3371. Localize o texto da primeira e terçeira linhas abaixo. A segunda linha deve ser inserida.

        {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
        {0x1106, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
        {0, 0, 0}

Entre na configuração do kernel (make menuconfig) e ative os módulos listados a seguir:

Device Drivers  --->
 Graphics support  --->
    <M> /dev/agpgart (AGP Support)  --->
      <M> VIA chipset support
    <M> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)
      <M> Via unichrome video cards

Compile e instale o kernel e os módulos. Após reiniciar o sistema você verá os seguintes módulos na lista de lsmod. Aparecerá também o arquivo /dev/dri/cards0.

# lsmod
Module                  Size  Used by
...
via                    40160  1
drm                   139712  2 via
via_agp                 7868  1
agpgart                29196  2 drm,via_agp
...

Executando o X e rodando glxinfo, pode-se confirmar que o DRI foi ativado:

$ glxinfo |grep direct
direct rendering: Yes

Não é a maior maravilha para uma placa gráfica, mas melhorou muito a exibição de vídeos. Antes de ativar o DRI o glxgears exibia apenas 80-90 FPS e depois:

$ glxgears
774 frames in 5.0 seconds = 154.666 FPS
797 frames in 5.0 seconds = 159.263 FPS
795 frames in 5.0 seconds = 158.824 FPS
786 frames in 5.0 seconds = 157.173 FPS
Categories: Linux, computação Tags: , , ,

DBX4 – Resultados Parciais de Otimização com Paralelismo

November 3rd, 2009 1 comment

Hoje em dia é super comum e barato comprar computadores com dois/quatro núcleos. Cada dia que passa estão mais acessíveis. Mas as aplicações desenvolvidas para estes processadores continuam sendo feitas sequencialmente (”mono-thread”).

Já olhou o Gerenciador de Tarefas e viu sua aplicação patinando nos 50% em uma máquina com dois núcleos? Isso só muda quando duas aplicações estão usando processador ao mesmo tempo, ou ainda, quando uma aplicação possui várias threads simultâneas para resolver um algoritmo.

Pensando nisso, a um bom tempo venho trabalhando em algumas idéias de otimização no driver DBX4. Apesar de o Delphi 2010 agora já vir com driver para Firebird, pretendo colocar esta otimização também nos demais drivers que fiz e disponibilizar para meus clientes de Postgres e Oracle.

A primeira idéia consiste em ter um buffer circular, mais ou menos uma espécie de pipelining. Uma thread busca os dados do banco e a outra repassa estes dados para o framework DBX. Desta forma, enquanto o framework DBX aloca memória e copia os valores dos campos, o driver vai requisitando a frente os dados do banco de dados.

A segunda idéia é um cache de statements. O Firebird ainda não tem um cache de statements preparados como os demais bancos (Oracle por exemplo). E o framework DBX não aproveita os statements criados. A cada registro de inserção/update, um novo statement é preparado e executado.

Os resultados parciais desta segunda idéia são animadores. Veja só o gráfico que compara o driver para Firebird e o TBODBXFB. No eixo y está o tempo em milisegundos e no eixo x a quantidade de registros inseridos em cada teste.

Gráfico Comparativo driver FIREBIRD X TBODBXFB

O teste consiste em inserir 1000, 5000, 10000, 50000 e 100000 registros numa tabela do banco. Para isolar qualquer interferência entre um e outro driver, o banco é criado no momento do início de cada teste. Também é utilizado o servidor classic do Firebird, para evitar qualquer tipo de cache entre as conexões. Os testes foram executados em uma máquina local. Firebird e Aplicação juntos.

Os tempos em milisegundos estão na tabela abaixo:

Registros inseridos TBODBXFB FIREBIRD D2010
1000 1279 2028
5000 6586 11158
10000 12212 20068
50000 64095 102144
100000 127065 202174

Caso deseje fazer um teste, o instalador do driver está no link abaixo. Por enquanto só pode ser instalado no Delphi 2010:

Driver TboDbxFb para Delphi 2010

Em breve darei mais detalhes e o código do teste. Também efetuarei testes com o banco em outro computador, já que este é o ambiente mais comum de utilização. Também exibirei outros testes a respeito do pipeline de registros em um artigo. Aguarde!

Categories: computação, delphi Tags:

Até onde o acaso me leva? Ao concerto do Reginaldo Pinheiro!

September 3rd, 2009 2 comments

Há dias monótonos, que não trazem nenhuma novidade. Mas também existem dias cheios de acasos. Foi o que aconteceu na minha última terça-feira. Acompanhe só.

Terça-feira. Vou à UFG. Um dia como outro qualquer, se não fossem alguns “acasos”. Entrei na sala do mestrado e deixei meu notebook no armário como sempre faço. Por acaso, não haveria aula de Seminários, logo fiquei sabendo. Como tinha que resolver um pequeno problema no Banco do Brasil, lá fui.

Quando voltei, por outro acaso descobri: trocaram o cadeado da sala do mestrado! Lá estava eu sem meu “passatempo” até a hora da próxima aula.

Resolvi então ir a biblioteca, procurar novidades. Só pra ficar olhando as prateleiras, sem rumo certo. Fico a procura dos livros que estão com as folhas mais brancas e capas mais conservadas. Estão neles as novidades! Encontrei Refactoring to Patters, agora na seção “O que estou lendo?”. Nem é tão novo assim, mas só foi emprestado uma vez, está branquinho ainda!

Eis que ocorre outro acaso! O sistema da biblioteca estava fora do ar. Encostei no balcão um pouco distante dos computadores dos funcionários à espera. Não haveria chance alguma de encostar ali se não fosse o sistema. Olha só o que encontrei: Um convite para o Concertos na Cidade. O último que estava sobre o balcão. Peguei-o meio desconfiado, pensando que tivesse dono.

Era neste convite que estava minha diversão de quarta. É de lá que acabo de chegar. Um recital de canto e piano. Foi muito bom! Um espetáculo. Conheci um Villa Lobos que não havia ouvido antes com a “Iara”. A interpretação do Reginaldo Pinheiro e da Guida Borghoff foi excepcional.

Desde a primeira vez que ouvi o Reginaldo num programa da Rádio Cultura FM de São Paulo, há uns dois ou três anos atrás fiquei a imaginar que exemplo de Brasileiro de sucesso. Pois hoje tive a oportunidade de confirmar o quanto ele canta bem, logo alí, à minha frente.

Parabéns a professora Ana Flávia Frazão e ao SESC, além dos demais da organização. Estão fazendo um trabalho de primeira qualidade! Continuem nos proporcionando estes bons momentos de boa música.

Ao demais, continuem trocando os cadeados das salas e “derrubando” os sistemas da biblioteca! Façam o necessário para me fazer ficar sabendo destes eventos, ou, simplesmente, deixem o acaso agir por si próprio!

Categories: geral Tags:

A Cabeça de Steve Jobs, de Quem Não Vive no Mundo Mac

August 18th, 2009 1 comment

Acabo de ler o livro A Cabeça de Steve Jobs e para não perder os mais interessantes achados no livro estou aqui registrando-os. Primeiro, o que não gostei.

Não gostei muito da organização do livro. A tentativa do autor, Leander Kahney, de dividir em capítulos por tema resultou em uma certa bagunça. Sabe aquele tipo de escrita que tem muito: “Daqui a pouco falaremos mais disso”? Quase que o único capítulo que segue seu título é o último, o oitavo: “Controle Total – A obra toda”. Aliás, o melhor dos capítulos na minha opnião. O mais esclarecedor do porquê das decisões do Steve.

Ilustrações! Faltou. Durante a leitura senti extrema falta de figuras. É como se o livro fosse escrito somente para quem acompanhou toda a trajetória dos Macs. Pra quem sabe que o Mac tinha o botão de desligar na parte de trás. Para quem acompanhou todas as propagandas “Pense Diferente (Think Different)”. Às vezes tive que recorrer ao YouTube e a figuras na web.

E por falar das propagandas, não parecem tão boas assim. Claro, tem muito a ver com a cultura em que estou inserido. Mas na minha opnião existem propagandas infinitamente melhores aqui no Brasil. Essa parte foi a que mais achei fanatismo dos “Mac-maníacos” juntamente com o ovacionismo nas Macworld’s quando Steve diz: “E tem mais…”.

Inventividade? Nada! Steve, de acordo com o livro, é um “escolhedor”. O que ele faz de melhor é escolher e rejeitar as melhores e piores idéias dos seus colaboradores, para logo depois achá-las uma ótima idéia, com a mínima ou sequer nenhuma alteração. O grande detalhe está no processo de simplificação. Steve rejeitou o nome iPod antes de aceitá-lo.

Steve também “rouba” idéias, como foi o caso da GUI que copiou da Xerox. Não estou condenando. O livro te aconselha a fazer o mesmo! A Xerox não saberia o que fazer com aquilo na época. Ela vendia máquinas de copiar.

Além de escolhedor, é um caçador de talentos. Sempre contrata e mantém os melhores a sua volta. Essa é uma cultura que grande parte dos brasileiros empreendedores não possuem. Talvez seja essa história do jeitinho brasileiro, sempre tentando tapar buraco. Não é possível ser o melhor sem os melhores, nisso eu acredito.

Para manter estes talentos na Apple ele distribui opções de compra de ações, por valores baixos. Quando o funcionário resolve comprar ou vender as ações elas valem mais do que eles pagaram por elas. Isso mantém qualquer um motivado, e inventivo. Não tenho notícias dessa cultura na área de TI aqui no Brasil, mesmo que seja na forma de PLR.

Steve também é um aficcionado por perfeição. Não há como negar que iPod e iPhone são perfeitos demais para a maioria dos usuários. O acabamento é muito bem feito. Duvida? Então vejamos. Responda a seguinte pergunta: “Quantas vezes comprou um produto e abriu a caixa observando cada efeito desde a luminosidade, efeitos, o porquê das fontes na embalagem, dobras das abas até, enfim, visualizar o produto?” É, isso mesmo, até a embalagem do equipamento é pensada neste nível de detalhes. Veja a cerimônia desta “unboxing” neste vídeo (como é chamado a abertura da embalagem). O mais interessante é que ao chegar ao iPhone, ele coloca-o de lado. Algum brasileiro faz isso?

Aliás, tudo que roda o mundo Mac parece ter uma certa diferença. Só de curiosidade, passe em uma banca de revista e veja a capa da Mac+ número 38. Acredite, esta foto aqui ao lado não tem nada a ver com olhá-la em suas mãos.

Confesso que discordei de grande parte do livro até ler o último capítulo. Nele, muita coisa fez sentido para um usuário de Linux e Windows. Há uma explicação interessante dos modelos vertical e horizontal de distribuição de equipamentos. Steve, desde que fundou a Apple, segue o modelo vertical.

No modelo vertical a distribuição contempla o conjunto: hardware, software e serviços, ou seja, a solução completa. O iPod por exemplo não é somente o aparelho. É o conjunto: aparelho, software e loja iTunes. E isso vai contra o que aconteceu nos últimos 30 anos. Buscou-se uma comoditização/generalização do hardware, e algumas empresas focaram em hardware (Intel, AMD), outras em software (Microsoft) e outros ainda em serviços para as plataformas.

Ser o dono de tudo facilita muito a distribuição e reduz drasticamente a quantidade de erros de integração. A Microsoft demorou mais copiou isso, com o Zune e o XBox. E aparentemente o mundo está girando a favor da Apple neste sentido. O autor se refere a isso como se Steve estivesse à frente do seu tempo, cerca de trinta anos. Não estou certo disso.

Mas isto está virando resumo do livro! Vou deixar a idéia solta, para sobrar vontade de ler o livro! Há muito mais do que o escrito aqui! Hummm, nem falei da obsessão pelo segredo até o lançamento, o formato das lojas de varejo, …

Categories: computação Tags: , , , ,

Hadoop, Núvens, Banco de Dados distribuído, Delphi é útil neste ambiente?

July 28th, 2009 No comments

Serviços nas nuvens estão na moda. Todo dia chega alguma mensagem na minha caixa a respeito. Talvez porque o tema de minha dissertação esbarra no assunto, mas acredito que não.

Então veio a pergunta hoje, depois de receber um anúncio a respeito do HadoopDb. Alguma pessoa que programa em Delphi trabalha com um projeto que precisa escalar ao ponto de rodar a aplicação em um cluster de 50, 100 nós?

Ou estes “monstros” são pilotados sempre com Java/C++?

Seria por conta de não ter como acessar diretamente no Delphi, já que não fazem binding para Delphi? Mas e aí, serviços na nuvem vieram para ficar, na minha opnião. Se houvesse um driver DBX, por exemplo, que mapeasse a API para chamar este tipo de serviço, alguém em Delphi usaria?

Enfim, muitas questões. Será que Delphi cabe neste mundo?

Categories: computação, delphi Tags:

FieldByName é O(n), que tal melhorá-lo para O(Lg n)?

July 19th, 2009 8 comments

Há muitas formas de acessar os campos dos DataSets no Delphi, conforme a relação a seguir (observe a relação linha x item enumerado):

DataSet.Fields[0].AsString
cdsClienteNOMECLIENTE.AsString
DataSet.FieldByName('NOMECLIENTE').AsString
DataSet['NOMECLIENTE']
  1. Pelo índice do campo: É uma causa frequente de erros, afinal, mudando a ordem dos campos (na SQL ou no DataSet) altera totalmente o comportamento do código.
  2. Diretamente pelo objeto que representa o campo: Evita os erros da primeira e ainda garante que você acesse somente campos que existem no dataset, avisando durante a compilação caso contrário. Só pode ser usada quando os campos são adicionados em tempo de projeto. Quando se trabalha com multi-bancos existem problemas de mapeamento de tipos de campos e classes de representação.
  3. Por FieldByName: Evita os problemas da primeira abordagem. Mas não há aviso a respeito de campos não existentes no dataset em tempo de compilação.
  4. Pegando o valor diretamente: Usa FieldByName internamente.
  5. Alguma outra?

Para o objetivo deste artigo, irei considerar o uso de FieldByName (3).

Não uso FieldByName, portanto vou parar de ler o artigo!

Calma! Há um detalhe que passa despercebido. Mesmo você não usando, a própria VCL e componentes de terceiros estão cheios de chamadas a este método! Por exemplo, um simples TDBEdit chama este método. O DBGrid, o seu gerador de relatórios e muitos outros.

Hummm, mesmo atribuindo o DataField em tempo de projeto ao TDBEdit?

Sim! A propriedade DataField é uma string. Para fazer o primeiro vínculo é chamado o método FieldByName. Observe este trecho de código, retirado da unit DBCtrls.pas:

procedure TFieldDataLink.UpdateField;
begin
  if Active and (FFieldName <> '') then
  begin
    FField := nil;
    if Assigned(FControl) then
      SetField(GetFieldProperty(DataSource.DataSet, FControl, FFieldName)) else
      SetField(DataSource.DataSet.FieldByName(FFieldName));
  end else
    SetField(nil);
end;

Abra a unit DBGrids.pas e procure por FieldByName. Você irá encontrar referência em muitas linhas.

Chegamos então a questão do título. O algoritmo que procura um campo no dataset é linear em relação a quantidade de campos, ou seja, sua complexidade é:

  • Ω(1). No melhor caso, o campo procurado é o primeiro da lista.
  • Θ(n/2). No caso médio, você encontra o campo mais ou menos na metade e para.
  • O(n). No pior caso, o campo procurado é o último. O nome do campo foi comparado com todos os outros.

Veja o algorítmo, retirado da unit DB.pas. Note que o TDataSet.FieldByName chama TFields.FindField:

function TFields.FindField(const FieldName: string): TField;
var
  I: Integer;
begin
  for I := 0 to FList.Count - 1 do
  begin
    Result := FList.Items[I];
    if WideCompareText(Result.FFieldName, FieldName) = 0 then Exit;
  end;
  Result := nil;
end;

Repare a simplicidade. Na linha 5 é realizado um for na lista de campos (FList). Atribui o i-ésimo item à variável de retorno Result na linha 7. Na linha 8, caso o FFieldName seja igual ao campo procurado o algoritmo é interrompido. Se o campo procurado for o último da lista, o for será executado completamente.

Isso é conhecido como o algoritmo do pintor burro. Suponha que você contrate um pintor para pintar aquelas linhas do meio da rodovia. Mas o pintor não move a lata de tinta. Então todas as vezes ele molha o pincel, pinta a rodovia e volta para molhar o pincel novamente. No começo é rápido, mas quanto mais ele se distancia da lata de tinta, mais demorado fica. (Veja mais sobre isso neste ótimo post no Blog do Joel)

Puxa, isso é muito ruim. Como melhorar isso?

De fato existem alguns algoritmos melhores para fazer isso. Pode-se implementar um hash que distribua os nomes dos campos de acordo com os índices. Mas isso parece um pouco complicado. Além do mais, não existe este tipo de estrutura pronta no Delphi, e então seria necessário incluir uma outra dependência no DB.pas.

Outra forma de melhorar é usar uma lista ordenada. Sabe-se que procurar um item numa lista ordenada é O(lg n). Inclusive, este algoritmo é implementado no tão conhecido TStringList. Só é necessário ordenar ele, com a propriedade sorted := true.

Ótimo então, vamos alterar o arquivo DB.pas e incluir uma lista ordenada!

Realizar uma alteração em um arquivo da VCL é mais complicado que só alterar o código. O ideal seria:

  1. Adicionar uma variável privada na classe TFields do tipo TStringList.
  2. Ao adicionar os Fields no dataset, adicioná-lo também nesta outra lista ordenada.
  3. Ao procurar por um campo, utilizar a lista ordenada.

Porém, alterar a definição de um objeto implica em recompilar todas as units dependentes. Isso inclui tudo que usa TDataSet, inclusive partes da própria VCL. Já recebeu à famosa mensagem Unit x was compiled with a different version of y?

Como é melhor causar o menor impacto possível, a saída é declarar uma variável global na unit DB.pas. Porém, sendo global, não temos uma instância própria para cada instância de dataset. Isso implica em termos uma lista de datasets antes. Cada item desta lista tem uma outra lista com os campos, ou seja, uma lista de listas. (Uma lista de datasets onde cada item é uma outra lista de campos)

Desta forma, realizar a alteração é feito na seguinte ordem:

  1. Declarar uma variável global do tipo TStringList. Iniciar na seção initialization e destruir na finalization;
  2. Alterar o método FindField da classe TDataSet. (O melhor seria FindField de TFields, mas o código não ficaria tão simples, já que precisaria preocupar com a leitura de campos do dfm)
  3. Na primeira chamada de FieldByName, construir a lista ordenada de campos
  4. Destruir a lista ao fechar o dataset

“Há, mas qual é o overhead introduzido com estas alterações?”

Bom, não tem como não ter nenhum. Então o overhead introduzido com esta alteração é o seguinte:

  • Uma lista é instanciada no início da aplicação. Esta lista será preenchida com dataset’s que invocaram o método FieldByName pelo menos uma vez. O dataset é removido da lista quando for fechado. Isso só é preocupante quando se tem muitos dataset’s ativos na aplicação. Deixá-los abertos também é uma má prática, ok?
  • Uma outra lista é instanciada para cada dataset, e contém os campos do mesmo, de forma ordenada. É executado o algoritmo quicksort Θ(lg n) para ordenar a lista. Isto é feito uma vez a cada abertura do dataset.
  • O quicksort tem pior caso O(n²), quando os itens já estão ordenados. Mas em geral isso raramente irá acontecer, certo?

Não seria melhor remover o dataset da lista somente no evento Destroy do TDataSet?

Seria. Mas há o caso de dataset’s temporários, onde os campos são criados em tempo de execução. E se o desenvolvedor fechar o dataset e modificar os campos?

Para ser mais breve, vou anexar um diff do arquivo DB.pas no final. Por hora, uma análise da alteração no método TDataSet.FindField:

function TDataSet.FindField(const FieldName: string): TField;
var
  List: TStringList;
  i, di: Integer;
begin
  di := DataSetsListOrderFields.IndexOf(GetObjectUniqueName(Self));
  if di < 0 then
  begin
    List := TStringList.Create;
    List.Capacity := FFields.Count;
    for i := 0 to FFields.Count - 1 do
      List.AddObject(FFields[i].FieldName, Fields[i]);
    List.Sorted := True;
    DataSetsListOrderFields.AddObject(GetObjectUniqueName(Self), List);
  end
  else
    List := TStringList(DataSetsListOrderFields.Objects[di]);

  Result := nil;
  if List.Find(FieldName, i) then
    Result := TField(List.Objects[i]);
  if (Result = nil) and ObjectView then
    Result := FieldList.Find(FieldName);
  if Result = nil then
    Result := FAggFields.FindField(FieldName);
end;

Seja m a quantidade de dataset’s abertos e n a quantidade de campos:

  • Ao iniciar o método (linha 6), procuramos pelo dataset na lista. Essa operação leva O(lg m), já que esta lista também é ordenada.
  • Se ele não é encontrado (primeira chamada a FieldByName), o dataset é então adicionado a lista (linhas 9 a 14). Esta operação leva O(n + lg m). O lg m é para buscar a posição onde inserir o dataset.
  • Na linha 20 o campo é então procurado, isso leva O(lg n).

Resumindo, a complexidade total na primeira chamada seria O(2 lg m + lg n) e nas demais O(lg m + lg n). Poderia remover o O(lg m) se fosse declarado uma nova variável a classe TDataSet. Mas esta complexidade já garantirá um bom desempenho. Vamos aos testes?

Os testes executados consistem em criar um ClientDataset com cem (100) campos inteiros, preenchê-lo com 10, 20 e 30 mil registros usando FieldByName e consultar os valores do melhor caso (1º campo), caso médio (50º campo) e pior caso (último campo). Veja a figura com os resultados:

Comparação de FieldByName O(n) e O(lg n)
Tempos da comparação de FieldByName O(n) e O(lg n)

Os testes foram executados em uma máquina virtual VMWare com Windows XP e Delphi 2009. O aplicativo foi executado fora do Delphi, para não haver interferência do debugger. Talvez os tempos mudem em uma máquina real, mas acredito que a proporção entre eles se mantenha. Segue uma breve discussão dos resultados:

  • Append: Na adição de registros todos os campos são chamados uma vez para cada registro. O novo método FieldByName mostra-se até 73% mais rápido que o antigo (de 9,78 para 2,59 segundos).
  • No melhor caso: Como era esperado, o novo método é alguns centésimos de segundos (0,14 para 0,17) pior. Isso ocorre porque o novo algoritmo é Ω (lg n), ao contrário do antigo, que é Ω (1).
  • No caso médio: O novo FieldByName chega a ser 63% mais rápido que o antigo.
  • No pior caso: O novo FieldByName é até 80% mais rápido.
  • Constante: Observe também que tempo entre o melhor, médio e pior caso se mantém constante entre os registros, mostrando que sua complexidade é sempre lg n (na tabela, destacado em laranja).

Aqui está o arquivo diff com as modificações no arquivo DB.pas e o código dos testes. Elas foram feitas para o Delphi 2009. Aplicarei elas ao Delphi 2006 e 2007. Caso haja alguma diferença, postarei as outras versões.

Para você que resistiu firme até aqui, se tiver algum comentário ou observação, sinta-se a vontade!

Categories: computação, delphi Tags:

Desde o último post

July 18th, 2009 No comments

Muita coisa aconteceu desde o dia do último post: 23/03/2006. A graduação acabou! Agora sou casado, a mais de ano! Veja só como isso também passou rápido.

Profissionalmente ainda trabalho na mesma empresa, Siagri. Mas agora estou em Goiânia, também a mais de ano.

Neste meio tempo sem publicações por aqui, andei publicando na revista Active Delphi, uma série de artigos sobre DBX4. Também criei dois driver DBX4 para Firebird e PostgreSQL.

Já cursei a metade do mestrado! Já passei por todas as disciplinas obrigatórias. A pesquisa está bem avançada. É em sistemas distribuídos, mais especificamente R-Trees distribuídas e como fazer Joins nessas estruturas com Hadoop.

Vem comigo nesta nova fase? Publicarei sobre assuntos do mestrado e novidades em geral. Meus interesses continuam os mesmos, exceto por ter expandido bastante eles.

Agora não são mais duas linguagens, são várias como C++, C#, Delphi, Java, Python. Em banco de dados, estive estudando Oracle este tempo todo, e não é por nada, mas já consegui aprender alguma coisa.

Categories: geral Tags:

Recital de violão

March 23rd, 2006 No comments

Como é do conhecimento de alguns, a Siagri está promovendo um Recital de Violão Clássico no auditório do SENAC neste sábado, às 20:00. A entrada é franca. Serão abordados compositores estrangeiros e nacionais como Bach, Tárrega, João Pernambuco, dentre outros.

Convido a todos para prestigiarem o evento com sua presença. Os “recitantes” serão funcionários da Siagri. Wisley e eu no violão e Cristiane como contralto.

Veja um fragmento de apresentação do programa:

“E sempre notável a aparição de música clássica nas mais variadas situações. Aquela reportagem de arte, arquitetura ou culinária sempre tem fundo clássico. E o uso na educação? Alunos de renomados colégios aumentam sua capacidade de concentração e aprendizado estudando ao som de gênios.

De fato, desde os mais remotos tempos, música clássica é uma forma de expressão da inteligência humana. Ao violão, instrumento romântico, dos mais variados sons, soa com extremo dinamismo e beleza.

Mas de onde surgiu? Como se instalou em tal instrumento musical? O que cada compositor pretende mostrar com determinado andamento e combinação de tons? O que o nosso povo conseguiu e consegue produzir a este respeito?

Pretendemos apresentar a você nosso convidado, talvez não acostumado a este tipo de evento, um outro leque de música. A música dita por erudita, clássica, que é transmitida através de notação musical ao som do instrumento mais tocado no mundo.”

Conto com sua presença!

Categories: música Tags: