- 字符串使用intern方法可以节约内存,但是需要注意不要太多,太多会导致young gc耗时缓慢增高
2.慎用正则表达式,如果要使用缓存Pattern,尽量不使用内部使用了正则表达式少的方法,比如string的split方法 -
linkedList用for循环遍历比arrayList慢,需要用迭代器。
4.几款性能测试工具
image.png
5.高并发IO场景:a.使用缓冲区优化读写操作。b.使用directBuffer避免内存拷贝,c.避免阻塞,优化IO操作,比如使用NIO
6.避免使用java序列化:没法跨语言,序列化后流太大,易被攻击,序列化性能差
7.避免使用深拷贝,使用map
8.优化rpc通信:a.选择合适的通信协议,可靠使用tcp,追求极致性能用udp。b.使用单一长连接,规避频繁创建和销毁连接。c.优化socket通信,比如使用netty:使用非阻塞io,高效的reactor模型,零拷贝。d.量身定制报文格式
9.优化synchronize
image.png
10.lock锁优化:a.读写锁,读读不阻塞,两把锁(读和写)一个状态高16代表读低16位代表写。b.读很多写很少,读写锁容易造成写饥饿,使用stampedlock
11.优化cpu上下文切换:竞争锁优化:持有时间,锁粒度,非阻塞乐观锁替换悲观锁。wait/notify优化:使用condtion的await和sign。合理设置线程池大小
12.不同场景最优容器
image.png - 协程优化IO操作
a.java在linux操作系统采用的是用户线程+轻量级线程,一个用户线程映射一个内核线程。由于线程是通过内核调度,从一个线程切换到另外一个线程涉及上下文切换。
b.而Go语言使用的是N:M线程模式实现调度器,在N个内核线程上调度M个协程,协程的上下文切换是在用户态由调度器完成,代价很小了。
c.协程并不是取代线程, 而且抽象于线程之上, 线程是被分割的CPU资源, 协程是组织好的代码流程, 协程需要线程来承载运行, 线程是协程的资源。
d.协程是一种用户态的轻量级线程,协程的调度完全由用户控制。从技术的角度来说,“协程就是你可以暂停执行的函数”。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
网友评论