java低延迟可能的手段【yetdone】

-java

堆内对象池 启用nocleaner堆外内存,增大新生代 精确控制gc次数

把程序写简单,编译期能干的事情就不在运行时干;避免用不必要的virutal function

关注java c的同一段逻辑的cpu cycle 和切换,jvm背地里会干的一些事情

contiguous 相邻内存块,尽量让可能被同时使用的数据挨在一起(CPU缓存空间局限性

数据要分两种,一种从交易所发过来的市场数据,流量很大,另一种是系统向交易所发出的交易指令,相比前者流量很小,这两种数据需要在不同的TCP/IP连接里传输。

避免阻塞,优先轮训,甚至避免超线程(同一个核心上两个线程对缓存行的访问是串行化的)甚至多线程(避免上下文切换);

数据无需编码解码,可以直接顺序从内存读取,直接可以在网络上收发(避免堆内内存反序列化,直接读写直接内存甚至内核内存,减少拷贝

修改jvm 

 

-内存

用memory pool,用lock free data structure (Intel TBB),避免kernel call. 善用cache。

限制动态分配内存,当堆空间不足时会调用sbrk(),当分配内存很大时会调用mmap(),这些都是系统调用,而且新分配的内存被first touch时也要过很久才能准备好(缓存里没有);一次随机内存访问花费的时间和顺序访问对于CPU(CPU缓存空间局限性来说花费的时间相差两个数量级

能在cache里面存下data和instructions,就不用access main memory,能在registers里面存下,就不要access cache

 

-网络协议
tcp协议栈优化,去除复杂网络可靠性冗余

select ack / syn捎带报文
udp报单 tcp确认回报
禁用nagle,或禁用/修改delay ack时间
增加滑动窗口大小,根据实际流量调优
tcp慢启动优化
频繁小包ack导致高频系统调用和上下文切换
udp包控制在mtu 1472字节-局域网,548字节-互联网,不要ip层分片
tls 1.3椭圆曲线代替rsa
quic ,kcp等可靠udp协议,kcp用带宽空间换时间

走专线,缩短数据链路层,定制mtu

用户态tcp协议栈,减少拷贝

 

 

-内核

其实就是在数据,比如市场信息,进入cpu之前(当然那种fpga进,fpga出的特殊解决方案除外),尽量减少数据拷贝以及context switches

上下文切换是非常耗时的,其中固定的消耗包括(cpu流水线被冲掉、各种寄存器需要被保存和恢复、内核中的调度算法要被执行),此外,缓存很有可能出现大量miss

指定cpu affinity时考虑LLC缓存(同核的两个超线程是共享L1,同cpu的两个核是共享L3,不同NUMA核是通过QPI总线);会被多个核同时读写的数据按照缓存行对齐(避免false sharing)。

使用带有内核bypass功能的网卡。每个进程或者线程都独占一个cpu核(!=CPU亲和,有点像CPU隔离,某个CPU就干这个事不响应中断,防止缓存被刷)【isolcpus和irqbalance的细节见注释3】,并且不停地轮询,用以保证快速响应。尽量避免任何可能导致阻塞的事件(如mutex),某些注定很慢的活动(比如把log写到磁盘上)应该被独立出来放到别的cpu上,不能影响主线程(不要切换,不要系统调用)。

要做到低延时首先确保最少的线程切换一般通过设置CPU亲和性实现,尽量减少中断一般采用内核旁路UIO实现为避免数据拷贝一般使用用户态协议栈,kernel bypass

cpu isolation

 



 

https://www.zhihu.com/question/23185359?share_code=rvLR1N3eBoB3&utm_campaign=Sharon&utm_content=group2_supplementQuestions&utm_psn=1949103301565068316

 

 

 

-其他

这台机器有2个NUMA结点,CPU型号是E5 2643 v4(3.4GHz 6核)。所有的测试都是用rdtsc指令来测量时间,Intel官网上有一篇pdf文档[Gabriele Paoloni, 2010],讲述了如何精准地测量时间(要用cpuid来同步)。我自己做的性能测试的结果会写成“100(sd20)ns”的形式,代表平均值是100ns,标准差是20ns。
 
架构设计上分通道,需要高频和不需要高频的


posted on 2025-09-06 23:24  silyvin  阅读(17)  评论(0)    收藏  举报