ergoplatform / sigma-rust

Rust implementation of ErgoTree interpreter and wallet-related features
Creative Commons Zero v1.0 Universal
70 stars 47 forks source link

Performance Improvement (Interpreter) #737

Closed SethDusek closed 2 months ago

SethDusek commented 5 months ago

Currently sigma-rust's performance leaves much to be desired, it is significantly slower than ergo node/sigmastate-interpreter in many cases. This is mostly because sigma-rust clones objects excessively, especially in interpreter where pretty much every interpreter op will clone it's operand, and when calling .try_extract_into::(), will again clone the value. This ends up being very painful when scripts are using Colls/nested Colls or in general have complex scripts. This transaction for example takes 700+ seconds to verify: https://ergexplorer.com/transactions#e2a90dc0f3f12d6fdc8437d72ae8cf801c25a8b1734544539eb63907629e0b4b.

The best way to tackle this would be to let the Value enum borrow from its context instead of owning every single element, something like

enum Value<'ctx> {
    Boolean(bool),
    Byte(i8),
    CBox(&'ctx ErgoBox),
    Coll(&'ctx CollKind),
    ...
}

This would allow for things like Boxes taken from CONTEXT/INPUTS/DATAINPUTS/ContextExtension to be borrowed from context instead of cloned each time. However we couldn't borrow variables declared inside the script this way because of rust's aliasing rules (can't append to Env while borrowing from Env). This could be solved by storing Rc's instead, something like:

enum Borrowed<'ctx, T> {
    Borrowed(&'ctx T),
    RefCounted(Rc<T>)
}