Em um programa conjunto de ITMO e JetBrains
Master , solicitamos aos alunos que são enviados para a conferência que escrevam um relatório com uma revisão dos relatórios.
Publicamos um desses relatórios sobre a conferência C ++ Russia Piter 2019. O autor é um estudante do segundo ano Artyom Khoroshev.

No início de novembro, participei da conferência cpp-russia-piter, abaixo vou falar sobre os relatórios que me lembro.
Roman Rusyaev: exceções C ++ através do prisma de otimizações do compilador
Um relatório interessante no qual o orador do exemplo do LLVM falou sobre exceções de custo zero no C ++ moderno.
O LLVM IR apresenta o programa como um gráfico de controle de fluxo. Nos nós do gráfico, existem blocos de instruções que devem ser seguidos. No final de cada bloco, existe um terminador que transfere o controle para o próximo bloco. O terminador pode ser uma transição condicional para outro bloco, uma instrução de retorno ou uma instrução de chamada especial, que tem a semântica de chamar a função e, se bem-sucedida, transfere o fluxo de controle para um bloco e, no caso de uma exceção, indica o bloco no qual você deseja processá-lo. As instruções em um bloco têm a propriedade de que, se batermos em um bloco, executaremos todas as instruções ou não cairemos nesse bloco. Existem otimizações que podem funcionar apenas em um único bloco. No caso de blocos pequenos, eles terão um contexto menor, como resultado, é pior fazer otimizações.
O palestrante falou sobre como os compiladores modernos podem converter instruções de chamada em instruções de chamada, que não são mais terminais e, como resultado, dão ao compilador mais espaço para otimizações. Mas, para não confiar no compilador, você mesmo pode escrever a função noexcept (se estiver correta) para garantir que o compilador executará todas as otimizações.
(slides do relatório)Maxim Khizhinsky: Habitação da classe Comfort para atores e manipuladores
O orador estabeleceu uma meta para se livrar de vários problemas associados à programação paralela:
- dados compartilhados
- mudança de contexto,
- sincronizando
- Criação frequente de fluxo em tempo real para necessidades de curto prazo.
Como resultado, o palestrante sugeriu dividir seu programa em componentes, cuja vida útil será igual à vida útil do programa, e colocar componentes em "apartamentos", cujo número deve ser igual ao número de threads. Os próprios componentes, como resultado, são de thread único e a comunicação entre os componentes deve ocorrer através da passagem de mensagens. Concordo que isso resolve o problema, mas à custa de toda a personalização do nosso programa, devemos fazê-lo no momento da compilação. No mínimo, é necessário no momento da compilação distribuir uniformemente os componentes entre os “apartamentos”, o que impede ainda mais o sistema de reequilibrar dependendo da carga. Como resultado, na minha opinião, a solução em si não parece suficientemente flexível.
(slides do relatório)Nikolay Beloborodov: O uso de alocadores de placas em aplicativos de rede altamente carregados
O nome fala por si. O palestrante contou como eles aumentaram significativamente o desempenho do sistema usando um
alocador de placas . O alocador de placas opera em várias entidades:
- laje é uma parte contígua da memória (geralmente um tamanho fixo) que é dividida em seções do mesmo tamanho. Essas áreas são usadas para armazenar objetos do mesmo tamanho,
- cache - uma lista de lajes com a mesma divisão,
- alocador de placas - um conjunto de caches.
Graças a esta construção, objetos do mesmo tamanho são armazenados localmente. A desalocação é projetada como uma marca de que um site específico é fraco e pode ser reutilizado. Isso evita a fragmentação da memória.
A partir dessa definição da laje de um alocador, fica claro que ela é adequada para destacar a liberação de objetos cujo tamanho está em um intervalo limitado. Por exemplo, alocando um tamanho cada vez maior, um novo cache será criado, os caches antigos não serão reutilizados.
O orador disse que, por causa disso, eles tiveram que abandonar alguns contêineres, em favor de outros. Por exemplo, o vetor foi substituído por uma lista, hashmap por uma árvore, mas, no entanto, ainda foi obtido um ganho no desempenho.
(slides do relatório)Anton Polukhin: Truques de táxi em C ++
Os relatórios de Anton Polukhin são sempre interessantes e as soluções que ele oferece parecem boas. Dessa vez, Anton mostrou como o padrão pimpl pode ser aprimorado em termos de alocação dinâmica. Para fazer isso, você precisa colocar o repositório para o objeto de implementação no próprio objeto. Deixe-me lembrá-lo de que o padrão pimpl clássico é o seguinte:
Queremos nos livrar da alocação dinâmica, para isso, prepararemos um local com antecedência diretamente no objeto Foo:
Este método não funcionará, pois não temos informações completas sobre o tipo Foo_impl em Foo.h e um erro de compilação será recebido. A única solução que resta é adivinhar o tamanho do armazenamento com antecedência.
Mas você precisa adicionar uma verificação de que o tamanho ainda está correto. Isso é necessário, pois uma tentativa de colocar o objeto em um buffer inadequado é UB.
Fazemos uma verificação no arquivo cpp e, se algo for indicado incorretamente, terminamos com um erro de compilação e imprimimos o tamanho correto da estrutura para que o programador possa adivinhar a partir da segunda tentativa.
Anton mostrou como tornar conveniente sua biblioteca de serialização em vários formatos, sem esquecer o recurso ADL: se houver parâmetros de modelo para argumentos de função, a função será pesquisada no espaço de nome de parâmetro desses argumentos.
(slides do relatório)Eric Niebler: Uma abstração unificadora para assíncrona em C ++
Um relatório interessante, que discute os problemas de abstrações assíncronas no padrão de linguagem existente: por que o futuro e a promessa são lentos, e podemos projetar a biblioteca de maneira a evitar essas despesas gerais. Os desenvolvedores do facebook parecem ter uma solução decente
https://github.com/facebookexperimental/libunifex(slides do relatório)Dmitry Kozhevnikov e Andrey Davydov: Dois relatórios sobre módulos
O programa teve dois relatórios consecutivos sobre os módulos. Depois de ouvir os dois relatórios, ficou claro que os módulos ainda não estão prontos para uso. Isso me chateou um pouco, já que não estava interessado em princípio como esse novo recurso da linguagem é implementado e pensei que o C ++ 20 seria lançado e estaria pronto para uso imediatamente. Infelizmente, verificou-se que não é assim.
(slides dos relatórios:
1 ,
2 )
Conclusão
A conferência passada ficou satisfeita com exemplos interessantes de uso de recursos conhecidos da linguagem. Um grande número de relatórios tratava de chips do seguinte padrão - C ++ 20. Obviamente, isso é muito útil para todos os desenvolvedores de C ++.