paint-brush
Um estudo sobre execução paralela: tudo o que você precisa saberpor@sin7y
9,960 leituras
9,960 leituras

Um estudo sobre execução paralela: tudo o que você precisa saber

por Sin7Y20m2023/01/03
Read on Terminal Reader

Muito longo; Para ler

O FISCO-BCOS 2.0 utiliza uma estrutura gráfica no processamento de transações. Os desenvolvedores projetaram um Parallel Transaction Executor (PTE) baseado no modelo Directed Acyclic Graph (DAG) PTE pode ajudá-lo a utilizar totalmente as vantagens de um processador multi-core para que as transações no bloco possam ser executadas em paralelo.
featured image - Um estudo sobre execução paralela: tudo o que você precisa saber
Sin7Y HackerNoon profile picture
0-item

Prefácio

Esta pesquisa compara sistemas de implementação semelhantes ao Ethereum e analisa as dificuldades e possibilidades de realizar a execução paralela de transações.


Vale ressaltar que as cadeias analisadas para esta pesquisa são baseadas no esquema de design do modelo de conta, não incluindo o esquema UTXO.

Objetos de pesquisa

  1. FISCO-BCOS, um dos blockchains do consórcio que suporta execução paralela de verificação de transações dentro de blocos.


  2. Khipu public chain, implementação scala do protocolo Ethereum.


  3. Cadeia pública Aptos, Move Virtual Machine.

Dificuldades com Execução Paralela

Vamos dar uma olhada no processo tradicional de execução de transações.


O módulo de execução retira cada transação do bloco e a executa sequencialmente.


O estado do mundo mais recente será modificado durante o processo de execução e, em seguida, o estado será adicionado após a conclusão de uma transação para atingir o estado do mundo mais recente após a conclusão do bloco.


A execução do próximo bloco é estritamente dependente do estado mundial do bloco atual/anterior, portanto, esse processo de execução sequencial de thread único não é muito adequado para execução paralela.



Abaixo, estão os principais conflitos nos atuais métodos de execução paralela do Ethereum:


  1. Conflito de conta: se dois threads processam o saldo ou outros atributos de uma conta de endereço ao mesmo tempo, como podemos garantir que seja consistente com o resultado do processamento sequencial, ou seja, se o estado do mundo é uma máquina de estado finito definida?


  1. Conflito de armazenamento do mesmo endereço : onde ambos os contratos modificaram o armazenamento da mesma variável global.


  2. Conflito de chamada entre contratos: se o contrato A for implantado primeiro, o contrato B precisa aguardar até que a implantação do contrato A seja concluída para chamar o contrato A. No entanto, quando as transações são paralelas, não há essa sequência, o que leva ao conflito.

Esquemas de Execução Paralela

FISCO-BCOS

Resumo

O FISCO-BCOS 2.0 utiliza uma estrutura gráfica no processamento de transações. Os desenvolvedores projetaram um Parallel Transaction Executor (PTE) baseado no modelo Directed Acyclic Graph (DAG).


O PTE pode ajudá-lo a utilizar totalmente as vantagens de um processador multi-core para que as transações no bloco possam ser executadas em paralelo na medida do possível.


Ao mesmo tempo, fornece uma interface de programação simples e amigável para o usuário, para que o usuário não precise se preocupar com os tediosos detalhes da implementação paralela.


Os resultados experimentais do programa de teste de benchmark mostram que, em comparação com o esquema tradicional de execução de transação serial, o PTE rodando em um processador de 4 núcleos sob condições ideais pode atingir cerca de 200% ~ 300% de melhoria de desempenho, e a melhoria computacional é proporcional ao número de núcleos.


Quanto mais núcleos, melhor o desempenho.

Regime Geral

Um grafo direcionado acíclico é muitas vezes referido como gráfico acíclico direcionado (DAG).


Em um lote de transações, são identificados os recursos mutuamente exclusivos ocupados por cada transação; então um DAG dependente de transação é construído de acordo com a sequência de transações no bloco e a relação de ocupação de recursos mutuamente exclusivos.


Conforme mostrado na figura abaixo, todas as transações com um grau de entrada de 0 (sem tarefas de pré-encomenda dependentes) podem ser executadas em paralelo. A transação DAG à direita pode ser obtida por classificação topológica com base na ordem da lista de transações original à esquerda.


Arquitetura Modular


  • Os usuários iniciam transações direta ou indiretamente por meio do SDK.


  • A transação é então sincronizada entre os nós, e o nó com os mesmos direitos de empacotamento invoca o Sealer (TxPool) para pegar uma certa quantidade de transações de (txpool) e empacotá-las em um bloco. Depois disso, os blocos são enviados para a unidade Consensus em preparação para o consenso entre nós.


  • A validação da transação é realizada antes do consenso ser alcançado, e é aqui que a PTE inicia seu processo de trabalho. Como pode ser visto no diagrama de arquitetura, o PTE primeiro lê as transações no bloco em ordem e as insere no DAG Constructor, que constrói um DAG de transação contendo todas as transações de acordo com as dependências de cada transação. A PTE então ativa o pool de trabalhadores. Use vários encadeamentos para executar a transação DAG em paralelo. O Joiner suspende o thread principal até que o DAG tenha sido executado por todos os threads no pool de trabalho. Nesse ponto, o Joiner calcula a raiz do estado e a raiz do recebimento com base no registro de modificação do estado de cada transação e retorna o resultado ao chamador no nível superior.


  • Depois que o bloco é verificado, o bloco é carregado na cadeia. Depois que uma transação é executada, se o estado de cada nó for consistente, um consenso é alcançado e o bloco é gravado no armazenamento subjacente, que é permanentemente registrado no blockchain.

Processo de Construção da Transação DAG


  1. Pegue todas as transações no bloco do bloco compactado.


  2. Inicialize uma instância DAG com o número de transações como o número máximo de vértices.


  3. Leia todas as transações em ordem. Se uma transação puder ser mesclada, resolva seu campo de conflito e verifique se alguma transação anterior está em conflito com ela. Em caso afirmativo, construa uma borda de dependência entre as transações correspondentes. Se a transação não for mescável, considera-se que ela deve ser executada após todas as transações anteriores terem sido executadas, então uma borda de dependência é criada entre a transação e todas as suas predecessoras.


Nota : Uma vez criadas todas as arestas dependentes, elas não podem ser mescladas e podem ser executadas apenas sequencialmente.

Processo de Execução DAG


  1. O thread principal inicializará primeiro um pequeno grupo de threads com base no número de núcleos de hardware e, se os núcleos de hardware falharem, nenhum outro thread será criado.


  2. Quando o DAG não é concluído, o loop de encadeamento espera que a transação pronta com o grau de entrada 0 seja retirada do método waitPop do DAG. Se a transação a ser executada for realizada com sucesso, a transação será executada. Se falhar, o DAG concluiu a execução e o encadeamento é encerrado.

Problemas e Soluções

  1. Para o mesmo bloco, como garantimos que todos os nós concluíram a execução e estão no mesmo estado (os três nós raiz correspondem)?


O FISCO BCOS verifica se os triplos, ou seja, raiz de estado, raiz de transação e raiz de recebimento, são iguais entre si para determinar se os estados são acordados. Uma raiz de transação é um valor de hash calculado com base em todas as transações no bloco.


Desde que todos os nós de consenso processem os mesmos dados de bloco, a raiz da transação deve ser a mesma, o que é relativamente fácil de garantir. A chave é garantir que o estado e a raiz do recebimento gerados após a transação sejam os mesmos.


É sabido que a ordem de execução entre as instruções executadas em paralelo em diferentes núcleos de CPU não pode ser prevista com antecedência, e o mesmo vale para transações executadas em paralelo.


No esquema de execução de transação tradicional, a raiz do estado muda uma vez que cada transação é executada e a raiz do estado alterada é gravada no recibo da transação.


Depois que todas as transações são executadas, a raiz do estado final representa o estado atual do blockchain. Ao mesmo tempo, uma raiz de recebimento é calculada com base em todos os recebimentos de transações.


Pode-se ver que na implementação tradicional, a raiz do estado atua como uma variável global compartilhada.


Quando as transações são executadas em paralelo e fora de ordem, o cálculo tradicional da raiz do estado não é mais aplicável porque as transações são executadas em uma ordem diferente em máquinas diferentes e a raiz do estado final não é garantida como consistente, nem a raiz do recebimento é garantida para ser consistente.


No FISCO BCOS, as transações são executadas primeiro em paralelo e o histórico da mudança de estado de cada transação é registrado. Depois que todas as transações são executadas, uma raiz de estado é calculada com base no histórico.


Ao mesmo tempo, a raiz do estado na confirmação da transação torna-se a raiz do estado final após todas as transações terem sido executadas, garantindo assim que os nós de consenso ainda possam chegar a um acordo, mesmo que as transações sejam executadas em paralelo.


  1. Como determinar se duas transações são dependentes?


Se duas transações não forem dependentes, mas forem consideradas, isso levará a uma perda de desempenho desnecessária. Por outro lado, se ambas as transações reescreverem o estado da mesma conta, mas forem executadas em paralelo, o estado final da conta pode ser incerto.


Portanto, a determinação da dependência é uma questão importante que afeta o desempenho e pode até determinar se o blockchain pode funcionar corretamente.


Em uma transação de transferência simples, podemos julgar se duas transações são dependentes com base nos endereços do remetente e do destinatário. Tome como exemplo as três transações de transferência a seguir, A→B, C→D e D→E.


É fácil ver que a transação D→E depende do resultado da transação C→D, mas a transação A→B não tem nada a ver com as outras duas transações, portanto pode ser executada em paralelo.


Esse tipo de análise é verdadeiro em um blockchain que suporta apenas transferências simples, mas pode não ser tão preciso em um blockchain Turing-completo que executa contratos inteligentes, porque não sabemos exatamente o que está acontecendo em um contrato de transferência escrito pelo usuário. . Aqui está o que pode acontecer.


Parece que a transação de A→B não tem nada a ver com o status da conta de C e D, mas na implementação subjacente do usuário, A é uma conta especial e uma determinada taxa deve ser deduzida da conta de C para todo dinheiro transferido pela conta de A.


Neste cenário, as três transações estão todas relacionadas, portanto não podem ser executadas em paralelo. Se as transações forem divididas de acordo com o método de análise de dependência anterior, isso poderá causar erros.


Podemos deduzir automaticamente quais dependências realmente existem em uma transação com base no conteúdo do contrato do usuário? A resposta é não. Conforme mencionado anteriormente, é difícil analisar as dependências contratuais e o processo de execução na análise estática.


No FISCO BCOS, a atribuição de dependências comerciais é deixada para os desenvolvedores mais familiarizados com o conteúdo do contrato. Especificamente, os recursos mutuamente exclusivos dos quais a transação depende podem ser representados por um conjunto de strings.


O FISCO BCOS expõe a interface para o desenvolvedor, que define os recursos dos quais a transação depende na forma de strings e informa o executor da cadeia.


O executor organizará automaticamente todas as transações no bloco na transação DAG de acordo com as dependências de transação especificadas pelo desenvolvedor.


Por exemplo, em um contrato de transferência simples, o desenvolvedor simplesmente especifica que a dependência para cada transação de transferência é {endereço do remetente + endereço do destinatário}.


Além disso, se o desenvolvedor introduzir outro endereço de terceiros na lógica de transferência, a dependência precisará ser definida como {endereço do remetente + endereço do destinatário + endereço de terceiros}.


Essa abordagem é intuitiva, simples e geral e se aplica a todos os contratos inteligentes, mas também aumenta a responsabilidade sobre os ombros do desenvolvedor.


O desenvolvedor deve ter muito cuidado ao especificar as dependências da transação. Se as dependências não forem escritas corretamente, as consequências serão imprevisíveis.

Contrato Quadro Paralelo

Para que os desenvolvedores usem a estrutura de contratos paralelos, o FISCO BCOS definiu algumas especificações para a redação de contratos. As especificações são as seguintes:

Paralelo Mutuamente Exclusivo

Se duas transações podem ser executadas em paralelo depende se as duas transações são mutuamente exclusivas. A exclusão mútua refere-se à interseção do conjunto de variáveis ​​de armazenamento de duas transações.


Por exemplo, em um cenário de transferência de ativos, uma transação é uma operação de transferência entre usuários. transfer(X, Y) representa a interface de transferência do usuário X para o usuário Y, e a exclusão mútua é a seguinte.



  • Parâmetro mutuamente exclusivo: Parâmetro relacionado à operação “ler/escrever” da variável de armazenamento do contrato na interface do contrato. Pegue a interface de transferência transfer(X, Y) por exemplo. X e Y são parâmetros mutuamente exclusivos.


  • Mutex: O conteúdo mutex específico extraído de uma transação de acordo com os parâmetros mutex. Pegue a interface de transferência transfer(X, Y) por exemplo. Em uma transação de transferência usando esta interface, o parâmetro específico é transfer(A, B) e o mutex desta operação é [A, B]. Para outra transação, transfer(A, C) é chamado e o mutex para esta operação é [A, C].


Determinar se duas transações podem ser executadas em paralelo ao mesmo tempo é determinar se o mutex de duas transações se cruzam. As transações cujas interseções estão vazias podem ser executadas em paralelo.


O FFISCO-BCOS fornece duas maneiras de escrever contratos paralelos, contratos pré-compilados e contratos de solidez, apenas os últimos dos quais são descritos aqui. O mesmo vale para contratos pré-compilados.

Estrutura Paralela do Contrato de Solidez

Para escrever um contrato de solidity paralelo, além disso, simplesmente faça ParallelContract.sol a classe base para os contratos que você deseja paralelizar. O método registerParallelFunction() é chamado para registrar interfaces que podem ser paralelizadas.


O código do Contrato Paralelo é o seguinte:

 pragma solidity ^0.4.25; //Precompile the contract interface contract ParallelConfigPrecompiled { function registerParallelFunctionInternal(address, string, uint256) public returns (int); function unregisterParallelFunctionInternal(address, string) public returns (int); } //The parallel contract base class needs to be registered and the subcontract needs to be implement enable or disable interface contract ParallelContract { ParallelConfigPrecompiled precompiled = ParallelConfigPrecompiled(0x1006); function registerParallelFunction(string functionName, uint256 criticalSize) public { precompiled.registerParallelFunctionInternal(address(this), functionName, criticalSize); } function unregisterParallelFunction(string functionName) public { precompiled.unregisterParallelFunctionInternal(address(this), functionName); } function enableParallel() public; function disableParallel() public; }


O exemplo a seguir é um contrato de transferência escrito com base em um contrato-quadro paralelo:


 pragma solidity ^0.4.25; import "./ParallelContract.sol"; // Introduce ParallelContract.sol contract ParallelOk is ParallelContract // useParallelContract as a base class { // Contract implementation mapping (string => uint256) _balance; // Global mapping // The mutually exclusive variables from and to are the first two parameters at the beginning of transfer (). It can be seen that the contract requirements are still very strict, which will make users uncomfortable to write function transfer(string from, string to, uint256 num) public { _balance[from] -= num; // From is the key of the global mapping, and is a mutually exclusive parameter _balance[to] += num; //// To is the key of the global mapping, and is a mutually exclusive parameter } // The mutex variable name comes first as an argument to the beginning of set() function set(string name, uint256 num) public { _balance[name] = num; } function balanceOf(string name) public view returns (uint256) { return _balance[name]; } // Register contract interfaces that can be parallel function enableParallel() public { // The function definition string (note that there are no Spaces after ",") and the first few arguments are mutex arguments (mutex arguments must be first when designing a function) //The number 2 indicates that the first two are mutex parameters, and the system decodes the mutex according to the function signature and abi registerParallelFunction("transfer(string,string,uint256)", 2); // critical: string string // registerParallelFunction("set(string,uint256)", 1); // critical: string } // Deregister the parallel contract interface function disableParallel() public { unregisterParallelFunction("transfer(string,string,uint256)"); unregisterParallelFunction("set(string,uint256)"); } }


Determine se a interface pode ser paralela

Uma interface de contrato paralela deve satisfazer:

  • Nenhum contrato externo é chamado.
  • Nenhuma outra interface de função é chamada.

Determinar o parâmetro Mutex

Antes de programar uma interface, determine os parâmetros mutuamente exclusivos da interface. Os parâmetros mutuamente exclusivos da interface são mutuamente exclusivos para variáveis ​​globais. As regras para determinar parâmetros mutuamente exclusivos são as seguintes:


  • Se o mapeamento global for acessado pela interface, a chave do mapeamento é o parâmetro mutuamente exclusivo.


  • Se o array global for acessado pela interface, o subscrito do array é o parâmetro mutuamente exclusivo.


  • Se a interface acessar variáveis ​​globais de um tipo simples. Todas as variáveis ​​globais de um tipo simples compartilham um parâmetro mutex e usam nomes de variáveis ​​diferentes como objetos mutex.


Por exemplo, existem múltiplas variáveis ​​globais de tipos simples no contrato e diferentes interfaces acessam diferentes variáveis ​​globais.


Se você deseja paralelizar diferentes interfaces, precisa definir um parâmetro mutex no parâmetro de interface com a variável global modificada para indicar qual variável global é usada durante a chamada.


Quando chamado, o parâmetro mutex recebe ativamente o “nome da variável” modificado da variável global para identificar o mutex da transação.


Tal como: Se setA(int x) modifica globalA como um parâmetro global, setA precisa ser definido como set(string aflag, int x) . Quando chamado, setA("globalA", 10) é passado. Use o nome da variável “globalA” para indicar que o mutex para esta transação é globalA .

Determinar o tipo e a ordem do parâmetro

Depois de determinar os parâmetros mutuamente exclusivos, determine o tipo e a ordem do parâmetro de acordo com as regras. As regras são as seguintes:


  • Os parâmetros de interface são limitados a string, address, uint256 e int256 (mais tipos serão suportados no futuro).


  • Todos os parâmetros mutuamente exclusivos devem aparecer nos parâmetros da interface.


  • Todos os parâmetros mutuamente exclusivos estão no primeiro lugar dos parâmetros de interface.


Percebe-se que a transação paralela do FISCO-BCOS depende muito das especificações dos contratos redigidos pelos usuários.


Se as especificações dos contratos escritos pelos usuários não forem padronizadas, o sistema realiza execuções paralelas às pressas, o que pode causar a inconsistência raiz dos livros contábeis.

Khipu

Resumo

Khipu acredita que não é realista para os usuários identificar e rotular o intervalo de endereços que criarão conflitos estáticos no momento da redação do contrato sem erros. Isso contrasta com a visão do FISCO-BCOS.


Se, onde e sob quais condições a condição de corrida aparecerá, pode ser julgado apenas quando a aquisição de certeza envolve o estado atual.


Esse tipo de julgamento, com as linguagens de programação de contrato atuais, torna quase impossível para a análise estática do código obter resultados completamente corretos e infalíveis.


Khipu fez uma tentativa mais abrangente de resolver esse problema e concluiu um processo para implementá-lo.

Regime Geral

No Khipu, cada transação no mesmo bloco começa no estado mundial do bloco anterior e, em seguida, é executada em paralelo, registrando as três condições de corrida acima encontradas ao longo de todos os caminhos de experiência ideais durante a execução.


Após a fase de execução paralela vem a fase de mesclagem, quando os estados do mundo paralelo são mesclados um a um. Ao mesclar uma transação, primeiro julgue se você tem um conflito com as condições de corrida mescladas anteriormente a partir das condições estáticas registradas.


Se não, mescle diretamente. Se assim for, a transação é executada novamente começando com o estado anterior do mundo que foi mesclado.


O último estado do mundo mesclado é verificado no hash do bloco. Esta é a última linha de defesa. Se a verificação estiver incorreta, a mesclagem anterior é abandonada e o bloco é executado novamente.

Índice de Paralelismo

Aqui, Khipu introduz um índice de paralelismo, que se refere à proporção de transações em um bloco que podem combinar resultados diretamente sem precisar ser executados novamente.


A observação de Khipu do replay do Ethereum ao longo de vários dias, desde o bloco de criação até o bloco mais recente, mostra que essa proporção (paralelismo) pode atingir 80% em média.


Em geral, se as tarefas de computação puderem ser totalmente paralelizadas, a escalabilidade de uma única cadeia é infinita. Porque você sempre pode adicionar mais núcleos de CPU a um nó. Se não for esse o caso, a taxa teórica máxima é limitada pelo teorema de Andal:


O limite para o qual você pode acelerar o sistema depende do recíproco das partes que não podem ser paralelizadas. Portanto, se você pode paralelizar 99%, pode acelerar até 100 vezes. Mas se você conseguir atingir apenas 95% de paralelização, poderá obter apenas 20 vezes mais rápido.


De todas as transações no Ethereum, cerca de 80% podem ser paralelizadas e 20% não, então o limite de velocidade de Khipu é de cerca de 5 vezes.

Marcadores de conflito

Ao entender as instruções no código evm, descobriu-se que um número limitado de instruções criou processos de leitura e gravação para o armazenamento, portanto, foi possível gravar esses processos de leitura e gravação para formar uma coleção de leitura e gravação, mas o código estático análise não pôde garantir que esses processos fossem registrados.


Portanto, é necessário pré-executar cada transação uma vez ao processar cada bloco. O processo de pré-execução informa se as transações são lidas e gravadas na mesma conta ou armazenamento e cria um readSet e um writeSet para cada transação.


Se houver 100 transações no blockchain, essas 100 transações podem ser executadas em paralelo por meio do pool de threads. Cada contrato tem o mesmo estado inicial do mundo e 100 readSets e writeSets serão criados durante a execução, bem como 100 novos estados cada.


Terminada a pré-execução, inicia-se a próxima etapa do processamento. Idealmente, se as 100 entradas readSet e writeSet não forem conflitantes, elas podem ser mescladas diretamente para produzir o estado final do mundo de todas as transações no bloco. No entanto, a transação muitas vezes não é tão ideal.


A forma correta de lidar com isso é comparar o readSet e o writeSet após a execução da primeira transação com o readSet e o writeSet após a execução do segundo contrato, e ver se eles leram e escreveram na mesma conta ou armazenamento.


Se assim for, isso significa que os dois acordos estão em conflito. Em seguida, a segunda transação começará após a conclusão da primeira transação e será executada novamente.


Da mesma forma, à medida que a máquina de estado de mesclagem continua, o conjunto de conflitos continuará a se acumular e, desde que as transações subsequentes entrem em conflito com as transações anteriores, elas serão executadas sequencialmente até que todas as transações tenham sido executadas.


Através da reprodução de transações na rede principal do Ethereum, verifica-se que onde há muitos conflitos, a maioria dos casos são trocas no mesmo bloco com transações inter-relacionadas, o que também é consistente com esse processo.


Processo Geral


Processo Paralelo Específico

Aptos

Resumo

Aptos é construído na linguagem Move de Diem e MoveVM para criar uma cadeia de alto rendimento que permite a execução paralela. A abordagem da Aptos é detectar associações enquanto é transparente para usuários/desenvolvedores.


Ou seja, as transações não precisam declarar explicitamente qual parte do estado (localização da memória) elas usam.

Regime Geral

A Aptos usa uma versão modificada da memória de transação de software chamada Block-STM e implementa seu mecanismo de execução paralela baseado no Block-STM .


O Block-STM usa MVCC (Multi-version Concurrency Control) para evitar conflitos de gravação e gravação. Todas as gravações no mesmo local são armazenadas com suas versões, que contêm seu TX-ID e o número de vezes que a gravação tx foi reexecutada.


Quando uma transação (tx) lê um valor para um local de memória, ela obtém o valor gravado do MVCC para esse local que ocorreu antes de tx junto com a versão associada para determinar se há um conflito de leitura/gravação.


No Block-STM, as transações são pré-classificadas em blocos e divididas entre os threads do processador para execução paralela durante a execução. Na execução paralela, assume-se que não há dependências para executar a transação.


Os locais de memória modificados pela transação são registrados. Após a execução, verifique todos os resultados da transação. Durante a validação, se for encontrada uma transação para acessar um local de memória modificado por uma transação anterior, a transação é inválida.


Atualize o resultado da negociação e execute-a novamente. Este processo é repetido até que todas as transações do bloco tenham sido executadas. O Block-STM acelera a execução quando vários núcleos de processador são usados. A aceleração depende de quão interdependentes são as transações.


Pode-se observar que o esquema utilizado pelo Aptos é mais ou menos semelhante ao Khipu citado acima, mas existem algumas diferenças na implementação, que detalhamos a seguir:


  • Khipu usa execução paralela e verificação sequencial para transações intra-bloco. No entanto, o Aptos implementa execução e verificação paralelas para as transações dentro do bloco. Esses dois esquemas têm vantagens e desvantagens. Khipu é fácil de implementar e a eficiência é um pouco menor. Por meio do Block-STM, o Aptos usa sincronização e operação de sinal em muitos threads, o que é altamente eficiente, mas é difícil de implementar o código.


  • Como o Move oferece suporte nativo ao endereçamento global de recursos, o Aptos reordenará as transações, mesmo entre blocos, quando for propício à execução paralela. A Aptos afirma que esse esquema pode não apenas melhorar a eficiência do paralelo, mas também resolver o problema do MEV. No entanto, se isso afetará a experiência do usuário ainda precisa ser considerado.


  • O Aptos armazena o conjunto de gravação resultante na memória durante a execução para velocidade máxima de execução e, em seguida, o usa como um cache para o próximo bloco a ser executado. Qualquer gravação repetida só precisa ser gravada uma vez na memória estável.

Teste de referência

A Aptos fez um benchmark correspondente após a integração do bloco-STM e comparou entre a execução sequencial e a execução paralela de um bloco de 10k transações. O resultado da comparação é mostrado a seguir:


Pode ser visto na figura acima que Block STM atinge 16 vezes mais rápido que a execução sequencial com 32 threads em paralelo e mais de 8 vezes mais rápido sob alta contenção.

Conclusão

Com base na comparação e análise acima, pode-se concluir que alguns esquemas exigem que os usuários gravem o armazenamento de acordo com as regras estabelecidas ao escrever contratos para que as dependências possam ser encontradas por análises estáticas e dinâmicas.


Solana e Sui usam esquemas semelhantes, mas a percepção do usuário é diferente. Este esquema é essencialmente uma mudança no modelo de armazenamento para obter melhores resultados de análise.


Khipu e Aptos são esquemas independentes de usuário. A sobrecarga da execução paralela não recai sobre os desenvolvedores e eles não precisam pensar nisso ao redigir seus contratos.


A máquina virtual analisa dinamicamente as relações de dependência antes da execução, implementando assim a execução paralela sem relações de dependência.


Isso é difícil de implementar e o grau de paralelismo depende até certo ponto da divisão de contas da transação. Quando há muitos conflitos de transação, o desempenho se deteriora significativamente devido à reexecução constante.


A Aptos mencionou que fará otimizações futuras de contratos de autoria do usuário para analisar melhor as dependências e, assim, obter uma execução mais rápida.


A simples modificação de um esquema baseado em série para um esquema paralelo pode trazer uma melhoria de 3 a 16 vezes na taxa de transferência transacional em um ambiente de cadeia pública e, se isso puder ser combinado com grandes blocos e grandes limites de gás, a taxa de transferência L2 será ainda mais otimizada, potencialmente cerca de 100 vezes.


Do ponto de vista da engenharia, em relação à implementação e eficiência, o OlaVM provavelmente adotará o esquema Khipu mais uma solução de modelo de armazenamento personalizado, que pode melhorar o desempenho, evitando a complexidade causada pela introdução do Block-STM e facilitando uma melhor otimização de engenharia.


Referências

  1. FISCO-BCOS Github, FISCO-BCOS
  2. Khipu GitHub, GitHub - khipu-io/khipu: Uma plataforma blockchain empresarial baseada em Ethereum
  3. Aptos GitHub, GitHub - aptos-labs/aptos-core: Aptos é um blockchain de camada 1 construído para suportar o uso generalizado de blockchain por meio de melhor tecnologia e experiência do usuário.

Sobre nós

Fundada em 2021 e desenvolvida por desenvolvedores de blockchain de alto nível, a Sin7y é uma incubadora de projetos e uma equipe de pesquisa de tecnologia blockchain que explora as tecnologias mais importantes e de ponta, incluindo EVM, Layer2, cadeia cruzada, computação de privacidade, soluções de pagamento autônomo, etc. .


Atualmente, estamos trabalhando em um ZKVM compatível com EVM, rápido e escalável chamado OlaVM. Se você estiver interessado em falar conosco, sinta-se à vontade para se juntar ao nosso grupo TG ou envie um e-mail para [email protected] .