Skip to content

Optimize evaluation of treatments #210

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

cltnschlosser
Copy link

These changes resulted in a 3x performance increase of feature evaluation in a golang service I maintain. Almost every commit here can stand alone, and this PR can be broken up into individual (sometimes sequential) PRs for each commit if that makes it easier to review / merge.

The change with the largest impact is the first commit, introducing a layer for producing grammar.Split instances for the evaluator to use instead of interacting directly with the storage layer. With in memory storage we can introduce a cache which significantly optimizes feature evaluation performance, because Matchers and Conditions don't need to be created for each evaluation. This change would be a semver major change to this library but the changes to splitio/go-client are straightforward and don't impact the api there (cltnschlosser/go-client@7acbaae). I have those changes made and can open a PR there after this is merged and there is a public version to use in go.mod.
I did increase the go version here to be able to take advantage of iterators, though if that's an issue I can introduce a version which creates a temporary map or slice instead.

Time Flame graph
Before Split-Before
After Split-After

Important note: These are scaled for maximum readability, but aren't scaled relative to each other. This makes areas that didn't receive optimizations now look larger. They aren't slower, they are just now a larger percentage of the (much smaller) total time.

Aside about impression tracking

As you can see above, after these optimizations, the slowest piece is the impression tracking. I didn't investigate this area much because I believe my use case don't use impression data from the split sdk at all, so a future improvement would be to offer a mechanism to completely disable it.
I also think that once that is solved, we may see better performance by calling the individual TreatmentWithConfig function in a loop, because we can avoid several map creations. And the deduplication step in ValidateFeatureNames, which isn't a concern for my case.
But as I said I didn't dig in too far here, I wanted to focus on changes that didn't change functionality.

@cltnschlosser cltnschlosser requested a review from a team as a code owner June 9, 2025 01:39
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.

1 participant