-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Single step expression is compiled into regex more than once (thus it makes test execution slower) #2035
Comments
My Java/cucumber-jvm knowledge is pretty low, but I managed to implement a quickfix/hack for this by introducing expression cache in |
Heya thanks for reporting this. A solution may be a bit more complicated then adding a cache. The type registry from which cucumber expressions are compiled is stateful. It is possible that same expression string results in a different regex. For example the expression I do have some long term plans to add some immutability to the runner and glue but it needs major change to the way backends discover and register glue. So I don't think this will be fixed any time soon. |
Some improvements may also come from implementing a proper parser for cucumber expressions rather the rewriting using regexes (see cucumber/common#771) but that too is a long term project. |
Thanks for quick and insightful reply @mpkorstanje. Feel free to close this issue if it's not going to be fixed anytime soon. PS: Thanks for Cucumber guys! It's pleasure to work with. |
Your welcome! I'll keep the issue around as a reminder to benchmark this in the future. |
If it were me,
public static void Patterns {
private static final Map<String, Pattern> store = new ConcurrentHashMap<>();
private Patterns() {}
public static Pattern compile(String pattern) {
return store.computeIfAbsent(pattern, Pattern::compile);
}
public static Pattern compile(String pattern, int flags) {
// ... look at flags, prepend to string pattern as (?x), delegate
// alternatively, have a HashKey class contain both the pattern and the flags
}
} |
Once |
I can confirm that all step expressions are recreated at each test scenario (for one of my project with about 400 test scenarios, expressions are recreated about 400 times). Also I understand the issue of caching with respect to the parameter type registry. Thus, I tested a cached version of my proposed
I can conclude that adding caching made no significant improvement. Thus, I'm not sure having such caching is the way to go to improve the performance. For completeness, there is the code with caching:
|
Currently we have to have to rebuild all Cucumber expressions for each scenario because |
It seems that all step expressions are re-compiled into regexes before each scenario.
Steps to reproduce the behavior:
io.cucumber.core.stepexpression.StepExpressionFactory.createExpression
method is executed twice with "foo" expression (because there are two scenarios)Expected behavior
"foo" is compiled only once.
Context & Motivation
I noticed that if I remove all bodies of my steps from sources it still takes considerable amount of time to run my tests (e.g., 2.2 seconds for 186 scenarios). Using Java Flight Recorder I collected some profiling data and it seems that a lot of time is being spent in
io.cucumber.core.stepexpression.StepExpressionFactory.createExpression
(47% in my case according to flame graph - see below). When I examined that method in debugger I noticed that it's being called more than once with sameexpressionString
parameter.Screenshots
Your Environment
The text was updated successfully, but these errors were encountered: