Before the Ethereum merge of september 2022, it was often said that ethereum ’s execution model was ‘single-threaded’ , meaning that Ethereum can only process one transaction or one smart contract at a time. Is the fact that ethereum 2.0 been released and that the merge with the beacon chain is operative , has it changed its execution model ?
No, Ethereum 2.0 has introduced the idea of a multiple-threaded execution model, where the Beacon Chain acts as the hub of activity, allowing for simultaneous transactions which are then synced with the chain. This is in stark contrast to the single-threaded operation previously seen on the older versions of Ethereum, allowing for much faster and more efficient throughput. please give more details
In Ethereum 2.0, the Beacon Chain acts as the center of activity and the main coordinating source for all the nodes in the Ethereum network. The Beacon Chain is also capable of handling sharding, which is the process of splitting data load and traffic across multiple nodes. As opposed to Ethereum’s previous single-threaded model, this multiple-threaded model allows for much faster transaction times and throughput.
Sharding is important because it prevents the network from being overwhelmed by transactions and increases its ability to scale as more transactions are done through the network.
As of this writing (July 2023), the sharding feature of Ethereum 2.0 is not yet operational, therefore, until then, Ethereum 2.0 will be limited to its current single-threaded execution model.
The EVM in details
The Ethereum virtual machine , which is the runtime environment for executing turing-complete operations like smart contracts, is a stack-based virtual machine, and unlike other architectures, it does not include any dedicated registers for storing & manipulating intermediate values during computation. Registers are small , high-speed storage units within the processor(CPU) itself. Registers are part of the processor’ s internal memory hierarchy and play a crucial role in the execution of instructions and data manipulation.
To clarify, “intermediate values” refer to the temporary results or data produced during the execution of instructions. They are not the final outputs of a computation but rather the values used to perform calculations or transformations during the process. The stack in the EVM acts as a storage mechanism for these intermediate value.
This simplified design in the Ethereum VM allows for a more uniform and portable execution environment. This choice helps maintain consistency across different implementations of the EVM and enables deterministic execution of smart contracts on the Ethereum blockchain.
In a stack-based architecture, the primary data structure used for computation is a stack . The stack follows a LIFO pattern , meaning that values are pushed on top of the stack and popped from the stack (think of it as a stack of books, where you pile up the books as you add more and , when you need a book , you remove the book from the pile ) .
When executing smart contracts on the EVM, the data is stored on the stack and manipulated using stack-based operations .
Difference between Heap and Stack
Stack :
1- Memory Allocation: memory is allocated in a LIFO manner meaning the most recently allocated variables are the first to be de-allocated.
2- Size: The size of the stack is determined at compile time and is fixed, meaning memory can not be allocated dynamically to the stack.
3- Speed : Accessing memory on the stack is faster because the CPU caches the stack and the variables are stored in contiguous blocks of memory.
4- Scope : Variables allocated on the stack are automatically de-allocated when they go out-of-scope.
5- Usage: the stack is generally used for short-lived variables created and destroyed within a function or block of code.
6- Thread-safety: each thread has it own stack, making it inherently smaller than heap size .
7- Limitations: stack overflows can occur if you exceed the stack limit size which is usually smaller that the heap size.
Local Variables : in the EVM, local variables are stored on the stack. Those variables are popped onto the stack when they are declared and popped off when no longer needed. However, due to the stack’s limited size, sometimes storage or memory is used for variables that have a longer lifecycle or which are larger in size.