lightbend / config

configuration library for JVM languages using HOCON files
https://lightbend.github.io/config/
6.12k stars 968 forks source link

Inefficient getDuration() parsing - Re-creation of Pattern #770

Open baltiyskiy opened 2 years ago

baltiyskiy commented 2 years ago

We've noticed when we are calling to Config.getDuration() often enough, it generates a lot of garbage. Allocation profiling shows the following picture:

void java.util.regex.Pattern$BitClass.<init>()  24139   97.3 %
Pattern$CharPredicate java.util.regex.Pattern.clazz(boolean)    24139   97.3 %
Pattern$Node java.util.regex.Pattern.sequence(Pattern$Node) 24139   97.3 %
Pattern$Node java.util.regex.Pattern.expr(Pattern$Node) 24139   97.3 %
void java.util.regex.Pattern.compile()  24139   97.3 %
void java.util.regex.Pattern.<init>(String, int)    24139   97.3 %
Pattern java.util.regex.Pattern.compile(String) 24139   97.3 %
boolean java.util.regex.Pattern.matches(String, CharSequence)   24139   97.3 %
boolean java.lang.String.matches(String)    24139   97.3 %
long com.typesafe.config.impl.SimpleConfig.parseDuration(String, ConfigOrigin, String)  24139   97.3 %
Duration com.typesafe.config.impl.SimpleConfig.getDuration(String)  24139   97.3 %

Also

void java.util.ArrayList.<init>(int)    2770    3.97 %
void java.util.regex.Pattern.compile()  2084    2.99 %
void java.util.regex.Pattern.<init>(String, int)    2084    2.99 %
Pattern java.util.regex.Pattern.compile(String) 2084    2.99 %
boolean java.util.regex.Pattern.matches(String, CharSequence)   2084    2.99 %
boolean java.lang.String.matches(String)    2084    2.99 %
long com.typesafe.config.impl.SimpleConfig.parseDuration(String, ConfigOrigin, String)  2084    2.99 %
Duration com.typesafe.config.impl.SimpleConfig.getDuration(String)  2084    2.99 %

Basically, SimpleConfig.getDuration() uses String.matches() API (https://github.com/lightbend/config/blob/main/config/src/main/java/com/typesafe/config/impl/SimpleConfig.java#L781), which, internally, creates a new Pattern object just to throw it away. A simple fix is to hoist Pattern object as a static field and use it to perform the matching.