Skip to content
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

optimize counter for min/max/avg/percentiles #340

Merged
merged 1 commit into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
<!-- 检查是否有嵌套代码块 -->
<module name="AvoidNestedBlocks"/>
<!-- 检查是否有空代码块 -->
<module name="EmptyBlock"/>
<!-- <module name="EmptyBlock"/>-->
<!-- 检查左大括号位置 -->
<module name="LeftCurly"/>
<!-- 检查右大括号位置 -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,6 @@ public class ThreadPoolStats extends Metrics {
*/
private double tps;

/**
* 任务平均耗时(单位:ms)
*/
private double mean;

/**
* 最大任务耗时
*/
Expand All @@ -152,10 +147,15 @@ public class ThreadPoolStats extends Metrics {
*/
private long minRt;

/**
* 任务平均耗时(单位:ms)
*/
private double avg;

/**
* 满足50%的任务执行所需的最低耗时
*/
private double median;
private double tp50;

/**
* 满足75%的任务执行所需的最低耗时
Expand Down
5 changes: 5 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>

<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ public static ThreadPoolStats toMetrics(ExecutorWrapper wrapper) {
poolStats.setDynamic(executor instanceof DtpExecutor);

poolStats.setTps(performanceSnapshot.getTps());
poolStats.setMean(performanceSnapshot.getMean());
poolStats.setAvg(performanceSnapshot.getAvg());
poolStats.setMaxRt(performanceSnapshot.getMaxRt());
poolStats.setMinRt(performanceSnapshot.getMinRt());
poolStats.setMedian(performanceSnapshot.getMedian());
poolStats.setTp50(performanceSnapshot.getTp50());
poolStats.setTp75(performanceSnapshot.getTp75());
poolStats.setTp90(performanceSnapshot.getTp90());
poolStats.setTp95(performanceSnapshot.getTp95());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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.dromara.dynamictp.core.metric;

import com.codahale.metrics.Reservoir;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.UniformSnapshot;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;

/**
* LimitedUniformReservoir related
*
* @author yanhom
* @since 1.1.5
*/
public class LimitedUniformReservoir implements Reservoir {

private static final int DEFAULT_SIZE = 4096;

private static final int BITS_PER_LONG = 63;

private final AtomicLong count = new AtomicLong();

private volatile AtomicLongArray values = new AtomicLongArray(DEFAULT_SIZE);

@Override
public int size() {
final long c = count.get();
if (c > values.length()) {
return values.length();
}
return (int) c;
}

@Override
public void update(long value) {
final long c = count.incrementAndGet();
if (c <= values.length()) {
values.set((int) c - 1, value);
} else {
final long r = nextLong(c);
if (r < values.length()) {
values.set((int) r, value);
}
}
}

@Override
public Snapshot getSnapshot() {
final int s = size();
final List<Long> copy = new ArrayList<>(s);
for (int i = 0; i < s; i++) {
copy.add(values.get(i));
}
return new UniformSnapshot(copy);
}

public void reset() {
count.set(0);
values = new AtomicLongArray(DEFAULT_SIZE);
}

private static long nextLong(long n) {
long bits;
long val;
do {
bits = ThreadLocalRandom.current().nextLong() & (~(1L << BITS_PER_LONG));
val = bits % n;
} while (bits - val + (n - 1) < 0L);
return val;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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.dromara.dynamictp.core.metric;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.atomic.AtomicLong;

/**
* MMACounter related
*
* @author yanhom
* @since 1.1.5
*/
@SuppressWarnings("all")
public class MMACounter implements Summary {

private final AtomicLong total = new AtomicLong();

private final AtomicLong count = new AtomicLong();

private final AtomicLong min = new AtomicLong(Long.MAX_VALUE);

private final AtomicLong max = new AtomicLong(Long.MIN_VALUE);

@Override
public void add(long value) {
total.addAndGet(value);
count.incrementAndGet();
setMin(value);
setMax(value);
}

public long getTotal() {
return total.get();
}

public long getCount() {
return count.get();
}

public long getMin() {
long current = min.get();
return (current == Long.MAX_VALUE) ? 0 : current;
}

public long getMax() {
long current = max.get();
return (current == Long.MIN_VALUE) ? 0 : current;
}

public double getAvg() {
long currentCount = count.get();
long currentTotal = total.get();
if (currentCount > 0) {
double avgLatency = currentTotal / (double) currentCount;
BigDecimal bg = new BigDecimal(avgLatency);
return bg.setScale(4, RoundingMode.HALF_UP).doubleValue();
}
return 0;
}

public void reset() {
total.set(0);
count.set(0);
min.set(Long.MAX_VALUE);
max.set(Long.MIN_VALUE);
}

private void setMax(long value) {
long current;
while (value > (current = max.get()) && !max.compareAndSet(current, value)) {
// no op
}
}

private void setMin(long value) {
long current;
while (value < (current = min.get()) && !min.compareAndSet(current, value)) {
// no op
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.dromara.dynamictp.core.metric;

import com.codahale.metrics.Histogram;
import com.codahale.metrics.Snapshot;

/**
* MMAPCounter related
*
* @author yanhom
* @since 1.1.5
*/
@SuppressWarnings("all")
public class MMAPCounter implements Summary {

private final MMACounter mmaCounter;

private final LimitedUniformReservoir reservoir;

private final Histogram histogram;

public MMAPCounter() {
this.mmaCounter = new MMACounter();
reservoir = new LimitedUniformReservoir();
histogram = new Histogram(reservoir);
}

@Override
public void add(long value) {
mmaCounter.add(value);
histogram.update(value);
}

public Snapshot getSnapshot() {
return histogram.getSnapshot();
}

public MMACounter getMmaCounter() {
return mmaCounter;
}

public void reset() {
mmaCounter.reset();
reservoir.reset();
}
}
34 changes: 34 additions & 0 deletions core/src/main/java/org/dromara/dynamictp/core/metric/Summary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.dromara.dynamictp.core.metric;

/**
* Summary related
*
* @author yanhom
* @since 1.1.5
*/
public interface Summary {

/**
* Add value.
*
* @param value current value
*/
void add(long value);
}
Loading
Loading