Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Conversation

@davidmurdoch
Copy link
Contributor

No description provided.

get(key: LargeNumber, cb: Callback<Buffer | null>): void;
put(key: LargeNumber, value: LargeNumber, cb: Callback<never>): void;
copy(): Trie;
copy(): CheckpointTrie;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just fixing some types

@@ -0,0 +1,11 @@
declare module "merkle-patricia-tree/secure" {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just adding a type for SecureTrie

if (txHashCurrentlyProcessing == transactionHash) {
const beforeTxListener = (tx: Transaction) => {
txHashCurrentlyProcessing = tx.hash();
if (txHashCurrentlyProcessing.equals(transactionHash)) {
Copy link
Contributor Author

@davidmurdoch davidmurdoch Feb 26, 2021

Choose a reason for hiding this comment

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

Comparing buffers is faster than converting them to a string then comparing strings.

(err: Error, result: Buffer) => {
if (err) {
throw err;
const database = this.#database;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For reasons, this.#database is slow once typescript compiles things, so I like to cache the lookup.

Copy link
Contributor

Choose a reason for hiding this comment

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

How did you measure the performance difference @davidmurdoch ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't need to. Just look at what typescript generates for our ES target. It's a function call, a Map has call, a branch, and a Map get call, IIRC.

I'd love to generate multiple builds so we can ship without these sorts of polyfills. I like the "true" private fields the syntax provides, and don't think I want to remove their use all together.

Happy to have your review on this!

if (err) {
throw err;
const database = this.#database;
return Promise.all(
Copy link
Contributor Author

@davidmurdoch davidmurdoch Feb 26, 2021

Choose a reason for hiding this comment

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

The beforeTx event emitter awaits the returned promise. I didn't find any race condition issues in our tests, but this seemed like a place they could crop up, so I thought it'd be good to "fix" it anyway.


resolve(keys);
});
const rs = storageTrie.createReadStream();
Copy link
Contributor Author

@davidmurdoch davidmurdoch Feb 26, 2021

Choose a reason for hiding this comment

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

We can't get keys to come back already ordered because the merkle patricia tree library we use parallelizes up to 500 database requests at once.

This just means we have to sort client side, which could mean performance takes a hit.

But generally I think callers to debug_storageRangeAt will attempt to consume all available storage in one go, which means we would have had to load all the data anyway.

Where we'd take a hit is when we only need to return a small amount of storage. In that case we still have to load all of it.

I think turning the priority queue it uses internally into a FIFO queue would actually be very complicated, because it resolves both branches and leaves, and it'd have to ensure the proper ordering there. Not positive though.

Since that's not going to happen any time soon, the next best thing is to just insert them in order as we get them, instead of a big oll sort at the end.

This will suck a bit more after we get the in-memory cache in place. We won't need any parallelization in that case; and it'll actually just slow everything down (it'll still be faster than hitting leveldb, of course).

Thanks for watching. Don't forget to smash that like button!

#initialize = async () => {
const levelupOptions: any = { valueEncoding: "binary" };
const levelupOptions: any = {
keyEncoding: "binary",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes it so that we don't have to stringify our keys, which are almost always, if not always, already a Buffer.

storageKeys.set(hashedKey, key.toBuffer());
).toBuffer();
const hashedKey = keccak(key);
storageKeys.set(hashedKey.toString(), { key, hashedKey });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Trading some memory for CPU. Previously the consumer of this data would convert the Map's keys (hashedKey.toString()) back into Buffers before saving them to the database. Now it just reads the Buffers stored in the values of the Map.

Comment on lines 28 to 48
export function findInsertPosition<T>(
array: T[],
val: T,
comp: (a: T, b: T) => boolean
) {
let count = array.length;

let first = 0;
let offset = 0;
while (count > 0) {
let step = (count / 2) | 0;
offset += step;
if (!comp(val, array[offset])) {
first = ++offset;
count -= step + 1;
} else {
count = step;
offset = first;
}
}
return first;
Copy link
Contributor Author

@davidmurdoch davidmurdoch Feb 26, 2021

Choose a reason for hiding this comment

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

Binary searches a sorted array for the sorted insert position.

This implementation was ported from the C++ stdlib, http://www.cplusplus.com/reference/algorithm/upper_bound/.

@davidmurdoch davidmurdoch marked this pull request as ready for review February 26, 2021 02:49
@davidmurdoch davidmurdoch changed the title chore(perf): optimize debug_storageRangeAt perf: optimize debug_storageRangeAt Feb 26, 2021
Copy link
Contributor

@eshaben eshaben left a comment

Choose a reason for hiding this comment

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

just a couple small things... looks good though! thanks for cleaning it up... keyStart 😆

Copy link
Contributor

@eshaben eshaben left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@gnidan gnidan left a comment

Choose a reason for hiding this comment

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

Here's a couple style suggestions. This looks good!

@davidmurdoch davidmurdoch merged commit f714114 into develop Mar 3, 2021
@davidmurdoch davidmurdoch deleted the debug_storageRangeAt-optimized branch March 3, 2021 22:44
sambacha pushed a commit to contractshark/ganache-core that referenced this pull request Apr 15, 2021
Co-authored-by: Erin Shaben <[email protected]>
Co-authored-by: g. nicholas d'andrea <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants