paritytech / polkadot-stps

Polkadot Standard Transactions Per Second (sTPS) performance benchmarking

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How many transfer events fits in one parablock?

bredamatt opened this issue · comments

Bounds on POV size and relay block size (i.e. availability cores) are important factors to consider when measuring TPS, in particular for parachains. Indeed, the max data-rate of the relay chain is a function of how many availability cores exist, times the maximum POV size. Hence, given that a Transfer takes single_transfer_proof_size amount of bytes, then the total number of such Transfer events to fit on the relay chain at any given time can roughly be modelled as:

max_parachain_tps = ((max_POV_size/single_transfer_proof_size)*num_availability_cores)/parablock_inclusion_time

where parablock_time is the time it takes to include a parablock / candidate in the relay chain, which will vary based on whether sync-, or async-backing is used.

If we know how many Transfer events will fit in a particular POV, we can then start to think more clearly about how many sender binaries we should use to maximise throughput during the (s)TPS test.

This should definitely also relate to the weight associated with the Balances pallet transfers. I would like to see a way to go from weight to bytes, but don't think this is possible. So ideally, there is a way to calculate the size in bytes for each event given some Pallet. See: https://substrate.stackexchange.com/questions/518/what-does-pov-stand-for/519#519 for some more context.

After discussing with the FRAME team, it appears that the PoV bound is a bit more intricate than first expected, as there exists various PoV bounds at various points in time during the protocol execution:

  • once pre-dispatch based on weight
  • once with the proof-recorder
  • once where the two above results get compacted and compressed for the final PoV size result

However, in this case the final one is what matters in the end so it makes sense to somehow test by setting weights in the Transfer call to 0 in the Balances pallet, then monitoring the PoV size that gets sent to relay whilst gradually increasing the number of Transfer events included in a candidate.

Thinking more about this, I think some work should be started on building out a separate tool, or macro that allows us to calculate the proof size for any dispatchable in substrate. This means we would have:

  • weights to indicate execution time
  • the tool to indicate proof size of a dispatchable

An alternative way to look at this would be in terms of execution time, which we currently can estimate using weights:

max_para_tps = ((max_exec_time/single_transfer_exec_time)*num_availability_cores)/parablock_inclusion_time

Naturally, there is some interplay between exec time and proof size, since even if you could theoretically fit a large number of transactions in terms of exec time, if few transfers consumes the entire PoV, then you'd still be limited to few transactions, and vice versa (i.e. if the transfer proof size is small, but the exec time large).

Thinking more about this, I think some work should be started on building out a separate tool, or macro that allows us to calculate the proof size for any dispatchable in substrate. This means we would have:
weights to indicate execution time
the tool to indicate proof size of a dispatchable

FRAME benchmarking does this. For example a TKA transaction has ~3.6KB proof size estimated here.
The exact size will depend on the size of the DB snapshot.

Thanks for guidance on this @ggwpez ! However, I am somewhat confused after seeing this: https://github.com/paritytech/smart-bench#running-benchmarks and their output:

0005: PoV Size=0130KiB(005%) Weight RefTime=0000088ms(017%) Weight ProofSize=3277KiB(064%) Witness=0119KiB Block=0011KiB NumExtrinsics=0048
...

where it is reported different numbers for the Weight ProofSize and the PoV size for a particular contract.

I suspect FRAME benchmarking gives weight Proof Size and not PoV Size?

Closing this.

Thanks for guidance on this @ggwpez ! However, I am somewhat confused after seeing this: https://github.com/paritytech/smart-bench#running-benchmarks and their output:

I dont know what smart-bench is doing or how it works. The Proof is additionally compressed when a block is being build, so I have no clue what exactly it is outputting or how it relates to FRAME. Maybe you can find out what it outputs.