ZMQ官方介绍inproc是进程内方式进行消息处理,效率更好。
下面写一个demo程序,分别使用tcp和inproc协议发送和接收10万/100万条数据,对比发送耗时、接收耗时、发送前和接收后的耗时,进行对比。
测试代码
package org.zmq.tcp;
import org.zeromq.ZMQ;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ZMQPushPullExample {
public static final int TEST_MESSAGE_COUNT = 100000;
private static long beginSendTime;
public static void main(String[] args) {
final ZMQPushPullExample zmqPushPullExample = new ZMQPushPullExample();
zmqPushPullExample.zmqStart("inproc://example");
zmqPushPullExample.zmqStart("tcp://127.0.0.1:8888");
delay(2000);
System.out.println("=====================================上面预热=====================================");
zmqPushPullExample.zmqStart("inproc://example");
System.out.println("=====================================分隔符=====================================");
zmqPushPullExample.zmqStart("tcp://127.0.0.1:8888");
}
private void zmqStart(String addr) {
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket pushSocket = context.socket(ZMQ.PUSH);
ZMQ.Socket pullSocket = context.socket(ZMQ.PULL);
pushSocket.bind(addr);
pullSocket.connect(addr);
System.out.printf("ZMQ绑定协议:%s.", addr).println();
Thread thread = new Thread(() -> {
long start = 0;
List<String> list = new ArrayList<>();
for (int i = 0; i < TEST_MESSAGE_COUNT; i++) {
String message = new String(pullSocket.recv());
if (i == 0) {
start = System.currentTimeMillis();
}
list.add(message);
}
long end = System.currentTimeMillis();
final long cost = System.nanoTime() - beginSendTime;
System.out.printf("从接收第一个消息包到第%d个消息包,耗时:%d毫秒", TEST_MESSAGE_COUNT, (end - start)).println();
System.out.printf("从开始发送到接收完毕总耗时:%d毫秒", TimeUnit.NANOSECONDS.toMillis(cost)).println();
});
thread.start();
beginSendTime = System.nanoTime();
long start = System.currentTimeMillis();
for (int i = 0; i < TEST_MESSAGE_COUNT; i++) {
String message = "Message #" + i;
pushSocket.send(message.getBytes(), 0);
}
long end = System.currentTimeMillis();
System.out.printf("Zmq发送%d次,耗时:%d毫秒", TEST_MESSAGE_COUNT, (end - start)).println();
delay(2000L);
pushSocket.close();
pullSocket.close();
context.term();
}
public static void delay(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
10万条数据,输出结果:
ZMQ绑定协议:inproc://example.
Zmq发送100000次,耗时:39毫秒从接收第一个消息包到第100000个消息包,耗时:39毫秒
从开始发送到接收完毕总耗时:39毫秒
ZMQ绑定协议:tcp://127.0.0.1:8888.
Zmq发送100000次,耗时:23毫秒
从接收第一个消息包到第100000个消息包,耗时:25毫秒
从开始发送到接收完毕总耗时:25毫秒
=====================================上面预热=====================================
ZMQ绑定协议:inproc://example.
Zmq发送100000次,耗时:21毫秒
从接收第一个消息包到第100000个消息包,耗时:21毫秒
从开始发送到接收完毕总耗时:21毫秒
=====================================分隔符=====================================
ZMQ绑定协议:tcp://127.0.0.1:8888.
Zmq发送100000次,耗时:23毫秒
从接收第一个消息包到第100000个消息包,耗时:25毫秒
从开始发送到接收完毕总耗时:25毫秒
- 备注:因为是并发打印,可能会出现乱序问题。例如:第二行输出与第三行混在了一次,可以忽略。
100万条数据,输出:
ZMQ绑定协议:inproc://example.
Zmq发送1000000次,耗时:325毫秒
从接收第一个消息包到第1000000个消息包,耗时:325毫秒
从开始发送到接收完毕总耗时:325毫秒
ZMQ绑定协议:tcp://127.0.0.1:8888.
Zmq发送1000000次,耗时:252毫秒
从接收第一个消息包到第1000000个消息包,耗时:251毫秒
从开始发送到接收完毕总耗时:251毫秒
=====================================上面预热=====================================
ZMQ绑定协议:inproc://example.
Zmq发送1000000次,耗时:225毫秒
从接收第一个消息包到第1000000个消息包,耗时:225毫秒
从开始发送到接收完毕总耗时:225毫秒
=====================================分隔符=====================================
ZMQ绑定协议:tcp://127.0.0.1:8888.
Zmq发送1000000次,耗时:266毫秒
从接收第一个消息包到第1000000个消息包,耗时:254毫秒
从开始发送到接收完毕总耗时:266毫秒
Process finished with exit code 0
结论:
- zmq的tpc和inproc的耗时,相差不大,都很高效。但inproc也确实比tcp更高效一些。
- zmq效率很高,100万消息发送耗时250毫秒左右。作为高效的消息队列使用非常试用。线程同步可以使用他,就不要自己做同步了。