Otimização de paralelização EVM: A chave para superar os gargalos de desempenho
É bem conhecido que o EVM é um dos componentes centrais mais importantes do Ethereum, sendo posicionado como "motor de execução" e "ambiente de execução de contratos inteligentes". Como a blockchain pública é uma rede aberta que contém uma grande quantidade de nós, as diferenças nos parâmetros de hardware entre diferentes nós podem ser bastante grandes. Para que os contratos inteligentes possam obter os mesmos resultados em vários nós, satisfazendo o requisito de "consistência", a tecnologia de máquinas virtuais pode criar o mesmo ambiente em diferentes dispositivos.
O EVM pode executar contratos inteligentes da mesma forma em vários sistemas operacionais e dispositivos, essa compatibilidade entre plataformas garante que cada nó obtenha resultados consistentes após a execução do contrato. Isso é semelhante ao princípio da Java Virtual Machine (JVM).
Os contratos inteligentes que vemos no explorador de blocos são primeiro compilados em bytecode EVM e depois armazenados na blockchain. Ao executar o contrato, a EVM lê esse bytecode em ordem, e cada instrução tem um custo de Gas correspondente. A EVM rastreia o consumo de Gas durante a execução de cada instrução, e a quantidade consumida depende da complexidade da operação.
Como o mecanismo central de execução do Ethereum, o EVM processa transações de maneira serial, com todas as transações enfileiradas em uma única fila e executadas em uma ordem determinada. A razão pela qual não se adota uma abordagem paralela é que a blockchain precisa atender rigorosamente à consistência; um lote de transações deve ser processado na mesma ordem em todos os nós. Se o processamento de transações for paralelo, torna-se difícil prever com precisão a ordem das transações, a menos que algoritmos de agendamento complexos sejam introduzidos.
A equipe fundadora do Ethereum, em 2014-2015, devido à pressão do tempo, optou por um modo de execução serial que fosse simples e fácil de manter. No entanto, com a evolução da tecnologia blockchain e a ampliação da base de usuários, as demandas por TPS e capacidade de processamento aumentaram consideravelmente. Com a maturação da tecnologia Rollup, os gargalos de desempenho causados pela execução serial da EVM já se tornaram evidentes na rede de segunda camada do Ethereum.
O Sequencer, como um componente chave do Layer 2, assume todas as tarefas de computação na forma de um único servidor. Se a eficiência dos módulos externos que trabalham em conjunto com o Sequencer for suficientemente alta, o gargalo final dependerá da eficiência do próprio Sequencer, e nesse caso, a execução em série se tornará um grande obstáculo.
Uma equipe otimizou ao máximo a camada DA e o módulo de leitura e escrita de dados, permitindo que o Sequencer execute até cerca de 2000 transferências ERC-20 por segundo. Esse número parece muito alto, mas se as transações processadas forem muito mais complexas do que as transferências ERC-20, o valor do TPS certamente diminuirá drasticamente. Portanto, a paralelização do processamento de transações se tornará uma tendência inevitável no futuro.
A seguir, vamos explorar as limitações do EVM tradicional e as vantagens do EVM paralelo.
Os dois principais componentes da execução de transações Ethereum
No nível do módulo de código, além do EVM, outro componente central relacionado à execução de transações no go-ethereum é o stateDB, que é usado para gerenciar o estado das contas e o armazenamento de dados no Ethereum. O Ethereum utiliza uma estrutura de árvore chamada Merkle Patricia Trie como índice de banco de dados. A cada execução de transação, o EVM altera certos dados no stateDB, e essas mudanças acabam sendo refletidas na árvore de estado global.
O stateDB é responsável por manter o estado de todas as contas do Ethereum, incluindo contas EOA e contas de contrato, armazenando dados como saldo de contas, código de contratos inteligentes, entre outros. Durante o processo de execução da transação, o stateDB realizará operações de leitura e escrita nos dados das contas correspondentes. Após a conclusão da execução da transação, o stateDB precisa submeter o novo estado ao banco de dados subjacente para processamento de persistência.
Em geral, o EVM é responsável por interpretar e executar instruções de contratos inteligentes, alterando o estado na blockchain com base nos resultados do cálculo, enquanto o stateDB atua como um armazenamento de estado global, gerenciando todas as mudanças de estado das contas e contratos. Ambos colaboram para construir o ambiente de execução de transações do Ethereum.
processo específico de execução em série
As transações de Ethereum são divididas em duas categorias: transferências EOA e transações de contrato. As transferências EOA são o tipo de transação mais simples, ou seja, transferências de ETH entre contas comuns, sem envolver chamadas de contrato, com velocidade de processamento muito rápida e taxas de gás extremamente baixas.
As transações de contratos envolvem a chamada e execução de contratos inteligentes. Quando a EVM processa transações de contratos, precisa interpretar e executar uma a uma as instruções em bytecode do contrato inteligente. Quanto mais complexa for a lógica do contrato, mais instruções estarão envolvidas e mais recursos serão consumidos.
Por exemplo, o tempo de processamento de uma transferência ERC-20 é cerca de 2 vezes maior do que o de uma transferência EOA, enquanto contratos inteligentes mais complexos como a operação de negociação em um DEX ( levam mais tempo, podendo ser até dez vezes mais lentos que transferências EOA. Isso se deve ao fato de que os protocolos DeFi precisam lidar com pools de liquidez, cálculo de preços, troca de tokens e outras lógicas complexas durante as transações, exigindo um grande volume de cálculos.
No modo de execução em série, o processo de tratamento de transações entre o EVM e o stateDB é o seguinte:
No design do Ethereum, as transações dentro de um bloco são processadas sequencialmente, e cada transação tem uma instância independente que executa operações específicas. Embora cada transação utilize uma instância EVM diferente, todas as transações compartilham o mesmo banco de dados de estado, stateDB.
Durante a execução da transação, o EVM precisa interagir continuamente com o stateDB, a fim de ler os dados relevantes e escrever os dados alterados de volta no stateDB.
Do ponto de vista do código, o fluxo geral de execução de transações em colaboração entre o EVM e o stateDB é o seguinte:
A função processBlock)( chama a função Process)( para processar as transações em um bloco.
O processo ) define um loop for na função, onde as transações são executadas uma por uma.
Após a conclusão de todas as transações, a função processBlock() chama a função writeBlockWithState(), e então chama a função statedb.Commit() para submeter os resultados da alteração de estado.
Quando todas as transações em um bloco forem executadas, os dados no stateDB serão submetidos à árvore de estado global e um novo raiz de estado será gerado. A raiz de estado é um parâmetro importante em cada bloco, que registra o "resultado comprimido" do novo estado global após a execução do bloco.
O modo de execução serial do EVM apresenta um gargalo evidente: as transações devem ser executadas em ordem, e se uma transação de contrato inteligente demorar muito, as outras transações só podem esperar, não conseguindo aproveitar plenamente os recursos de hardware, como a CPU, o que limita bastante a eficiência.
Proposta de otimização de paralelismo em múltiplas threads do EVM
Fazendo uma analogia entre a execução serial e a execução paralela, a primeira é como um banco com apenas um balcão, enquanto a EVM paralela é como um banco com vários balcões. No modo paralelo, é possível abrir várias threads para processar várias transações ao mesmo tempo, podendo aumentar a eficiência em várias vezes, mas o desafio que se enfrenta é o problema de conflitos de estado.
Se várias transações declararem que desejam modificar os dados de uma determinada conta, um conflito ocorrerá ao processá-las simultaneamente. Por exemplo, se um NFT puder ser cunhado apenas uma vez, e a transação 1 e a transação 2 desejarem cunhar esse NFT, se ambos os pedidos forem atendidos, evidentemente haverá um erro. Na prática, conflitos de estado ocorrem com mais frequência, portanto, o processamento paralelo de transações deve ter medidas para lidar com conflitos de estado.
( Princípios de otimização paralela do EVM em um determinado projeto
Um determinado projeto ZKRollup otimiza a paralelização do EVM alocando uma transação para cada thread e fornecendo um banco de dados de estado temporário em cada thread, chamado de pending-stateDB. Os detalhes específicos são os seguintes:
Execução de transações em paralelo com múltiplas threads: configurar várias threads para processar diferentes transações simultaneamente, sem interferência entre as threads, pode aumentar várias vezes a velocidade de processamento das transações.
Atribuir um banco de dados de estado temporário a cada thread: cada thread recebe um banco de dados de estado temporário independente )pending-stateDB###. Quando a thread executa transações, não modifica diretamente o stateDB global, mas registra temporariamente os resultados das mudanças de estado no pending-stateDB.
Sincronização das alterações de estado: Após a execução de todas as transações dentro de um bloco, o EVM sincroniza sequencialmente os resultados das alterações de estado registrados em cada pending-stateDB para o stateDB global. Se não houver conflitos de estado durante a execução de transações diferentes, as gravações no pending-stateDB podem ser mescladas com sucesso no stateDB global.
O projeto otimizou o tratamento de operações de leitura e gravação, garantindo que as transações possam acessar corretamente os dados de estado e evitar conflitos:
Operação de leitura: quando uma transação precisa ler o estado, o EVM primeiro verifica o ReadSet do estado pendente. Se o ReadSet contiver os dados necessários, ele é lido diretamente do pending-stateDB. Se o ReadSet não contiver a chave-valor correspondente, os dados do estado histórico são lidos do stateDB global do bloco anterior.
Operações de escrita: Todas as operações de escrita (, ou seja, modificações de estado ), não são escritas diretamente no stateDB global, mas são primeiro registradas no WriteSet do estado pendente. Após a execução da transação, tenta-se fundir os resultados da alteração de estado no stateDB global através da detecção de conflitos.
A questão-chave da execução paralela é o conflito de estado, que se torna especialmente significativo quando várias transações tentam ler e gravar o mesmo estado da conta. Para isso, foi introduzido um mecanismo de detecção de conflitos:
Detecção de conflitos: durante a execução da transação, o EVM monitora o ReadSet e o WriteSet de diferentes transações. Se detectar que várias transações tentam ler e escrever o mesmo item de estado, isso é considerado uma ocorrência de conflito.
Tratamento de conflitos: Quando um conflito é detectado, a transação em conflito é marcada como necessitando de reexecução.
Após a conclusão de todas as transações, várias mudanças registradas no stateDB pendente serão combinadas no stateDB global. Se a combinação for bem-sucedida, o EVM submeterá o estado final à árvore de estados global e gerará uma nova raiz de estado.
A otimização de paralelismo com múltiplas threads apresenta um aumento significativo no desempenho, especialmente ao lidar com transações complexas de contratos inteligentes. Estudos mostram que, em cargas de trabalho de baixo conflito, o TPS em testes de referência aumentou de 3 a 5 vezes em comparação com a execução serial tradicional. Em cargas de trabalho de alto conflito, teoricamente, se todas as medidas de otimização forem aplicadas, pode-se alcançar um aumento de até 60 vezes.
Resumo
A solução de otimização de paralelismo multithread EVM mencionada acima, atribuindo um repositório de estado temporário para cada transação e executando transações em paralelo em diferentes threads, melhorou significativamente a capacidade de processamento de transações do EVM. Ao otimizar operações de leitura e escrita e introduzir um mecanismo de detecção de conflitos, as blockchains públicas EVM podem realizar paralelização em larga escala das transações, garantindo a consistência do estado, resolvendo o gargalo de desempenho trazido pelo modo de execução serial tradicional. Isso estabelece uma base importante para o desenvolvimento futuro do Rollup do Ethereum.
As direcções futuras de investigação incluem: optimizar ainda mais a eficiência de armazenamento para melhorar o desempenho, soluções de optimização para lidar com altas situações de conflito, e como utilizar GPUs para optimização, entre outros conteúdos.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
Quebra de paralelização EVM: a tecnologia chave para melhorar o desempenho do Layer2 em 60 vezes.
Otimização de paralelização EVM: A chave para superar os gargalos de desempenho
É bem conhecido que o EVM é um dos componentes centrais mais importantes do Ethereum, sendo posicionado como "motor de execução" e "ambiente de execução de contratos inteligentes". Como a blockchain pública é uma rede aberta que contém uma grande quantidade de nós, as diferenças nos parâmetros de hardware entre diferentes nós podem ser bastante grandes. Para que os contratos inteligentes possam obter os mesmos resultados em vários nós, satisfazendo o requisito de "consistência", a tecnologia de máquinas virtuais pode criar o mesmo ambiente em diferentes dispositivos.
O EVM pode executar contratos inteligentes da mesma forma em vários sistemas operacionais e dispositivos, essa compatibilidade entre plataformas garante que cada nó obtenha resultados consistentes após a execução do contrato. Isso é semelhante ao princípio da Java Virtual Machine (JVM).
Os contratos inteligentes que vemos no explorador de blocos são primeiro compilados em bytecode EVM e depois armazenados na blockchain. Ao executar o contrato, a EVM lê esse bytecode em ordem, e cada instrução tem um custo de Gas correspondente. A EVM rastreia o consumo de Gas durante a execução de cada instrução, e a quantidade consumida depende da complexidade da operação.
Como o mecanismo central de execução do Ethereum, o EVM processa transações de maneira serial, com todas as transações enfileiradas em uma única fila e executadas em uma ordem determinada. A razão pela qual não se adota uma abordagem paralela é que a blockchain precisa atender rigorosamente à consistência; um lote de transações deve ser processado na mesma ordem em todos os nós. Se o processamento de transações for paralelo, torna-se difícil prever com precisão a ordem das transações, a menos que algoritmos de agendamento complexos sejam introduzidos.
A equipe fundadora do Ethereum, em 2014-2015, devido à pressão do tempo, optou por um modo de execução serial que fosse simples e fácil de manter. No entanto, com a evolução da tecnologia blockchain e a ampliação da base de usuários, as demandas por TPS e capacidade de processamento aumentaram consideravelmente. Com a maturação da tecnologia Rollup, os gargalos de desempenho causados pela execução serial da EVM já se tornaram evidentes na rede de segunda camada do Ethereum.
O Sequencer, como um componente chave do Layer 2, assume todas as tarefas de computação na forma de um único servidor. Se a eficiência dos módulos externos que trabalham em conjunto com o Sequencer for suficientemente alta, o gargalo final dependerá da eficiência do próprio Sequencer, e nesse caso, a execução em série se tornará um grande obstáculo.
Uma equipe otimizou ao máximo a camada DA e o módulo de leitura e escrita de dados, permitindo que o Sequencer execute até cerca de 2000 transferências ERC-20 por segundo. Esse número parece muito alto, mas se as transações processadas forem muito mais complexas do que as transferências ERC-20, o valor do TPS certamente diminuirá drasticamente. Portanto, a paralelização do processamento de transações se tornará uma tendência inevitável no futuro.
A seguir, vamos explorar as limitações do EVM tradicional e as vantagens do EVM paralelo.
Os dois principais componentes da execução de transações Ethereum
No nível do módulo de código, além do EVM, outro componente central relacionado à execução de transações no go-ethereum é o stateDB, que é usado para gerenciar o estado das contas e o armazenamento de dados no Ethereum. O Ethereum utiliza uma estrutura de árvore chamada Merkle Patricia Trie como índice de banco de dados. A cada execução de transação, o EVM altera certos dados no stateDB, e essas mudanças acabam sendo refletidas na árvore de estado global.
O stateDB é responsável por manter o estado de todas as contas do Ethereum, incluindo contas EOA e contas de contrato, armazenando dados como saldo de contas, código de contratos inteligentes, entre outros. Durante o processo de execução da transação, o stateDB realizará operações de leitura e escrita nos dados das contas correspondentes. Após a conclusão da execução da transação, o stateDB precisa submeter o novo estado ao banco de dados subjacente para processamento de persistência.
Em geral, o EVM é responsável por interpretar e executar instruções de contratos inteligentes, alterando o estado na blockchain com base nos resultados do cálculo, enquanto o stateDB atua como um armazenamento de estado global, gerenciando todas as mudanças de estado das contas e contratos. Ambos colaboram para construir o ambiente de execução de transações do Ethereum.
processo específico de execução em série
As transações de Ethereum são divididas em duas categorias: transferências EOA e transações de contrato. As transferências EOA são o tipo de transação mais simples, ou seja, transferências de ETH entre contas comuns, sem envolver chamadas de contrato, com velocidade de processamento muito rápida e taxas de gás extremamente baixas.
As transações de contratos envolvem a chamada e execução de contratos inteligentes. Quando a EVM processa transações de contratos, precisa interpretar e executar uma a uma as instruções em bytecode do contrato inteligente. Quanto mais complexa for a lógica do contrato, mais instruções estarão envolvidas e mais recursos serão consumidos.
Por exemplo, o tempo de processamento de uma transferência ERC-20 é cerca de 2 vezes maior do que o de uma transferência EOA, enquanto contratos inteligentes mais complexos como a operação de negociação em um DEX ( levam mais tempo, podendo ser até dez vezes mais lentos que transferências EOA. Isso se deve ao fato de que os protocolos DeFi precisam lidar com pools de liquidez, cálculo de preços, troca de tokens e outras lógicas complexas durante as transações, exigindo um grande volume de cálculos.
No modo de execução em série, o processo de tratamento de transações entre o EVM e o stateDB é o seguinte:
No design do Ethereum, as transações dentro de um bloco são processadas sequencialmente, e cada transação tem uma instância independente que executa operações específicas. Embora cada transação utilize uma instância EVM diferente, todas as transações compartilham o mesmo banco de dados de estado, stateDB.
Durante a execução da transação, o EVM precisa interagir continuamente com o stateDB, a fim de ler os dados relevantes e escrever os dados alterados de volta no stateDB.
Do ponto de vista do código, o fluxo geral de execução de transações em colaboração entre o EVM e o stateDB é o seguinte:
A função processBlock)( chama a função Process)( para processar as transações em um bloco.
O processo ) define um loop for na função, onde as transações são executadas uma por uma.
Após a conclusão de todas as transações, a função processBlock() chama a função writeBlockWithState(), e então chama a função statedb.Commit() para submeter os resultados da alteração de estado.
Quando todas as transações em um bloco forem executadas, os dados no stateDB serão submetidos à árvore de estado global e um novo raiz de estado será gerado. A raiz de estado é um parâmetro importante em cada bloco, que registra o "resultado comprimido" do novo estado global após a execução do bloco.
O modo de execução serial do EVM apresenta um gargalo evidente: as transações devem ser executadas em ordem, e se uma transação de contrato inteligente demorar muito, as outras transações só podem esperar, não conseguindo aproveitar plenamente os recursos de hardware, como a CPU, o que limita bastante a eficiência.
Proposta de otimização de paralelismo em múltiplas threads do EVM
Fazendo uma analogia entre a execução serial e a execução paralela, a primeira é como um banco com apenas um balcão, enquanto a EVM paralela é como um banco com vários balcões. No modo paralelo, é possível abrir várias threads para processar várias transações ao mesmo tempo, podendo aumentar a eficiência em várias vezes, mas o desafio que se enfrenta é o problema de conflitos de estado.
Se várias transações declararem que desejam modificar os dados de uma determinada conta, um conflito ocorrerá ao processá-las simultaneamente. Por exemplo, se um NFT puder ser cunhado apenas uma vez, e a transação 1 e a transação 2 desejarem cunhar esse NFT, se ambos os pedidos forem atendidos, evidentemente haverá um erro. Na prática, conflitos de estado ocorrem com mais frequência, portanto, o processamento paralelo de transações deve ter medidas para lidar com conflitos de estado.
( Princípios de otimização paralela do EVM em um determinado projeto
Um determinado projeto ZKRollup otimiza a paralelização do EVM alocando uma transação para cada thread e fornecendo um banco de dados de estado temporário em cada thread, chamado de pending-stateDB. Os detalhes específicos são os seguintes:
Execução de transações em paralelo com múltiplas threads: configurar várias threads para processar diferentes transações simultaneamente, sem interferência entre as threads, pode aumentar várias vezes a velocidade de processamento das transações.
Atribuir um banco de dados de estado temporário a cada thread: cada thread recebe um banco de dados de estado temporário independente )pending-stateDB###. Quando a thread executa transações, não modifica diretamente o stateDB global, mas registra temporariamente os resultados das mudanças de estado no pending-stateDB.
Sincronização das alterações de estado: Após a execução de todas as transações dentro de um bloco, o EVM sincroniza sequencialmente os resultados das alterações de estado registrados em cada pending-stateDB para o stateDB global. Se não houver conflitos de estado durante a execução de transações diferentes, as gravações no pending-stateDB podem ser mescladas com sucesso no stateDB global.
O projeto otimizou o tratamento de operações de leitura e gravação, garantindo que as transações possam acessar corretamente os dados de estado e evitar conflitos:
Operação de leitura: quando uma transação precisa ler o estado, o EVM primeiro verifica o ReadSet do estado pendente. Se o ReadSet contiver os dados necessários, ele é lido diretamente do pending-stateDB. Se o ReadSet não contiver a chave-valor correspondente, os dados do estado histórico são lidos do stateDB global do bloco anterior.
Operações de escrita: Todas as operações de escrita (, ou seja, modificações de estado ), não são escritas diretamente no stateDB global, mas são primeiro registradas no WriteSet do estado pendente. Após a execução da transação, tenta-se fundir os resultados da alteração de estado no stateDB global através da detecção de conflitos.
A questão-chave da execução paralela é o conflito de estado, que se torna especialmente significativo quando várias transações tentam ler e gravar o mesmo estado da conta. Para isso, foi introduzido um mecanismo de detecção de conflitos:
Detecção de conflitos: durante a execução da transação, o EVM monitora o ReadSet e o WriteSet de diferentes transações. Se detectar que várias transações tentam ler e escrever o mesmo item de estado, isso é considerado uma ocorrência de conflito.
Tratamento de conflitos: Quando um conflito é detectado, a transação em conflito é marcada como necessitando de reexecução.
Após a conclusão de todas as transações, várias mudanças registradas no stateDB pendente serão combinadas no stateDB global. Se a combinação for bem-sucedida, o EVM submeterá o estado final à árvore de estados global e gerará uma nova raiz de estado.
A otimização de paralelismo com múltiplas threads apresenta um aumento significativo no desempenho, especialmente ao lidar com transações complexas de contratos inteligentes. Estudos mostram que, em cargas de trabalho de baixo conflito, o TPS em testes de referência aumentou de 3 a 5 vezes em comparação com a execução serial tradicional. Em cargas de trabalho de alto conflito, teoricamente, se todas as medidas de otimização forem aplicadas, pode-se alcançar um aumento de até 60 vezes.
Resumo
A solução de otimização de paralelismo multithread EVM mencionada acima, atribuindo um repositório de estado temporário para cada transação e executando transações em paralelo em diferentes threads, melhorou significativamente a capacidade de processamento de transações do EVM. Ao otimizar operações de leitura e escrita e introduzir um mecanismo de detecção de conflitos, as blockchains públicas EVM podem realizar paralelização em larga escala das transações, garantindo a consistência do estado, resolvendo o gargalo de desempenho trazido pelo modo de execução serial tradicional. Isso estabelece uma base importante para o desenvolvimento futuro do Rollup do Ethereum.
As direcções futuras de investigação incluem: optimizar ainda mais a eficiência de armazenamento para melhorar o desempenho, soluções de optimização para lidar com altas situações de conflito, e como utilizar GPUs para optimização, entre outros conteúdos.