You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/06/27 09:57:15 UTC

[skywalking] branch master updated: Perf: optimize Envoy ALS analyzer performance in high traffic load scenario (reduce ~1cpu in ~10k RPS) (#7182)

This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new e7bc81a  Perf: optimize Envoy ALS analyzer performance in high traffic load scenario (reduce ~1cpu in ~10k RPS) (#7182)
e7bc81a is described below

commit e7bc81abbbcfdb32263f28b5eab1263414687489
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Sun Jun 27 17:56:59 2021 +0800

    Perf: optimize Envoy ALS analyzer performance in high traffic load scenario (reduce ~1cpu in ~10k RPS) (#7182)
---
 CHANGES.md                                         |  1 +
 .../receiver/envoy/ServiceMetaInfoFactoryImpl.java |  2 +-
 .../server/receiver/envoy/als/mx/FieldsHelper.java | 52 +++++++++++++++-------
 .../envoy/als/mx/ServiceMetaInfoAdapter.java       |  3 +-
 4 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index dae2bc0..5956f91 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -43,6 +43,7 @@ Release Notes.
 * OAL supports generating metrics from events.
 * Support endpoint name grouping by OpenAPI definitions.
 * Fix CounterWindow increase computing issue.
+* Performance: optimize Envoy ALS analyzer performance in high traffic load scenario (reduce ~1cpu in ~10k RPS).
 
 #### UI
 * Fix the date component for log conditions.
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
index 516989c..7916e01 100644
--- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
@@ -36,7 +36,7 @@ public class ServiceMetaInfoFactoryImpl implements ServiceMetaInfoFactory {
     }
 
     @Override
-    public ServiceMetaInfo fromStruct(final Struct struct) throws Exception {
+    public ServiceMetaInfo fromStruct(final Struct struct) {
         return new ServiceMetaInfoAdapter(struct);
     }
 }
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
index a615284..e0da74c 100644
--- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
@@ -18,28 +18,36 @@
 
 package org.apache.skywalking.oap.server.receiver.envoy.als.mx;
 
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.protobuf.Struct;
-import com.google.protobuf.Value;
 import java.io.InputStream;
-import java.lang.reflect.Method;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.BiConsumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import lombok.RequiredArgsConstructor;
-import lombok.experimental.Delegate;
-import lombok.extern.slf4j.Slf4j;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.skywalking.oap.server.library.module.ModuleStartException;
 import org.apache.skywalking.oap.server.library.util.ResourceUtils;
 import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
 import org.yaml.snakeyaml.Yaml;
 
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Value;
+
+import lombok.RequiredArgsConstructor;
+import lombok.experimental.Delegate;
+import lombok.extern.slf4j.Slf4j;
+
 @Slf4j
 public enum FieldsHelper {
     SINGLETON;
@@ -54,7 +62,7 @@ public enum FieldsHelper {
     /**
      * The mappings from the field name of {@link ServiceMetaInfo} to its {@code setter}.
      */
-    private Map<String, Method> fieldSetterMapping;
+    private Map<String, BiConsumer<? super ServiceMetaInfo, String>> fieldSetterMapping;
 
     public void init(final String file,
                      final Class<? extends ServiceMetaInfo> serviceInfoClass) throws Exception {
@@ -69,7 +77,7 @@ public enum FieldsHelper {
         }
 
         final Yaml yaml = new Yaml();
-        final Map<String, String> config = (Map<String, String>) yaml.load(inputStream);
+        final Map<String, String> config = yaml.load(inputStream);
 
         fieldNameMapping = new HashMap<>(config.size());
         fieldSetterMapping = new HashMap<>(config.size());
@@ -114,10 +122,21 @@ public enum FieldsHelper {
             );
 
             try {
-                final Method setterMethod = serviceInfoClass.getMethod("set" + StringUtils.capitalize(serviceMetaInfoFieldName), String.class);
-                setterMethod.setAccessible(true);
-                fieldSetterMapping.put(serviceMetaInfoFieldName, setterMethod);
-            } catch (final NoSuchMethodException e) {
+                final String setter = "set" + StringUtils.capitalize(serviceMetaInfoFieldName);
+                final MethodHandles.Lookup lookup = MethodHandles.lookup();
+                final Class<?> parameterType = String.class;
+                final CallSite site = LambdaMetafactory.metafactory(
+                        lookup, "accept",
+                        MethodType.methodType(BiConsumer.class),
+                        MethodType.methodType(void.class, Object.class, Object.class),
+                        lookup.findVirtual(serviceInfoClass, setter,
+                                           MethodType.methodType(void.class, parameterType)),
+                        MethodType.methodType(void.class, serviceInfoClass, parameterType));
+                final MethodHandle factory = site.getTarget();
+                final BiConsumer<? super ServiceMetaInfo, String> method =
+                        (BiConsumer<? super ServiceMetaInfo, String>) factory.invoke();
+                fieldSetterMapping.put(serviceMetaInfoFieldName, method);
+            } catch (final Throwable e) {
                 throw new ModuleStartException("Initialize method error", e);
             }
         }
@@ -129,9 +148,8 @@ public enum FieldsHelper {
      *
      * @param metadata        the {@link Struct} metadata from where to retrieve and inflate the {@code serviceMetaInfo}.
      * @param serviceMetaInfo the {@code serviceMetaInfo} to be inflated.
-     * @throws Exception if failed to inflate the {@code serviceMetaInfo}
      */
-    public void inflate(final Struct metadata, final ServiceMetaInfo serviceMetaInfo) throws Exception {
+    public void inflate(final Struct metadata, final ServiceMetaInfo serviceMetaInfo) {
         final Value empty = Value.newBuilder().setStringValue("-").build();
         final Value root = Value.newBuilder().setStructValue(metadata).build();
         for (final Map.Entry<String, ServiceNameFormat> entry : fieldNameMapping.entrySet()) {
@@ -153,7 +171,7 @@ public enum FieldsHelper {
             }
             final String value = Strings.lenientFormat(serviceNameFormat.format, values);
             if (!Strings.isNullOrEmpty(value)) {
-                fieldSetterMapping.get(entry.getKey()).invoke(serviceMetaInfo, value);
+                fieldSetterMapping.get(entry.getKey()).accept(serviceMetaInfo, value);
             }
         }
     }
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
index df8e38b..49ba821 100644
--- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
@@ -121,9 +121,8 @@ public class ServiceMetaInfoAdapter extends ServiceMetaInfo {
      * The same functionality with {@link ServiceMetaInfoAdapter#ServiceMetaInfoAdapter(com.google.protobuf.ByteString)}.
      *
      * @param metadata the {@link Struct struct} to adapt from.
-     * @throws Exception if the {@link Struct struct} can not be adapted to a {@link ServiceMetaInfo}.
      */
-    public ServiceMetaInfoAdapter(final Struct metadata) throws Exception {
+    public ServiceMetaInfoAdapter(final Struct metadata) {
         FieldsHelper.SINGLETON.inflate(requireNonNull(metadata), this);
     }