Estou entediado de linguagem X

Eu quero ir rapido

John Murray Blocked Unblock Seguir Seguindo 4 de janeiro

Eu não tenho programado há muito tempo, mas cheguei ao ponto de estar um pouco entediado trabalhando em Ruby, Python, Scala, PHP, C # e JavaScript (para citar alguns). Novos idiomas parecem antigos idiomas, remixados. As preocupações são mais ou menos semelhantes e os desafios são os mesmos. Eu preciso de um novo desafio.

(fonte: memeshappen.com )

Mas o que isso significa? Para mim, isso significou aprender C ++ e, bem, construir coisas realmente rápidas. Isso significa aprender um novo domínio e levar o software artesanal a um novo nível. Continue lendo e eu vou explicar.

Querendo ir rápido (em C ++)

A capacidade de ir rápido sempre esteve lá na forma de C ou C ++. Mas eu sempre ouvi rumores desagradáveis, vi código feio e tinha a noção geral de que era realmente fácil atirar no próprio pé.

(fonte: xkcd )

Isso sempre me fez manter minha distância, isto é, até que meu trabalho diário me tivesse programado em uma grande aplicação-C. E mais ou menos minhas suspeitas confirmaram que C não era uma linguagem ergonômica. Era difícil de usar, difícil de ler e não era muito divertido de programar. Foi quando descobri Rust .

Rust parecia muito com o Scala – um dos meus idiomas favoritos -, mas com foco no desempenho, um tempo de execução mínimo e compilando diretamente para código de máquina. Desta forma, direcionou grande parte do domínio do C ++. No entanto, também colocou uma grande importância na segurança do código e evitando as armadilhas comuns de C ou C ++. Existe até um sistema operacional totalmente funcional construído sobre o Rust, que é uma boa demonstração desses princípios.

Passei uma boa parte do meu tempo livre aprendendo Rust, ficando animado com Rust, e liderando um encontro semanal para resolver problemas e discutir soluções em Rust. Eu estava definitivamente no trem Rust.

(fonte: github.com/rochacbruno/rust_memes )

E então a vida aconteceu novamente.

Meu dia-trabalho mais uma vez me empurrou de volta para o território de C, desta vez com a adição de C ++. Era um projeto predominantemente greenfield, o que significava que a maior parte do meu trabalho seria escrever um novo código C ++ sobre bibliotecas compartilhadas existentes em C.

Era, mais uma vez, hora de mergulhar de novo na terra do código não ergonômico e difícil … ou assim pensei.

Aprendendo C ++

Se você não aprendeu C ++, ou apenas teve que tocá-lo durante a sua aula de algoritmos universitários, então você deve saber que o C ++ existe em duas formas. Existe o pré-C ++ 11, que pode ser descrito como “C com classes” e existe o C ++ 11 e além (11, 14, 17 e logo 20).

Fiquei mais do que agradavelmente surpreso ao ver que muitos dos recursos “modernos” que eu gostava em Rust também existiam em C ++. Ele possui "ponteiros inteligentes" que conferem certas propriedades de propriedade, como exclusividade ou objetos compartilhados (referência contada). Junto com isso, há a semântica RAII, que torna fácil evitar grande parte do código que era tão fácil de disparar no próprio pé.

(fonte: modernescpp.com )

A última versão (17) trouxe atualizações incrementais sobre 11 e 14 para melhorar a biblioteca e adicionar vários recursos pequenos (como ligações estruturadas). No entanto, o FileSystem TS (especificação técnica) chegou e é uma grande melhoria na ergonomia da linguagem.

O C ++ 20 poderá ver algumas melhorias ergonômicas importantes com conceitos (semelhantes a interfaces estilo Go), redes, módulos, corrotinas, recursos de simultaneidade (futuros, travas, barreiras, ponteiros atômicos inteligentes), reflexão em tempo de compilação e alguns outros recursos não vou mencionar porque eles começam a se aprofundar um pouco na floresta.

O que estou tentando dizer é que o moderno C ++ é, na verdade, apenas isso – moderno. Ele contém todos (ou pelo menos a maioria) dos recursos que estou acostumado a usar em uma linguagem como Scala. E é uma linguagem muito mais segura do que costumava ser. E o melhor de tudo é que a evolução não está parando. Recursos novos e interessantes estão sendo constantemente adicionados ao idioma.

