Replace AtomicInteger with LongAdder for curThreadNum of StatisticNode (#747)
This commit is contained in:
parent
9583e18706
commit
3a9e2629b7
|
|
@ -15,15 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package com.alibaba.csp.sentinel.node;
|
package com.alibaba.csp.sentinel.node;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
||||||
|
import com.alibaba.csp.sentinel.slots.statistic.base.LongAdder;
|
||||||
|
import com.alibaba.csp.sentinel.slots.statistic.metric.ArrayMetric;
|
||||||
|
import com.alibaba.csp.sentinel.slots.statistic.metric.Metric;
|
||||||
|
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
|
||||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
|
||||||
import com.alibaba.csp.sentinel.slots.statistic.metric.ArrayMetric;
|
|
||||||
import com.alibaba.csp.sentinel.slots.statistic.metric.Metric;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>The statistic node keep three kinds of real-time statistics metrics:</p>
|
* <p>The statistic node keep three kinds of real-time statistics metrics:</p>
|
||||||
|
|
@ -104,7 +104,7 @@ public class StatisticNode implements Node {
|
||||||
/**
|
/**
|
||||||
* The counter for thread count.
|
* The counter for thread count.
|
||||||
*/
|
*/
|
||||||
private AtomicInteger curThreadNum = new AtomicInteger(0);
|
private LongAdder curThreadNum = new LongAdder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last timestamp when metrics were fetched.
|
* The last timestamp when metrics were fetched.
|
||||||
|
|
@ -233,7 +233,7 @@ public class StatisticNode implements Node {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int curThreadNum() {
|
public int curThreadNum() {
|
||||||
return curThreadNum.get();
|
return (int)curThreadNum.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -265,12 +265,12 @@ public class StatisticNode implements Node {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void increaseThreadNum() {
|
public void increaseThreadNum() {
|
||||||
curThreadNum.incrementAndGet();
|
curThreadNum.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decreaseThreadNum() {
|
public void decreaseThreadNum() {
|
||||||
curThreadNum.decrementAndGet();
|
curThreadNum.decrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,23 @@ package com.alibaba.csp.sentinel.node;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.Constants;
|
import com.alibaba.csp.sentinel.Constants;
|
||||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
@ -198,4 +204,125 @@ public class StatisticNodeTest {
|
||||||
private static void log(Object obj) {
|
private static void log(Object obj) {
|
||||||
System.out.println(LOG_PREFIX + obj);
|
System.out.println(LOG_PREFIX + obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* com.alibaba.csp.sentinel.node.StatisticNode#curThreadNum using LongAdder replace the AtomicInteger.
|
||||||
|
* now test the LongAdder is fast than AtomicInteger
|
||||||
|
* and get the right statistic or not
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testStatisticLongAdder() throws InterruptedException {
|
||||||
|
AtomicInteger atomicInteger = new AtomicInteger(0);
|
||||||
|
StatisticNode statisticNode = new StatisticNode();
|
||||||
|
ExecutorService bizEs1 = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT,
|
||||||
|
0L, TimeUnit.MILLISECONDS,
|
||||||
|
new LinkedBlockingQueue<Runnable>());
|
||||||
|
ExecutorService bizEs2 = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT,
|
||||||
|
0L, TimeUnit.MILLISECONDS,
|
||||||
|
new LinkedBlockingQueue<Runnable>());
|
||||||
|
int taskCount = 100;
|
||||||
|
for (int i = 0; i < taskCount; i++) {
|
||||||
|
int op = i % 2;
|
||||||
|
bizEs2.submit(new StatisticAtomicIntegerTask(atomicInteger, op, i));
|
||||||
|
bizEs1.submit(new StatisticLongAdderTask(statisticNode, op, i));
|
||||||
|
}
|
||||||
|
Thread.sleep(5000);
|
||||||
|
|
||||||
|
log("LongAdder totalCost : " + StatisticLongAdderTask.totalCost() + "ms");
|
||||||
|
log("AtomicInteger totalCost : " + StatisticAtomicIntegerTask.totalCost() + "ms");
|
||||||
|
Assert.assertEquals(statisticNode.curThreadNum(), atomicInteger.get());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StatisticLongAdderTask implements Runnable {
|
||||||
|
|
||||||
|
|
||||||
|
private StatisticNode statisticNode;
|
||||||
|
/**
|
||||||
|
* 0 addition
|
||||||
|
* 1 subtraction
|
||||||
|
*/
|
||||||
|
private int op;
|
||||||
|
|
||||||
|
private int taskId;
|
||||||
|
|
||||||
|
private static Map<Integer, Long> taskCostMap = new ConcurrentHashMap<>(16);
|
||||||
|
|
||||||
|
|
||||||
|
public StatisticLongAdderTask(StatisticNode statisticNode, int op, int taskId) {
|
||||||
|
this.statisticNode = statisticNode;
|
||||||
|
this.op = op;
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
int calCount = 100000;
|
||||||
|
for (int i = 0; i < calCount; i++) {
|
||||||
|
if (op == 0) {
|
||||||
|
statisticNode.increaseThreadNum();
|
||||||
|
} else if (op == 1) {
|
||||||
|
statisticNode.decreaseThreadNum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long cost = System.currentTimeMillis() - startTime;
|
||||||
|
taskCostMap.put(taskId, cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long totalCost() {
|
||||||
|
long totalCost = 0;
|
||||||
|
for (long cost : taskCostMap.values()) {
|
||||||
|
totalCost += cost;
|
||||||
|
}
|
||||||
|
return totalCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StatisticAtomicIntegerTask implements Runnable {
|
||||||
|
|
||||||
|
AtomicInteger atomicInteger;
|
||||||
|
/**
|
||||||
|
* 0 addition
|
||||||
|
* 1 subtraction
|
||||||
|
*/
|
||||||
|
private int op;
|
||||||
|
|
||||||
|
private int taskId;
|
||||||
|
|
||||||
|
private static Map<Integer, Long> taskCostMap = new ConcurrentHashMap<>(16);
|
||||||
|
|
||||||
|
public StatisticAtomicIntegerTask(AtomicInteger atomicInteger, int op, int taskId) {
|
||||||
|
this.atomicInteger = atomicInteger;
|
||||||
|
this.op = op;
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
int calCount = 100000;
|
||||||
|
for (int i = 0; i < calCount; i++) {
|
||||||
|
if (op == 0) {
|
||||||
|
atomicInteger.incrementAndGet();
|
||||||
|
} else if (op == 1) {
|
||||||
|
atomicInteger.decrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long cost = System.currentTimeMillis() - startTime;
|
||||||
|
taskCostMap.put(taskId, cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long totalCost() {
|
||||||
|
long totalCost = 0;
|
||||||
|
for (long cost : taskCostMap.values()) {
|
||||||
|
totalCost += cost;
|
||||||
|
}
|
||||||
|
return totalCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue