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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit e6def8244c6990aaf396212adfbdf75eda53d7c0
Author: wujimin <[email protected]>
AuthorDate: Thu Nov 22 08:57:49 2018 +0800

    [SCB-1034] provide fast SimpleTimer to replace slow ServoTimer
---
 .../com/netflix/spectator/api/SpectatorUtils.java  |  22 +++-
 .../AbstractPeriodMeter.java}                      |  30 ++++--
 .../foundation/metrics/meter/PeriodMeter.java}     |  15 ++-
 .../foundation/metrics/meter/SimpleTimer.java      |  93 +++++++++++++++++
 .../metrics/registry/GlobalRegistry.java           | 114 +++++++++++++++++++++
 .../foundation/metrics/meter/TestSimpleTimer.java} |  31 ++++--
 .../metrics/metric/DefaultEndpointMetric.java      |  32 +++---
 java-chassis-dependencies/pom.xml                  |   2 +-
 java-chassis-distribution/src/release/LICENSE      |   4 +-
 9 files changed, 295 insertions(+), 48 deletions(-)

diff --git 
a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
 
b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
similarity index 55%
copy from 
foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
copy to 
foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
index 7a2f785..cccc710 100644
--- 
a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ 
b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
@@ -16,8 +16,24 @@
  */
 package com.netflix.spectator.api;
 
-public class SpectatorUtils {
-  public static CompositeRegistry createCompositeRegistry(Clock clock) {
-    return new CompositeRegistry(clock);
+public final class SpectatorUtils {
+  private SpectatorUtils() {
+  }
+
+  public static Id createDefaultId(String name) {
+    return new DefaultId(name);
+  }
+
+  public static void removeExpiredMeters(Registry registry) {
+    if (registry instanceof AbstractRegistry) {
+      ((AbstractRegistry) registry).removeExpiredMeters();
+    }
+  }
+
+  public static void registerMeter(Registry registry, Meter meter) {
+    if (!(registry instanceof AbstractRegistry)) {
+      throw new IllegalStateException("registry must be a AbstractRegistry, 
class=" + registry.getClass().getName());
+    }
+    ((AbstractRegistry) registry).getOrCreate(meter.id(), Meter.class, null, 
_id -> meter);
   }
 }
diff --git 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
similarity index 60%
copy from 
foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
copy to 
foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
index 80a2055..d9e2f46 100644
--- 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
+++ 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
@@ -14,19 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics;
+package org.apache.servicecomb.foundation.metrics.meter;
 
-/**
- * give not standard meters to calc measurement , eg : cpu usage, net 
throughput, and so on
- */
-public class PollEvent {
-  private final long msPollInterval;
+import java.util.Collections;
+import java.util.List;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+
+public abstract class AbstractPeriodMeter implements PeriodMeter {
+  protected Id id;
+
+  protected List<Measurement> allMeasurements = Collections.emptyList();
+
+  public Id id() {
+    return id;
+  }
 
-  public PollEvent(long msPollInterval) {
-    this.msPollInterval = msPollInterval;
+  @Override
+  public Iterable<Measurement> measure() {
+    return allMeasurements;
   }
 
-  public long getMsPollInterval() {
-    return msPollInterval;
+  public boolean hasExpired() {
+    return false;
   }
 }
diff --git 
a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
similarity index 68%
rename from 
foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
rename to 
foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index 7a2f785..f91d781 100644
--- 
a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -14,10 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.netflix.spectator.api;
+package org.apache.servicecomb.foundation.metrics.meter;
 
-public class SpectatorUtils {
-  public static CompositeRegistry createCompositeRegistry(Clock clock) {
-    return new CompositeRegistry(clock);
-  }
+import java.util.List;
+
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+
+public interface PeriodMeter extends Meter {
+  void calcMeasurements(long msNow, long secondInterval);
+
+  void calcMeasurements(List<Measurement> measurements, long msNow, long 
secondInterval);
 }
diff --git 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
new file mode 100644
index 0000000..09803a4
--- /dev/null
+++ 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.metrics.meter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Statistic;
+import com.netflix.spectator.impl.AtomicDouble;
+
+/**
+ * ServoTimer is too slow
+ * this is a faster timer
+ */
+public class SimpleTimer extends AbstractPeriodMeter {
+  private static final double CNV_SECONDS = 1.0 / TimeUnit.SECONDS.toNanos(1L);
+
+  private final Id idCount;
+
+  private final Id idTotalTime;
+
+  private final Id idMax;
+
+  private final LongAdder count = new LongAdder();
+
+  private final LongAdder totalTime = new LongAdder();
+
+  private final AtomicDouble max = new AtomicDouble();
+
+  private long lastCount = 0;
+
+  private long lastTotalTime = 0;
+
+  public SimpleTimer(Id id) {
+    this.id = id;
+    this.idCount = id.withTag(Statistic.count);
+    this.idTotalTime = id.withTag(Statistic.totalTime);
+    this.idMax = id.withTag(Statistic.max);
+  }
+
+  public void record(long nanoAmount) {
+    if (nanoAmount >= 0) {
+      totalTime.add(nanoAmount);
+      count.increment();
+      max.max(nanoAmount);
+    }
+  }
+
+  private Measurement newMeasurement(Id id, long msNow, Number n) {
+    return new Measurement(id, msNow, n.doubleValue());
+  }
+
+  @Override
+  public void calcMeasurements(long msNow, long secondInterval) {
+    List<Measurement> measurements = new ArrayList<>(3);
+    calcMeasurements(measurements, msNow, secondInterval);
+    allMeasurements = measurements;
+  }
+
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, 
long secondInterval) {
+    long currentCount = count.longValue();
+    long currentTotalTime = totalTime.longValue();
+
+    measurements.add(newMeasurement(idCount, msNow, (double) (currentCount - 
lastCount) / secondInterval));
+    measurements
+        .add(newMeasurement(idTotalTime, msNow, (currentTotalTime - 
lastTotalTime) / secondInterval * CNV_SECONDS));
+    measurements.add(newMeasurement(idMax, msNow, max.get() * CNV_SECONDS));
+
+    lastCount = currentCount;
+    lastTotalTime = currentTotalTime;
+    // maybe lost some max value, but not so important?
+    max.set(0);
+  }
+}
diff --git 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
new file mode 100644
index 0000000..9af39d0
--- /dev/null
+++ 
b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.metrics.registry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.servicecomb.foundation.metrics.PolledEvent;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
+
+import com.netflix.spectator.api.Clock;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class GlobalRegistry {
+  private Clock clock;
+
+  private List<Registry> registries = new CopyOnWriteArrayList<>();
+
+  private Registry defaultRegistry;
+
+  public GlobalRegistry() {
+    this(Clock.SYSTEM);
+  }
+
+  public GlobalRegistry(Clock clock) {
+    this.clock = clock;
+  }
+
+  public Clock getClock() {
+    return clock;
+  }
+
+  public List<Registry> getRegistries() {
+    return registries;
+  }
+
+  public Registry getDefaultRegistry() {
+    return defaultRegistry;
+  }
+
+  public synchronized void add(Registry registry) {
+    if (registries.isEmpty()) {
+      defaultRegistry = registry;
+    }
+    registries.add(registry);
+  }
+
+  public synchronized void remove(Registry registry) {
+    registries.remove(registry);
+    if (registry != defaultRegistry) {
+      return;
+    }
+
+    if (registries.isEmpty()) {
+      defaultRegistry = null;
+      return;
+    }
+
+    defaultRegistry = registries.get(0);
+  }
+
+  public synchronized void removeAll() {
+    registries.clear();
+    defaultRegistry = null;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Registry> T find(Class<T> cls) {
+    for (Registry registry : registries) {
+      if (cls.isAssignableFrom(registry.getClass())) {
+        return (T) registry;
+      }
+    }
+    return null;
+  }
+
+  public PolledEvent poll(long secondInterval) {
+    long msNow = clock.wallTime();
+    List<Meter> meters = new ArrayList<>();
+    List<Measurement> measurements = new ArrayList<>();
+    for (Registry registry : registries) {
+      SpectatorUtils.removeExpiredMeters(registry);
+
+      for (Meter meter : registry) {
+        if (meter instanceof PeriodMeter) {
+          ((PeriodMeter) meter).calcMeasurements(msNow, secondInterval);
+        }
+
+        meters.add(meter);
+        meter.measure().forEach(measurements::add);
+      }
+    }
+
+    return new PolledEvent(meters, measurements);
+  }
+}
diff --git 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
 
b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
similarity index 51%
rename from 
foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
rename to 
foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
index 80a2055..1d34497 100644
--- 
a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
+++ 
b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
@@ -14,19 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics;
+package org.apache.servicecomb.foundation.metrics.meter;
 
-/**
- * give not standard meters to calc measurement , eg : cpu usage, net 
throughput, and so on
- */
-public class PollEvent {
-  private final long msPollInterval;
+import org.junit.Assert;
+import org.junit.Test;
 
-  public PollEvent(long msPollInterval) {
-    this.msPollInterval = msPollInterval;
-  }
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class TestSimpleTimer {
+  SimpleTimer timer = new SimpleTimer(SpectatorUtils.createDefaultId("name"));
+
+  @Test
+  public void measure() {
+    timer.record(2);
+    timer.record(4);
+
+    Assert.assertFalse(timer.measure().iterator().hasNext());
 
-  public long getMsPollInterval() {
-    return msPollInterval;
+    timer.calcMeasurements(1, 2);
+    Assert.assertEquals(
+        "[Measurement(name:statistic=count,1,1.0), 
Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), 
Measurement(name:statistic=max,1,4.0E-9)]",
+        timer.measure().toString());
+    Assert.assertFalse(timer.hasExpired());
+    Assert.assertEquals("name", timer.id().name());
   }
 }
diff --git 
a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
 
b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
index f25ca64..86590ce 100644
--- 
a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
+++ 
b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.foundation.vertx.metrics.metric;
 
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAdder;
 
 import io.vertx.core.net.SocketAddress;
 
@@ -28,15 +28,15 @@ public class DefaultEndpointMetric {
 
   // summary of connect times from boot
   // by this, we can know how many new connections connected recently
-  private AtomicLong connectCount = new AtomicLong();
+  private LongAdder connectCount = new LongAdder();
 
   // summary of disconnect times from boot
   // by this, we can know how many connections disconnected recently
-  private AtomicLong disconnectCount = new AtomicLong();
+  private LongAdder disconnectCount = new LongAdder();
 
-  private AtomicLong bytesRead = new AtomicLong();
+  private LongAdder bytesRead = new LongAdder();
 
-  private AtomicLong bytesWritten = new AtomicLong();
+  private LongAdder bytesWritten = new LongAdder();
 
   public DefaultEndpointMetric(SocketAddress address) {
     this.address = address;
@@ -47,38 +47,38 @@ public class DefaultEndpointMetric {
   }
 
   public long getConnectCount() {
-    return connectCount.get();
+    return connectCount.longValue();
   }
 
   public long getDisconnectCount() {
-    return disconnectCount.get();
+    return disconnectCount.longValue();
   }
 
   public long getCurrentConnectionCount() {
-    return connectCount.get() - disconnectCount.get();
+    return connectCount.longValue() - disconnectCount.longValue();
   }
 
   public void onConnect() {
-    connectCount.incrementAndGet();
+    connectCount.increment();
   }
 
   public void onDisconnect() {
-    disconnectCount.incrementAndGet();
+    disconnectCount.increment();
   }
 
   public long getBytesRead() {
-    return bytesRead.get();
+    return bytesRead.longValue();
   }
 
-  public long addBytesRead(long bytes) {
-    return bytesRead.addAndGet(bytes);
+  public void addBytesRead(long bytes) {
+    bytesRead.add(bytes);
   }
 
   public long getBytesWritten() {
-    return bytesWritten.get();
+    return bytesWritten.longValue();
   }
 
-  public long addBytesWritten(long bytes) {
-    return bytesWritten.addAndGet(bytes);
+  public void addBytesWritten(long bytes) {
+    bytesWritten.add(bytes);
   }
 }
diff --git a/java-chassis-dependencies/pom.xml 
b/java-chassis-dependencies/pom.xml
index 50a0778..0847d69 100644
--- a/java-chassis-dependencies/pom.xml
+++ b/java-chassis-dependencies/pom.xml
@@ -366,7 +366,7 @@
       <dependency>
         <groupId>com.netflix.spectator</groupId>
         <artifactId>spectator-reg-servo</artifactId>
-        <version>0.63.0</version>
+        <version>0.71.0</version>
       </dependency>
       <dependency>
         <groupId>com.google.inject</groupId>
diff --git a/java-chassis-distribution/src/release/LICENSE 
b/java-chassis-distribution/src/release/LICENSE
index 31051f3..e166434 100644
--- a/java-chassis-distribution/src/release/LICENSE
+++ b/java-chassis-distribution/src/release/LICENSE
@@ -422,8 +422,8 @@ rxnetty-servo (https://github.com/ReactiveX/RxNetty) 
io.reactivex:rxnetty-servo:
 servo-core (https://github.com/Netflix/servo) 
com.netflix.servo:servo-core:jar:0.10.1
 servo-internal (https://github.com/Netflix/servo) 
com.netflix.servo:servo-internal:jar:0.10.1
 SnakeYAML (http://www.snakeyaml.org) org.yaml:snakeyaml:bundle:1.16
-spectator-api (https://github.com/Netflix/spectator) 
com.netflix.spectator:spectator-api:0.63.0
-spectator-reg-servo (https://github.com/Netflix/spectator) 
com.netflix.spectator:spectator-reg-servo:0.63.0
+spectator-api (https://github.com/Netflix/spectator) 
com.netflix.spectator:spectator-api:0.71.0
+spectator-reg-servo (https://github.com/Netflix/spectator) 
com.netflix.spectator:spectator-reg-servo:0.71.0
 Spring AOP (https://github.com/spring-projects/spring-framework) 
org.springframework:spring-aop:jar:4.3.16.RELEASE
 Spring Aspects (https://github.com/spring-projects/spring-framework) 
org.springframework:spring-aspects:jar:4.3.16.RELEASE
 Spring Beans (https://github.com/spring-projects/spring-framework) 
org.springframework:spring-beans:jar:4.3.16.RELEASE

Reply via email to