单机压测工具JMH

JMH Java准测试工具套件

什么是JMH

官网

http://openjdk.java.net/projects/code-tools/jmh/

创建JMH测试

1.创建Maven项目,添加依赖

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><encoding>UTF-8</encoding><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><groupId>mashibing.com</groupId><artifactId>HelloJMH2</artifactId><version>1.0-SNAPSHOT</version><dependencies><!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-core --><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.21</version></dependency><!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess --><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.21</version><scope>test</scope></dependency></dependencies></project>

2.idea安装JMH插件 JMH plugin v1.0.3

3.由于用到了注解,打开运行程序注解配置

compiler -> Annotation Processors -> Enable Annotation Processing

4.定义需要测试类PS (ParallelStream)

package com.mashibing.jmh;import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class PS {static List<Integer> nums = new ArrayList<>();static {Random r = new Random();for (int i = 0; i < 10000; i++) nums.add(1000000 + r.nextInt(1000000));}static void foreach() {nums.forEach(v->isPrime(v));}static void parallel() {nums.parallelStream().forEach(PS::isPrime);}static boolean isPrime(int num) {for(int i=2; i<=num/2; i++) {if(num % i == 0) return false;}return true;}
}

5.写单元测试

这个测试类一定要在 test package下面

package com.mashibing.jmh;import org.openjdk.jmh.annotations.*;import static org.junit.jupiter.api.Assertions.*;public class PSTest {@Benchmark@Warmup(iterations = 1, time = 3)@Fork(5)@BenchmarkMode(Mode.Throughput)@Measurement(iterations = 1, time = 3)public void testForEach() {PS.foreach();}
}

6.运行测试类,如果遇到下面的错误:

   ERROR: org.openjdk.jmh.runner.RunnerException: ERROR: Exception while trying to acquire the JMH lock (C:\WINDOWS\/jmh.lock): C:\WINDOWS\jmh.lock (拒绝访问。), exiting. Use -Djmh.ignoreLock=true to forcefully continue.at org.openjdk.jmh.runner.Runner.run(Runner.java:216)at org.openjdk.jmh.Main.main(Main.java:71)

这个错误是因为JMH运行需要访问系统的TMP目录,解决办法是:

打开RunConfiguration -> Environment Variables -> include system environment viables

7.阅读测试报告

JMH中的基本概念

  1. Warmup
    预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要

  2. Mesurement
    总共执行多少次测试

  3. Timeout

  4. Threads
    线程数,由fork指定

  5. Benchmark mode
    基准测试的模式

  6. Benchmark
    测试哪一段代码

Next

官方样例:
http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/


Disruptor单机最快MQ

内存里的高效队列

介绍

主页:http://lmax-exchange.github.io/disruptor/

源码:https://github.com/LMAX-Exchange/disruptor

GettingStarted: https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started

api: http://lmax-exchange.github.io/disruptor/docs/index.html

maven: https://mvnrepository.com/artifact/com.lmax/disruptor

Disruptor的特点

对比ConcurrentLinkedQueue : 链表实现

JDK中没有ConcurrentArrayQueue

Disruptor是数组实现的

无锁,高并发,使用环形Buffer,直接覆盖(不用清除)旧的数据,降低GC频率

实现了基于事件的生产者消费者模式(观察者模式)

RingBuffer

环形队列

RingBuffer的序号,指向下一个可用的元素

采用数组实现,没有首尾指针

对比ConcurrentLinkedQueue,用数组实现的速度更快

假如长度为8,当添加到第12个元素的时候在哪个序号上呢?用12%8决定

当Buffer被填满的时候到底是覆盖还是等待,由Producer决定

长度设为2的n次幂,利于二进制计算,例如:12%8 = 12 & (8 - 1) pos = num & (size -1)

Disruptor开发步骤

  1. 定义Event - 队列中需要处理的元素

  2. 定义Event工厂,用于填充队列

    这里牵扯到效率问题:disruptor初始化的时候,会调用Event工厂,对ringBuffer进行内存的提前分配

    GC产频率会降低

  3. 定义EventHandler(消费者),处理容器中的元素

事件发布模板

long sequence = ringBuffer.next();  // Grab the next sequence
try {LongEvent event = ringBuffer.get(sequence); // Get the entry in the Disruptor// for the sequenceevent.set(8888L);  // Fill with data
} finally {ringBuffer.publish(sequence);
}

使用EventTranslator发布事件

//===============================================================EventTranslator<LongEvent> translator1 = new EventTranslator<LongEvent>() {@Overridepublic void translateTo(LongEvent event, long sequence) {event.set(8888L);}};ringBuffer.publishEvent(translator1);//===============================================================EventTranslatorOneArg<LongEvent, Long> translator2 = new EventTranslatorOneArg<LongEvent, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l) {event.set(l);}};ringBuffer.publishEvent(translator2, 7777L);//===============================================================EventTranslatorTwoArg<LongEvent, Long, Long> translator3 = new EventTranslatorTwoArg<LongEvent, Long, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l1, Long l2) {event.set(l1 + l2);}};ringBuffer.publishEvent(translator3, 10000L, 10000L);//===============================================================EventTranslatorThreeArg<LongEvent, Long, Long, Long> translator4 = new EventTranslatorThreeArg<LongEvent, Long, Long, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l1, Long l2, Long l3) {event.set(l1 + l2 + l3);}};ringBuffer.publishEvent(translator4, 10000L, 10000L, 1000L);//===============================================================EventTranslatorVararg<LongEvent> translator5 = new EventTranslatorVararg<LongEvent>() {@Overridepublic void translateTo(LongEvent event, long sequence, Object... objects) {long result = 0;for(Object o : objects) {long l = (Long)o;result += l;}event.set(result);}};ringBuffer.publishEvent(translator5, 10000L, 10000L, 10000L, 10000L);

使用Lamda表达式

package com.mashibing.disruptor;import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.util.DaemonThreadFactory;public class Main03
{public static void main(String[] args) throws Exception{// Specify the size of the ring buffer, must be power of 2.int bufferSize = 1024;// Construct the DisruptorDisruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);// Connect the handlerdisruptor.handleEventsWith((event, sequence, endOfBatch) -> System.out.println("Event: " + event));// Start the Disruptor, starts all threads runningdisruptor.start();// Get the ring buffer from the Disruptor to be used for publishing.RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();ringBuffer.publishEvent((event, sequence) -> event.set(10000L));System.in.read();}
}

ProducerType生产者线程模式

ProducerType有两种模式 Producer.MULTI和Producer.SINGLE

默认是MULTI,表示在多线程模式下产生sequence

如果确认是单线程生产者,那么可以指定SINGLE,效率会提升

如果是多个生产者(多线程),但模式指定为SINGLE,会出什么问题呢?

等待策略

1,(常用)BlockingWaitStrategy:通过线程阻塞的方式,等待生产者唤醒,被唤醒后,再循环检查依赖的sequence是否已经消费。

2,BusySpinWaitStrategy:线程一直自旋等待,可能比较耗cpu

3,LiteBlockingWaitStrategy:线程阻塞等待生产者唤醒,与BlockingWaitStrategy相比,区别在signalNeeded.getAndSet,如果两个线程同时访问一个访问waitfor,一个访问signalAll时,可以减少lock加锁次数.

4,LiteTimeoutBlockingWaitStrategy:与LiteBlockingWaitStrategy相比,设置了阻塞时间,超过时间后抛异常。

5,PhasedBackoffWaitStrategy:根据时间参数和传入的等待策略来决定使用哪种等待策略

6,TimeoutBlockingWaitStrategy:相对于BlockingWaitStrategy来说,设置了等待时间,超过后抛异常

7,(常用)YieldingWaitStrategy:尝试100次,然后Thread.yield()让出cpu

8,(常用)SleepingWaitStrategy : sleep

消费者异常处理

默认:disruptor.setDefaultExceptionHandler()

覆盖:disruptor.handleExceptionFor().with()

多线程与高并发(九):单机压测工具JMH,单机最快MQ - Disruptor原理解析相关推荐

  1. 多线程与高并发(六) 单机压测工具JMH,Disruptor原理解析

    一,JMH Java Microbenchmark Harness,是Java用来做基准测试的工具,测试结果可信度高,用于测试某个方法的性能.13年首发,由JIT开发人员开发,后归于OpenJDK. ...

  2. 多线程和高并发搞不懂?还谈什么面试?(附面试题解析)

    前言: 作为一个 Java开发人员,多线程是一个逃不掉的话题,不管是工作还是面试,但理解起来比较模糊难懂,因为多线程程序在跑起来的时候比较难于观察和跟踪.搞懂多线程并发知识,可以在面试的时候和周围人拉 ...

  3. 基准测试工具(压测工具):wrk---高并发、损耗低,安装简单 (一)

    基准测试工具:Wrk初识   最近和同事聊起常用的一些压测工具,谈到了Apache ab.阿里云的PTS.Jmeter.Locust以及wrk各自的一些优缺点和适用的场景类型. 这篇博客,简单介绍下H ...

  4. 多线程导出excel高并发_大牛带你深入java多线程与高并发:JMH与Disruptor,确定能学会?...

    前言 今天我们讲两个内容,第一个是JMH,第二个是Disruptor.这两个内容是给大家做更进一步的这种多线程和高并发的一些专业上的处理.生产环境之中我们很可能不自己定义消息队列,而是使用 Disru ...

  5. 【腾讯优测干货分享】从压测工具谈并发、压力、吞吐量

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d914e07b7fc1c26a0cf7c 前言 随着部门业务的拓展,我们有 ...

  6. 多线程与高并发基础一(超发--多线程悲观锁,乐观锁、类数据库悲观锁乐观锁)

    PS:看完文章后对自己以前所做过的并发和锁机制有了深入原理的了解. 知其然和知其所以然! 遂以记之! 关键词: 线程,同步,单例,高并发,高访问,死锁 一.大规模并发带来的挑战 在过去的工作中,我曾经 ...

  7. 如何掌握java多线程,高并发,大数据方面的技能?

    https://www.zhihu.com/question/27575123 如何掌握java多线程,高并发,大数据方面的技能? 因为想进入互联网公司,然后发现互联网类型的公司问的主要问题都离不开这 ...

  8. 早知道早幸福——从压测工具谈并发、压力、吞吐量

    目前腾讯WeTest服务器性能测试已经正式对外开放, 点击 链接:http://wetest.qq.com/gaps/ 立即体验! 导语   这篇文章其实憋了很久,最初仅仅是对吞吐量计算的个人兴趣研究 ...

  9. java多线程实例_多线程&高并发(全网最新:面试题+导图+笔记)面试手稳心不慌...

    前言 当你开始开始去跳槽面试的时候,明明只是一份15K的工作,却问你会不会多线程,懂不懂高并发,火箭造得让你猝及不防,结果就是凉凉:现如今市场,多线程.高并发编程.分布式.负载均衡.集群等可以说是现在 ...

最新文章

  1. Elasticsearch全文检索对比:match、match_phrase、wildcard
  2. printf输出颜色和ANSI控制码(高亮,下划线,闪烁,光标位置,清屏等)
  3. 关掉ajax 的异步,asp.net ajax 取消异步回送
  4. Android-ndk编译osgdb_3ds静态库
  5. 文献记录(part42)--An end-to-end framework for unconstrained monocular 3D hand pose estimation
  6. C#中的thread和task之Task
  7. 借助Apache Hadoop大规模扩展Apache Solr实时实时索引
  8. structs2之多文件上传
  9. bootstrap1
  10. c语言中的函数可变参数列表相关的三个宏
  11. HALCON 21.11:深度学习笔记---Data(数据)(3)
  12. 计算机小白学生物信息的难度,基因表达数据分析,对于还是分子生物学小白的我来说太难了。。。...
  13. Oracle 数据脱敏
  14. windows7修复计算机在哪里找,Windows7系统修复方法大全
  15. Shiro小白新手入门教程,一看就会
  16. PS教程!手把手教你绘制3个效果酷炫的GIF动画效果
  17. Could not transfer artifact (https://repo.maven.apache.org/maven2): Received fatal alert: protocol_v
  18. TrafficMonitorr网速流量监控/CPU内存率查看工具
  19. 3D图形学(一):三维几何学基础(1):三维坐标系
  20. 应急通信指挥调度系统|智慧消防指挥中心

热门文章

  1. CodeForces - 91B Queue(单调队列+二分)
  2. HihoCoder - 1831 - 80 Days(暴力)
  3. HDU2896(病毒侵袭--AC自动机)
  4. mannachar(马拉车)求最长回文子串
  5. 3_1 StrategyMode.cpp 策略模式
  6. C++使用ADO存取图片
  7. 标准模板库(STL)学习指南之set集合
  8. Android OpenSL ES 对象结构
  9. 如何替公司省下数千万勒索费用
  10. ElasticSearch探索之路(五)集群与分片:选举、动态更新、近实时搜索、事务日志、段合并