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

exp/orderbook: Speed up path finding dfs by avoiding calls to consumeOffers for visited nodes #3933

Merged
merged 2 commits into from
Sep 17, 2021

Conversation

tamirms
Copy link
Contributor

@tamirms tamirms commented Sep 17, 2021

While I was reviewing #3921 , I realized we could improve the performance of the path finding DFS by moving the visited check from the beginning of the function to the moment we consider each outgoing edge.

Previously, we were doing both the call to consumeOffers() and the visited check for each outgoing edge. Now, we only call consumeOffers() if we pass the visited check. We improve the performance of the dfs by removing the expensive calls to consumeOffers() on edges which lead to nodes we have already visited.

Benchmark before changes:

goos: darwin
goarch: amd64
pkg: github.com/stellar/go/exp/orderbook
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkMultipleDestinationAssets
BenchmarkMultipleDestinationAssets-12    	       2	 501200867 ns/op
BenchmarkTestData
BenchmarkTestData-12                     	       1	19009783799 ns/op
PASS

Benchmark after changes:

goos: darwin
goarch: amd64
pkg: github.com/stellar/go/exp/orderbook
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkMultipleDestinationAssets
BenchmarkMultipleDestinationAssets-12    	       3	 402958734 ns/op
BenchmarkTestData
BenchmarkTestData-12                     	       1	15575703035 ns/op
PASS

There is about a 25% improvement in the benchmarks.

@@ -73,31 +83,25 @@ func dfs(
if err := ctx.Err(); err != nil {
return err
}
if currentAssetAmount <= 0 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we don't need to check if currentAssetAmount <= 0 because do the same check (nextAssetAmount <= 0) when processing outgoing edges.

@tamirms tamirms changed the title exp/orderbook: Speed up path finding dfs by avoiding edges leading to visited nodes exp/orderbook: Speed up path finding dfs by avoiding calls to consumeOffers for visited nodes Sep 17, 2021
@tamirms tamirms requested a review from a team September 17, 2021 08:48
Copy link
Contributor

@bartekn bartekn left a comment

Choose a reason for hiding this comment

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

Good find!

@@ -59,11 +59,21 @@ type searchState interface {
) (xdr.Asset, xdr.Int64, error)
}

func contains(list []string, want string) bool {
for i := 0; i < len(list); i++ {
if list[i] == want {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason why not use xdr.Asset.Equal as before? Is string comparison much faster?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The string comparison is faster than xdr.Asset.Equal but both of those operations are very fast.

The reason why I can't use xdr.Asset.Equal is because I only have nextAssetString I don't have the xdr.Asset form. Calling String() on each xdr.Asset in the visited list so that I can compare against nextAssetString would be significantly slower because of the String() operation

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, maybe we should remove visitedAssets then? If I'm reading the code right we can replace it with visitedAssetStrings everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

appendToPaths() requires visitedAssets. I think we previously discussed having an asset type which caches the String() result. I can try that out in a separate PR

@tamirms tamirms merged commit 2be7469 into stellar:master Sep 17, 2021
Shaptic pushed a commit to Shaptic/go that referenced this pull request Sep 21, 2021
This PR has been updated to work with liquidity pools as well.
Shaptic added a commit that referenced this pull request Sep 27, 2021
…s. (#3921)

* Add a way to simulate exchanges with liquidity pools
* Drop unused methods from `OBGraph` interface
* Iterate through interleaved set of LPs/offers
* Add various test cases: LPs, non-linear ratios, interleaved hops
* Speed up path-finding by avoiding edges to visited nodes (#3933)
* Integrate venues deeper into the graph for performance
* Update ingestion to match new function signature
* Add changelog entry

Co-authored-by: tamirms <tamir@stellar.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants