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

performance: Don't preallocate rarely used maps in MakeStateDelta #4715

Merged
merged 7 commits into from
Nov 3, 2022

Conversation

iansuvak
Copy link
Contributor

Summary

This PR removes explicit definitions for Txlease and Creatables maps in MakeStateDelta and make{app|resource}Caches in MakeAccountDelta.

The latter already had upsert methods defined that would allocate an empty map if it was nil. This creates matching methods for the remaining two fields and propagates them wherever they are used.

This is a risky change because some code could be added in the future that tries to insert into the nil-map. Open to suggestions or closing this PR if the risk is not worth it

Test Plan

Existing tests pass and added new tests for the new methods.

On scenario1s pprof this reduces alloc_objects metric as compared to master as percentage of all objects allocated:

  • MakeStateDelta 14.17% -> 8.65%
  • MakeAccountDelta 8.07% -> 4.33%

@algorandskiy algorandskiy requested a review from cce October 31, 2022 21:05
ledger/txtail.go Outdated Show resolved Hide resolved
ledger/ledgercore/statedelta.go Outdated Show resolved Hide resolved
Comment on lines 37 to 47
cs.mods.Creatables[basics.CreatableIndex(index)] = ledgercore.ModifiedCreatable{
Ctype: basics.AssetCreatable,
Creator: addr,
Created: false,
}
cs.mods.UpsertCreatable(
basics.CreatableIndex(index),
ledgercore.ModifiedCreatable{
Ctype: basics.AssetCreatable,
Creator: addr,
Created: false,
},
)
Copy link
Contributor

Choose a reason for hiding this comment

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

could write a quick test and see if the new code has more allocations than the old one? - wondering if compiler optimizes it right.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did you mean for this function in particular? or in general?

I ran the BenchmarkMakeStateDelta that already existed. Out of the box it's the same on master and this branch at 5allocs/op but when adding //go:noinline to MakeStateDelta the difference becomes 7 vs 12 as expected.

That seems odd to me since running go build --gcflags="-m" . in ledger/ledgercore gives this showing that the allocs are escaping to heap when compiled and scenario1 run above confirms it:
Screen Shot 2022-11-03 at 3 27 01 PM

Copy link
Contributor

Choose a reason for hiding this comment

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

then maybe AddCreatable should take a pointer to get rid of additional copying?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like this is already merged but do you want me to add it? This should be called rarely and the objects are tiny so the copy cost is not big but should be safe

@cce cce requested a review from jannotti November 1, 2022 20:36
Txids: make(map[transactions.Txid]IncludedTransactions, hint),
Txleases: make(map[Txlease]basics.Round),
Accts: MakeAccountDeltas(hint),
KvMods: make(map[string]KvValueDelta),
Copy link
Contributor

Choose a reason for hiding this comment

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

KvMods seems like a candidate for the same treatment. The vast majority of txns will not have any KvMods.

ledger/ledgercore/statedelta_test.go Outdated Show resolved Hide resolved
ledger/txtail.go Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Nov 3, 2022

Codecov Report

Merging #4715 (33ec03b) into master (3701d29) will increase coverage by 0.00%.
The diff coverage is 40.00%.

@@           Coverage Diff           @@
##           master    #4715   +/-   ##
=======================================
  Coverage   54.62%   54.62%           
=======================================
  Files         414      414           
  Lines       53517    53533   +16     
=======================================
+ Hits        29231    29245   +14     
+ Misses      21864    21862    -2     
- Partials     2422     2426    +4     
Impacted Files Coverage Δ
ledger/internal/applications.go 3.87% <0.00%> (ø)
ledger/internal/assetcow.go 0.00% <0.00%> (ø)
ledger/internal/cow.go 64.91% <25.00%> (ø)
ledger/internal/appcow.go 74.49% <100.00%> (+0.14%) ⬆️
ledger/ledgercore/statedelta.go 14.02% <100.00%> (+6.72%) ⬆️
ledger/blockqueue.go 85.63% <0.00%> (-2.88%) ⬇️
crypto/merkletrie/trie.go 66.42% <0.00%> (-2.19%) ⬇️
agreement/cryptoVerifier.go 67.60% <0.00%> (-2.12%) ⬇️
agreement/proposalManager.go 96.07% <0.00%> (-1.97%) ⬇️
crypto/merkletrie/node.go 91.62% <0.00%> (-1.87%) ⬇️
... and 8 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@algorandskiy algorandskiy merged commit 25e0087 into algorand:master Nov 3, 2022
Comment on lines 311 to 313
for key, value := range cb.mods.KvMods {
cb.commitParent.mods.KvMods[key] = value
cb.commitParent.mods.AddKvMod(key, value)
}
Copy link
Contributor

@cce cce Nov 4, 2022

Choose a reason for hiding this comment

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

I guess it might have been slightly more performant to do:

    if len(cb.mods.KvMods) {
        cb.commitParent.mods.KvMods = make(map[string]KvValueDelta)
	}
	for key, value := range cb.mods.KvMods {
		cb.commitParent.mods.KvMods[key] = value
	}

@jannotti
Copy link
Contributor

jannotti commented Nov 4, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants