Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(/blocks): cache extrinsic base weight constants to improve performance #478

Merged
merged 58 commits into from
Mar 29, 2021

Conversation

TarikGul
Copy link
Member

@TarikGul TarikGul commented Mar 17, 2021

This PR aims to fix a regression that happened when v2.1.2 was released. ie: commit.

  • Dynamically generate hardcoded extrinsicBaseWeight, and blockWeight values depending on their grouped runtime.
    • Polkadot
    • Kusama
  • Integrate getBlockWeights into BlockService with passing tests before passing in a cache config.
  • Create Caching system, saves on expandMetadata calls for unknown runtimes.
    • Change Cache object to only hold base weight to save on memory.
  • Add cache to the following services
    • getExtrinsicByTimepoint
    • getLatestBlock
    • getBlockById
  • Add more test cases to make sure extrinsicBaseWeights is reacting properly.

Update on benchmarks: After integrating getBlockWeights I made sure to do some benchmarking. I chose to target block 1907499 which has a staking bondExtra tx (Note I am querying a single block here). I ran a 30s Benchmark with 4 threads and 30 concurrent connections. (This was also done on my local Macbook pro which is extremely fast)

Before this PR:                     After:
--------------------- |           |----------------------
Avg Latency    : 1.13s            | Avg Latency   : 92.11ms
Completed Req  : 312              | Completed Req : 7392

To wrap this PR I ran a new set of benchmarks from our standard collection of 39 blocks that are used in Sidecar-Bench. I also ran it inside of our GCP instance, to recreate a standard environment. This benchmark is 2 minute's with 4 threads and 12 concurrent connections (Which is our standard test for Sidecar in GCP).

v4.0.1:                           This PR:
--------------------- |           |----------------------
Avg Latency    : 9.72s            | Avg Latency   : 5.28s
Completed Req  : 140              | Completed Req : 268

@TarikGul TarikGul added A3 - In Progress PR in progress, not ready for review I7 - Optimization 🚴 Make Sidecar drive faster labels Mar 17, 2021
@TarikGul
Copy link
Member Author

Benchmarks for the final additions.

/blocks

v4.0.1:                           The latest commits:
--------------------- |           |----------------------
Avg Latency    : 9.72s            | Avg Latency   : 4.48s
Completed Req  : 140              | Completed Req : 329

src/services/blocks/BlocksService.ts Outdated Show resolved Hide resolved
src/services/blocks/BlocksService.ts Outdated Show resolved Hide resolved
const len = block.extrinsics[idx].encodedLength;
const weight = weightInfo.weight;

const partialFee = calcFee.calc_fee(
BigInt(weight.toString()),
len,
extrinsicBaseWeight.toBigInt()
calcFeeExBaseWeight
);

extrinsics[idx].info = api.createType('RuntimeDispatchInfo', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TarikGul ^^^ didn't pan out? Or am I wrong?

src/types/chains-config/ControllerConfig.ts Outdated Show resolved Hide resolved
src/services/blocks/BlocksService.ts Show resolved Hide resolved
src/test-helpers/metadata/metadata.ts Outdated Show resolved Hide resolved
src/test-helpers/registries/polkadotRegistry.ts Outdated Show resolved Hide resolved
@@ -0,0 +1 @@
export type Option<T> = T | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there is no such type in Typescript itself?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea it doesn't exist out of the box.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should make a PR for Option to TypeScript ;) Native support for this would be very nice.

Copy link
Contributor

@emostov emostov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LMK when its ready for a thorough review - just mostly focused on responding to open comments for this one

src/test-helpers/metadata/polkadotV29Metadata.ts Outdated Show resolved Hide resolved
src/chains-config/metadata-consts/index.ts Outdated Show resolved Hide resolved
@@ -0,0 +1 @@
export type Option<T> = T | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should make a PR for Option to TypeScript ;) Native support for this would be very nice.

TarikGul and others added 2 commits March 29, 2021 14:03
Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
@emostov emostov self-requested a review March 29, 2021 18:47
extrinsicBaseWeightExists === undefined ||
!perByte ||
!extrinsicBaseWeightExists ||
(this.minCalcFeeRuntime && specVersion < this.minCalcFeeRuntime) ||
typeof api.query.transactionPayment?.nextFeeMultiplier?.at !== 'function'
Copy link
Contributor

@emostov emostov Mar 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try and query this on line 491 and with the ? it should just be undefined if it does not exist, so we can should just be able to check multiplier

const metadata = await api.rpc.state.getMetadata(blockHash);
const {
consts: { system },
} = expandMetadata(api.registry, metadata);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep an eye on what registry we use here in the future. There is a chance it may be better to pull the registry off block we get from the rpc response since that should be guranteed to have the exact types for the runtime. For now I think this is fine.

@emostov emostov self-requested a review March 29, 2021 19:18
Copy link
Contributor

@emostov emostov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good to me.

I tried making suggestions via the github vscode extension but botched it somewhere along the way and ended up just making a commit: 20feb8e

Mostly just updates to comments, and variable names. But I did take out that giant try catch when we loop through extrinsics. I honestly think if that is catching we are not doing the correct checks prior so my proposal is to remove it and if it becomes a production issue we can address it

@emostov emostov requested a review from dvdplm March 29, 2021 19:24
@emostov emostov changed the title fix: update reading decorated metadata to increase performance fix(/blocks): cache extrinsic base weight constants in order to improve performance Mar 29, 2021
@emostov emostov changed the title fix(/blocks): cache extrinsic base weight constants in order to improve performance fix(/blocks): cache extrinsic base weight constants to improve performance Mar 29, 2021
@@ -508,7 +503,7 @@ export class BlocksService extends AbstractService {
!perByte ||
!extrinsicBaseWeightExists ||
(this.minCalcFeeRuntime && specVersion < this.minCalcFeeRuntime) ||
typeof api.query.transactionPayment?.nextFeeMultiplier?.at !== 'function'
!multiplier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines +9 to +10
import { polkadotMetadataRpcV16 } from './polkadotV16Metadata';
import { polkadotMetadataRpcV29 } from './polkadotV29Metadata';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -1 +1,2 @@
export type Option<T> = T | null;
// Not to be confused with the polkadot-js `Codec` extending `Option` type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good pt!

@@ -1 +1,2 @@
export type Option<T> = T | null;
// Not to be confused with the polkadot-js `Codec` extending `Option` type.
export type IOption<T> = T | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the TS convention for when to use the I prefix?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thinks its more just a me convention that I have implicitly picked up from reading other TS code - I is really for interface, but I use it both for interface or types to avoid name collisions with classes / functions etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in typescript (this is quite the debate apparently), "I" should refer to interface's only, and when its not there it will refer to an impl. Even though this example doesn't fit those parameters the use of 'I' here is to make sure there is a distinguishing difference as stated in the comment.

Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, good job.

@emostov emostov merged commit 610db42 into master Mar 29, 2021
@emostov emostov deleted the fix-metadata-regression branch March 29, 2021 19:48
@emostov
Copy link
Contributor

emostov commented Mar 29, 2021

@lovesh you should take a look at the dock controller configs to make sure they are still valid. Additionally you may be interested in adding the equivalent of this for the dock chains.

@lovesh
Copy link
Contributor

lovesh commented Apr 8, 2021

@emostov Thanks for the notification. Submitted change at #511

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A0 - Please Review PR is ready for review I7 - Optimization 🚴 Make Sidecar drive faster
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants