刚刚在我的Corei5 2.8GHz上测试了Java的延迟,只有单字节发送/接收,刚刚生成了2个Java进程,而没有为特定的CPU内核分配任务集:
TCP - 25 microseconds
Named pipes - 15 microseconds
现在显式指定核心掩码,如 taskset 1 java Srv 或 taskset 2 java Cli:
TCP, same cores: 30 microseconds
TCP, explicit different cores: 22 microseconds
Named pipes, same core: 4-5 microseconds !!!!
Named pipes, taskset different cores: 7-8 microseconds !!!!
所以
TCP overhead is visible
scheduling overhead (or core caches?) is also the culprit
同时,Thread.sleep(0)(如strace所示,它会导致执行单个sched_yield()Linux内核调用)需要0.3微秒 - 因此,调度到单核的命名管道仍然有很多开销
一些共享内存测量:2009 年 9 月 14 日 – Solace Systems 今天宣布,其统一消息平台 API 可以使用共享内存传输实现小于 700 纳秒的平均延迟。http://solacesystems.com/news/fastest-ipc-messaging/
PS - 第二天尝试以内存映射文件的形式共享内存,如果忙于等待是可以接受的,我们可以将延迟降低到0.3微秒,以便使用如下代码传递单个字节:
MappedByteBuffer mem =
new RandomAccessFile("/tmp/mapped.txt", "rw").getChannel()
.map(FileChannel.MapMode.READ_WRITE, 0, 1);
while(true){
while(mem.get(0)!=5) Thread.sleep(0); // waiting for client request
mem.put(0, (byte)10); // sending the reply
}
注意:需要 Thread.sleep(0),以便 2 个进程可以看到彼此的更改(我还不知道另一种方法)。如果 2 个进程强制使用任务集连接到同一内核,则延迟将变为 1.5 微秒 - 这是上下文切换延迟
P.P.S - 0.3微秒是一个不错的数字!以下代码正好需要 0.1 微秒,同时仅执行基元字符串串联:
int j=123456789;
String ret = "my-record-key-" + j + "-in-db";
P.P.P.S - 希望这不会太偏离主题,但最终我尝试将Thread.sleep(0)替换为递增静态易失性int变量(JVM在这样做时碰巧刷新CPU缓存)并获得 - 记录!- 72纳秒延迟的Java到Java进程通信!
然而,当强制使用相同的CPU内核时,挥发性增量JVM永远不会相互产生控制权,从而产生恰好10毫秒的延迟 - Linux时间量似乎是5ms...因此,只有当有备用内核时才应使用此选项 - 否则 sleep(0) 更安全。