gnolang / gno

Gno: An interpreted, stack-based Go virtual machine to build succinct and composable apps + Gno.land: a blockchain for timeless code and fair open-source
https://gno.land/
Other
842 stars 343 forks source link

Gnoland is 45% faster using GOMAXPROCS=1 on multithreaded computers. #748

Open ajnavarro opened 1 year ago

ajnavarro commented 1 year ago

gnoland is 45% faster using GOMAXPROCS=1 on multithreaded computers

Description

Setting GOMAXPROCS to 1 makes gnolang 45% faster on multithreaded computers. I used supernova for performance testing:

Leaving with GOMAXPROCS as the default value: ``` ❯ ./build/supernova -sub-accounts 10 -transactions 200 -url http://localhost:26657 -mnemonic "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" -output result.json -mode PACKAGE_DEPLOYMENT 🧮 Initializing Accounts 🧮 Generating sub-accounts... accounts initialized 100% |███████████████████████████████████████████████████████████████████████| (11/11, 11 it/s) ✅ Successfully generated 11 accounts 💸 Starting Fund Distribution 💸 Calculated sub-account cost as 200000200 ugnot Funding 10 accounts... funding short accounts 100% |██████████████████████████████████████████████████████████████████████| (10/10, 1 it/s) ✅ Successfully funded 10 accounts 🔨 Constructing Transactions 🔨 constructing txs 100% |████████████████████████████████████████████████████████████████████████| (200/200, 11 it/s) ✅ Successfully constructed 200 transactions 📦 Batching Transactions 📦 Latest block number: 351 Preparing transactions... txs prepared 100% |██████████████████████████████████████████████████████████████████████████| (200/200, 91988 it/s) Generating batches... batches generated 100% |████████████████████████████████████████████████████████████████████████| (10/10, 6666 it/s) Sending batches... batches sent 100% |███████████████████████████████████████████████████████████████████████████████| (10/10, 62 it/s) ✅ Successfully sent 10 batches Parsing batch results... results parsed 100% |██████████████████████████████████████████████████████████████████████| (200/200, 2154035 it/s) ✅ Successfully parsed 10 batch results ✅ Successfully sent 200 txs in 10 batches 📊 Collecting Results 📊 txs collected 100% |████████████████████████████████████████████████████████████████████████████| (200/200, 49 it/s) TPS: 66 Block # Gas Used Gas Limit Transactions Utilization Block #352 830065 10000000 5 8.30% Block #353 9986080 10000000 60 99.86% Block #354 9999880 10000000 60 100.00% Block #355 10015980 10000000 60 100.16% Block #356 2503995 10000000 15 25.04% 💾 Saving Results 💾 ✅ Successfully saved results to result.json ```
Setting GOMAXPROCS to 1: ``` ❯ ./build/supernova -sub-accounts 10 -transactions 200 -url http://localhost:26657 -mnemonic "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" -output result.json -mode PACKAGE_DEPLOYMENT 🧮 Initializing Accounts 🧮 Generating sub-accounts... accounts initialized 100% |███████████████████████████████████████████████████████████████████████| (11/11, 11 it/s) ✅ Successfully generated 11 accounts 💸 Starting Fund Distribution 💸 Calculated sub-account cost as 200000200 ugnot Funding 10 accounts... funding short accounts 100% |██████████████████████████████████████████████████████████████████████| (10/10, 1 it/s) ✅ Successfully funded 10 accounts 🔨 Constructing Transactions 🔨 constructing txs 100% |████████████████████████████████████████████████████████████████████████| (200/200, 11 it/s) ✅ Successfully constructed 200 transactions 📦 Batching Transactions 📦 Latest block number: 368 Preparing transactions... txs prepared 100% |█████████████████████████████████████████████████████████████████████████| (200/200, 106393 it/s) Generating batches... batches generated 100% |████████████████████████████████████████████████████████████████████████| (10/10, 8011 it/s) Sending batches... batches sent 100% |███████████████████████████████████████████████████████████████████████████████| (10/10, 83 it/s) ✅ Successfully sent 10 batches Parsing batch results... results parsed 100% |██████████████████████████████████████████████████████████████████████| (200/200, 1762130 it/s) ✅ Successfully parsed 10 batch results ✅ Successfully sent 200 txs in 10 batches 📊 Collecting Results 📊 txs collected 100% |████████████████████████████████████████████████████████████████████████████| (200/200, 50 it/s) TPS: 97 Block # Gas Used Gas Limit Transactions Utilization Block #369 3324860 10000000 20 33.25% Block #370 9988380 10000000 60 99.88% Block #371 10006780 10000000 60 100.07% Block #372 10015980 10000000 60 100.16% 💾 Saving Results 💾 ✅ Successfully saved results to result.json ```

66 vs 97 TPS.

Your environment

Steps to reproduce

When executing the binary or directly running the Go code using GOMAXPROCS=1 GOMAXPROCS=1 go run ./cmd/gnoland/ makes code 45% faster on multithreaded nodes.

Actual behavior

Forcing the application to use only one thread makes it 45% faster.

Proposed solution

We should decide if we can improve performance by refactoring the code to use multiple threads better or, if that is not possible due to the nature of the application, focus on one-thread performance improvements.

moul commented 1 year ago

Related with #689 cc @peter7891

jaekwon commented 1 year ago

That is interesting!

Given that a single Machine instance is more like a Gnoroutine instance (it really is running a single gno-routine), I guess that is somewhat expected. i don't think we should try to "advanced-optimize" gno-routines into parallel go-routines or anything.

But we definitely want to support multiple gno-routines in the future, so ultimately our application will be multi-routined. So while we optimize Machine for a single go-routine, we shouldn't require ALL things to be single-routine optimized. For example, we might want a single common Store (or more like a component of) shared across all gno-routines, and that one might best be optimized for multiple go-routines; just spitballing here, I imagine in the long run we might want a pool of go-routines to be fetching items from the persistent Store to serve parallel gno-routines (even as we ensure determinism/isolation somehow).