Perf: cache regex pattern and result, optimize string concatenation (#7199)
The possible metrics names are relatively fixed in an OAP run, we previously always escape the metrics names, building a new regex Pattern from scratch, which is cpu-consuming. In this patch, I cache the escaped metrics names, and if it missed, use a pre-compiled regex Pattern to escape the metrics name. This patch also replace string concatenation `+` with `StringBuilder` in generated classes, which won't get optimized by Java compiler This may reduce 1~1.5 vCPU under 20K RPS environment.
This commit is contained in:
parent
b8fadec033
commit
84a7fe30c8
|
|
@ -47,6 +47,7 @@ Release Notes.
|
|||
* Performance: optimize Envoy ALS analyzer performance in high traffic load scenario (reduce ~1cpu in ~10k RPS).
|
||||
* Performance: trim useless metadata fields in Envoy ALS metadata to improve performance.
|
||||
* Fix: slowDBAccessThreshold dynamic config error when not configured.
|
||||
* Performance: cache regex pattern and result, optimize string concatenation in Envy ALS analyzer.
|
||||
|
||||
#### UI
|
||||
* Fix the date component for log conditions.
|
||||
|
|
|
|||
|
|
@ -18,9 +18,17 @@
|
|||
|
||||
package org.apache.skywalking.oap.meter.analyzer.prometheus;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.vavr.Tuple;
|
||||
import io.vavr.Tuple2;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.skywalking.oap.meter.analyzer.MetricConvert;
|
||||
import org.apache.skywalking.oap.meter.analyzer.dsl.Sample;
|
||||
|
|
@ -34,10 +42,6 @@ import org.apache.skywalking.oap.server.library.util.prometheus.metrics.Histogra
|
|||
import org.apache.skywalking.oap.server.library.util.prometheus.metrics.Metric;
|
||||
import org.apache.skywalking.oap.server.library.util.prometheus.metrics.Summary;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static io.vavr.API.$;
|
||||
import static io.vavr.API.Case;
|
||||
|
|
@ -51,11 +55,23 @@ import static org.apache.skywalking.oap.meter.analyzer.Analyzer.NIL;
|
|||
*/
|
||||
@Slf4j
|
||||
public class PrometheusMetricConverter {
|
||||
private final Pattern metricsNameEscapePattern;
|
||||
|
||||
private final LoadingCache<String, String> escapedMetricsNameCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.build(new CacheLoader<String, String>() {
|
||||
@Override
|
||||
public String load(final String name) {
|
||||
return metricsNameEscapePattern.matcher(name).replaceAll("_");
|
||||
}
|
||||
});
|
||||
|
||||
private final MetricConvert convert;
|
||||
|
||||
public PrometheusMetricConverter(Rule rule, MeterSystem service) {
|
||||
this.convert = new MetricConvert(rule, service);
|
||||
this.metricsNameEscapePattern = Pattern.compile("\\.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,6 +162,11 @@ public class PrometheusMetricConverter {
|
|||
|
||||
// Returns the escaped name of the given one, with "." replaced by "_"
|
||||
protected String escapedName(final String name) {
|
||||
return name.replaceAll("\\.", "_");
|
||||
try {
|
||||
return escapedMetricsNameCache.get(name);
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Failed to get escaped metrics name from cache", e);
|
||||
return metricsNameEscapePattern.matcher(name).replaceAll("_");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
public String id() {
|
||||
String splitJointId = String.valueOf(getTimeBucket());
|
||||
StringBuilder splitJointId = new StringBuilder(String.valueOf(getTimeBucket()));
|
||||
<#list fieldsFromSource as sourceField>
|
||||
<#if sourceField.isID()>
|
||||
<#if sourceField.getTypeName() == "java.lang.String">
|
||||
splitJointId += org.apache.skywalking.oap.server.core.Const.ID_CONNECTOR + ${sourceField.fieldName};
|
||||
<#else>
|
||||
splitJointId += org.apache.skywalking.oap.server.core.Const.ID_CONNECTOR + String.valueOf(${sourceField.fieldName});
|
||||
</#if>
|
||||
splitJointId.append(org.apache.skywalking.oap.server.core.Const.ID_CONNECTOR)
|
||||
.append(${sourceField.fieldName});
|
||||
</#if>
|
||||
</#list>
|
||||
return splitJointId;
|
||||
}
|
||||
return splitJointId.toString();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue