Einstein Analytics e Go

É raro termos a chance de comparar diretamente duas tecnologias uma contra a outra para a mesma tarefa.

Mas às vezes as estrelas se alinham, seja porque você começa a experimentar efeitos negativos da sua pilha atual, novas tecnologias aparecem que atendam às suas necessidades exatas, ou o conjunto de escala e recursos do seu projeto superou a tecnologia na mão.

 

Em nossa Pesquisa de 2019, perguntamos que tipo de conteúdo os usuários do Avance Network gostariam de ver além de perguntas e respostas. A resposta mais popular foi "artigos de tecnologia escritos por outros desenvolvedores." Então, a partir de agora, publicaremos regularmente artigos de colaboradores. Se você tiver uma ideia e quiser enviar um pitch, você pode enviar uma mensagem em meu perfil.

 

É raro termos a chance de comparar diretamente duas tecnologias uma contra a outra para a mesma tarefa. Mas às vezes as estrelas se alinham, seja porque você começa a experimentar efeitos negativos da sua pilha atual, novas tecnologias aparecem que atendam às suas necessidades exatas, ou o conjunto de escala e recursos do seu projeto superou a tecnologia na mão. 

 

Aqui na Salesforce, tivemos apenas essa situação nos últimos anos. Nós portamos a maioria do nosso Einstein Analytics backend de um híbrido Python-C para Go. Go é uma linguagem que o Google projetou para engenharia de software moderna e em larga escala. A história diz que os engenheiros do Google tiveram a ideia de criar uma linguagem projetada para seus aplicativos em grande escala e começaram a projetar Go enquanto esperavam seus projetos C++ maciços compilarem.

 

Este post discutirá nossa experiência em mover software de nível corporativo de um híbrido C-Python para um (quase) aplicativo Completamente Go. 

 

Einstein Analytics adiciona processamento de business intelligence às instâncias do Salesforce. Através do processamento de IA baseado em nuvem, ele gera insights acionáveis — previsões, relatórios de pipeline, medições de desempenho — diretamente a partir de dados do CRM da Salesforce, além de dados externos que o cliente precisar, independentemente de sua estrutura e formato. 

 

Nos bastidores, uma determinada instância do Salesforce expõe a funcionalidade do Einstein Analytics como parte das APIs regularesdo Salesforce REST . Esses link para um cluster de servidores de consulta, que cada um serve consultas de seus conjuntos de dados vinculados armazenados em cache na memória, embora possam preencher seus dados armazenados em cache a partir de qualquer nó no cluster. Para gerenciar todas essas solicitações, temos um processo otimizado em cada um desses servidores que encaminha solicitações para o nó apropriado e encaminha a resposta ao originador da solicitação de API. Para qualquer servidor de consulta que leia conjuntos de dados, todas essas chamadas parecem locais. E local significa rápido. Conjuntos de dados maiores são particionados, e um coordenador de consulta apátrida agrega dados de subqueries de partição remota.

 

Os conjuntos de dados são criados usando um processo de lote ETL (extrato, transformação, carga) e, em seguida, armazenados em um formato de banco de dados colunaar proprietário. O mecanismo de consulta e as ferramentas de criação de conjuntos de dados para o produto que eventualmente se tornou Einstein Analytics foram originalmente escritos em C para desempenho com um invólucro Python que forneceu funcionalidade de nível superior — consultas de análise, um servidor de API REST, o mecanismo de expressão e muito mais.

 

Em essência, o produto foi construído para ter o melhor dos dois mundos. Python é ótimo para escrever rapidamente aplicativos de nível mais alto, mas nem sempre oferece o alto desempenho necessário em um nível corporativo. C cria executáveis altamente performáticos, mas adicionar recursos leva muito mais tempo.

 

Primeira peça para Go

 

Inicialmente, essa combinação tinha funcionado. Mas depois de construir o software por anos, einstein analytics começou a mostrar desacelerações de desempenho. Isso porque qualquer recurso que não fazia parte do mecanismo de consulta principal foi adicionado ao invólucro Python. Os recursos poderiam ser desenvolvidos e implantados rapidamente desta forma, mas com o tempo, eles arrastaram todo o sistema para baixo. Python não faz multi-threading muito bem, então quanto mais o invólucro estava sendo solicitado a fazer, pior ele desempenhou. 

 

A equipe anterior já estava olhando para portar o invólucro para Go, então nós demos uma olhada também. Logo percebemos que em um sistema de nível corporativo, teríamos dois problemas adicionais. Primeiro, o Python usa a digitação solta, o que foi ótimo para uma pequena equipe desenvolvendo rapidamente novas ideias e colocando-as em produção — mas menos ótima para um aplicativo em escala corporativa pelo qual alguns clientes estavam pagando milhões de dólares. Em segundo lugar, previmos um vasto pesadelo de dependência no horizonte, pois implantar as bibliotecas, versões e arquivos python certos se tornaria uma tarefa. Então, em 2014, decidimos portar o invólucro Python para Go. 

 

Inicialmente estávamos cautelosos com o jovem ecossistema Go, mas quando comecei a olhar para as metas de design do idioma (Vá no Google: Language Design in the Service of Software Engineering), fiquei impressionado com o quão próximo ele se alinhava com os nossos. Ele é construído para engenharia de software mais do que sofisticação linguística, então seus pontos fortes incluem ferramentas sólidas incorporadas, compilações e implantações rápidas e fácil solução de problemas. 

 

A realidade do software corporativo é que você gasta muito mais tempo lendo código do que escrevendo-o. Nós apreciamos que Go torna o código fácil de entender. Em Python, você poderia escrever compreensão de lista super elegante e belo código que é quase matemático. Mas se você não escreveu o código, então essa elegância pode vir às custas da legibilidade.

 

O projeto portuário correu muito bem. Ficamos super felizes com o desempenho e a manutenção do novo invólucro. Uma das poucas reclamações que envolvemos uma troca da linguagem feita na escolha da escalabilidade em vez do desempenho bruto para ajudar na coleta de lixo: eles decidiram começar a armazenar tipos primitivos em interfaces como ponteiros em vez de valores, o que introduziu sobrecarga de desempenho e alocações adicionais para nós.

 

Tudo deve ir

 

Mas a experiência foi boa o suficiente para que, quando chegou a hora em 2016 de escrever um novo kernel de mecanismo de consulta com um otimizador melhor e melhorar nossas ferramentas de criação de conjuntos de dados, decidimos fazê-los em Go. Estávamos ganhando expertise no mesmo ritmo que o ecossistema Go estava amadurecendo, então fazia sentido reduzir a sobrecarga e tornar nosso código reutilizável em uma única língua. Além disso, queríamos eliminar a sobrecarga da interface CGO. 

 

A grande incógnita para isso era a performance. Go usa um modelo leve de "linha verde" de IO assíncronos em seus Goroutines,o que nos deu a vantagem multi-threading sobre Python, mas o código C funciona tão rápido quanto você deixa — ele troca a segurança incorporada por velocidade, além de compiladores C são mais maduros e têm melhores otimizações. Nossa equipe criou uma prova de conceito (POC) que alcançou quase paridade no desempenho com o motor C, mas apenas se usarmos os padrões de programação certos:

 

Tampe todos os IO para reduzir a sobrecarga nas chamadas do sistema Go. Em uma chamada do sistema, os Goroutines atuais cedem a essa chamada.

Quando possível em loops apertados, use estruturas em vez de interfaces para minimizar a sobrecarga de indireta dos métodos de interface.

Use buffers pré-alocados em loops apertados (da mesma forma que io. O leitor trabalha) para minimizar a pressão da coleta de lixo.

Processe linhas de dados em lotes como uma solução alternativa para a má inlintação do compilador, a medida em que mover a computação real para mais perto dos dados e minimizar a sobrecarga em cada chamada de função.

Essa reescrita foi concluída em 2017 e a nova versão go do Einstein Analytics foi para disponibilidade geral em 2018. Mantendo tudo na mesma língua, poderíamos reutilizar o código e trabalhar de forma mais eficiente. E o potencial de multiplataforma e trans-empilhamento facilita a portabilidade do código. Se precisarmos de algum desse código em um aplicativo móvel, podemos compilá-lo para iOS ou Android e ele só funcionará.

 

Mais cedo, eu disse que a versão é (quase) completamente escrita em Go. Uma exceção é o nosso gerenciador de clusters, o que pode parecer um pouco estranho, já que Kubernetes e outros tipos de aplicativos de orquestração de cluster são o uso mais comum para Go, mas a equipe dona deste serviço se sentiu mais confortável usando Java. É importante permitir que as equipes possuam seus próprios componentes; você não pode forçar as pessoas a fazer coisas que elas não querem fazer. 

 

Embora Go tenha algumas limitações que tivemos que contornar, estamos muito satisfeitos com os resultados. E Go continua a melhorar. Eles abordaram algumas das fraquezas em seu compilador movendo-o para um formulário de atribuição única estática,o que torna mais fácil fazer otimizações extravagantes. A coleta de lixo está ficando mais eficiente, e muitas vezes o compilador é inteligente o suficiente para realizar análises de fuga para detectar quando valores variáveis podem ser alocados baratamente na pilha em vez do monte.

 

Como desenvolvedor, se você quiser escrever código altamente performático em qualquer idioma, você precisa estar familiarizado com o funcionamento do compilador. Isso não está embalado na linguagem. Go tem uma referência muito simples — apenas duas páginas! Mas saber sobre o compilador requer reunir todo esse conhecimento tribal espalhado sobre, coisas que detalham todas as otimizações que você pode usar na versão específica do Go que você está usando. 

 

Depois desses portos, nossa equipe construiu alguma experiência com Go e suas peculiaridades compiladoras. Mas você ainda pode se queimar. Por exemplo, você pode muito facilmente escrever dados que você quer colocar na pilha mais barata em vez de para o monte muito mais caro. Você nem vai saber que isso está acontecendo lendo seu código. É por isso que, como em qualquer novo idioma que você exige alto desempenho, você precisa monitorar os processos de perto e criar benchmarks em torno do uso de CPU e memória. E então compartilhar o que você aprende com a comunidade para que esse conhecimento se torne menos tribal. 

 

Conclusão

 

Pode ser uma aposta escolher uma linguagem mais nova e introduzi-la em uma empresa corporativa. Felizmente, o ecossistema Go cresceu conosco. O Google continua apoiando o idioma e tem sido adotado em outras grandes empresas. Agora temos uma equipe de engenheiros trabalhando em Go em tempo integral, e continuamos a ver resultados positivos. Estamos ansiosos para crescer com a comunidade Go e compartilhar mais do que aprendemos com nossas experiências. 

 

A Salesforce acredita que o apoio a tecnologias de código aberto como o Go impulsiona nossa indústria, inicia novas carreiras e constrói confiança nos produtos que criamos. Contribuímos para milhares de projetos de código aberto todos os anos, desde tecnologias fundamentais que impulsionam nossa inovação até projetos comunitários que fazem do nosso mundo um lugar melhor.

 

 

O Avance Network é uma comunidade fácil de usar que fornece segurança de primeira e não requer muito conhecimento técnico. Com uma conta, você pode proteger sua comunicação e seus dispositivos. O Avance Network não mantém registros de seus dados; portanto, você pode ter certeza de que tudo o que sai do seu dispositivo chega ao outro lado sem inspeção.


Strong

3733 Blog Postagens

Comentários