É justo dizer que o C ++ esteve atrasado em termos de recursos de linguagem, recursos de biblioteca padrão e ferramentas (sistemas de criação e gerenciadores de pacotes para serem específicos). Mas tudo isso está melhorando (e em ritmo acelerado). Eu até ouvi isso ser chamado de C ++ Renaissance por desenvolvedores C ++ de longo prazo.

PS – Se isso te entusiasmar, confira um novo projeto em que estou trabalhando no cpp-vs.com para uma maneira diferente de aprender C ++.

Artesanato (Performance Edition)

(Foto de Clark Young no Unsplash )

Artesanato é algo que todos nós podemos obter, porque essencialmente significa criar um código bonito. E bonito pode significar fácil de ler, fácil de estender / modificar, fácil de testar ou todos os itens acima (e mais). E é divertido experimentar novas técnicas e padrões mestre que permitem que nosso código seja bonito.

Para mim, pessoalmente, eu queria mais e C ++ entregou isso na forma de desempenho. Com isso quero dizer que há toda uma nova classe de problemas a serem resolvidos para que, na minha opinião, caiam sob a égide da criação de código bonito.

Modelos de propriedade

Ao lidar com dados não coletados pelo lixo, precisamos garantir a manutenção de um código seguro. Isso significa não destruir as coisas que estão em uso, não usar coisas que foram destruídas, e também não segurar objetos indefinidamente (vazando memória).

Isso significa fazer uso de ponteiros inteligentes para determinar o que é de propriedade exclusiva, o que é compartilhado, o que é armazenado em cache e a definição de um modelo de propriedade em seu aplicativo. Isso permite que você use tipos de ponteiro inteligente para declarar explicitamente o contrato de memória com outras partes do seu código.

  • Este pedaço de dados é garantido para existir contanto que eu tenha?
  • Posso guardar uma cópia deste ponteiro para mim?
  • Posso compartilhar cópias deste ponteiro com outras partes do aplicativo?

Em nossos idiomas coletados com lixo, raramente pensamos em propriedade, embora possamos pensar em termos de imutabilidade, mas isso normalmente significa cópias. Quando um fator determinante para nosso código é o desempenho, trocamos cópias por uma semântica de propriedade forte (quando possível).

Abstrações de custo zero

Imagine aplicar código funcional a uma lista de dados – map, flatMap, filter, etc. Agora imagine que quando você compila este código, você obtém um loop com zero cópias desnecessárias de seus dados com todas essas ações perfeitamente recolhidas. Isso, em essência, é uma abstração de custo zero.

É a capacidade de projetar bibliotecas e escrever códigos que nos permitem ser expressivos e escrever código legível. Em seguida, permitimos que o compilador otimize esse código de alto nível em um código de baixo nível muito eficiente.

Ao escrever C ++, este é um núcleo-principal da biblioteca de linguagem e padrão, e é algo que deve ser buscado ao desenvolver abstrações e bibliotecas internas.

Padrões de Concorrência

Se você quer ir rápido, você tem que ser cuidadoso e atencioso com seus padrões de concorrência. O seu aplicativo de E / S está vinculado? Está ligado à CPU? E você modelou seu aplicativo para aproveitar esse limite?

Se você está usando E / S, você está usando um modelo com eventos como libevent ou libev ? Se você está limitado à CPU, você está fixando seus threads e utilizando NUMA ? Você modelou corretamente sua simultaneidade para maximizar o desempenho de seus aplicativos?

Ao contrário das linguagens de nível mais alto, o C ++ permite a você a liberdade de ajustar como seu aplicativo atinge a simultaneidade. Proporcionando a você maior controle sobre as características de desempenho de seus aplicativos.

Linhas de Cache

Escrever código rápido depende da compreensão de como o hardware executará seu código e de como ele armazenará os dados do aplicativo. Organizar seu código em padrões que permitem utilizar mais cache e evitar erros de cache será importante para ir mais rápido.

Laços apertados são o exemplo canônico. Isso significa executar um loop que envolve apenas dados locais (como a lista sendo iterada). Outro padrão emergente é chamado de Design Orientado a Dados, que é uma ótima maneira de maximizar a eficiência do cache no nível do aplicativo – um escopo muito maior do exemplo do circuito fechado.

Você quer ir rápido?

Se isso te excita, confira esta incrível lista de recursos para começar a aprender C ++ e ir rápido.

Artigos relacionados por John Murray

Programação de Sistemas
Desmistificado com uma exploração livre de jargão. hackernoon.com
Como lidar com limites de taxa com o Scala Futures
Desacelerar, indo rápido para ir mais rápido. itnext.io