系统调优 陶辉 您所在的位置:网站首页 nginx100讲PDF 系统调优 陶辉

系统调优 陶辉

2023-08-12 18:47| 来源: 网络整理| 查看: 265

CPU

CPU缓存分为数据缓存与指令缓存,对于数据缓存,我们应在循环体中尽量操作同一块内存上的数据,由于缓存是根据CPU Cache Line批量操作数据的,所以顺序地操作连续内存数据时也有性能提升。

对于指令缓存,有规律的条件分支能够让CPU的分支预测发挥作用,进一步提升执行效率(likely())。对于多核系统,如果进程的缓存命中率非常高,则可以考虑绑定CPU来提升缓存命中率。

内存

子线程预分配的内存是64MB(Ptmalloc2中被称为Thread Arena,32位系统下为1MB,64位系统下为64MB)

TCMalloc适用的场景,它对多线程下小内存的分配特别友好。

所以,当应用场景涉及大量的并发线程时,换成TCMalloc库也更有优势!

Ptmalloc2更擅长大内存的分配。

如果主要分配256KB以下的内存,特别是在多线程环境下,应当选择TCMalloc;否则应使用Ptmalloc2,它的通用性更好。

由于每个线程都有独立的栈,所以分配内存时不需要加锁保护,而且栈上对象的尺寸在编译阶段就已经写入可执行文件了,执行效率更高!

所以,当我们分配内存时,如果在满足功能的情况下,可以在栈中分配的话,就选择栈。

哈希:

解决哈希冲突有链接法和开放寻址法,而后者更擅长序列化数据,因此成为我们的首选 。

零拷贝:

零拷贝技术在内核中完成内存拷贝,天然降低了内存拷贝次数。它通过一次系统调用合并了磁盘读取与网络发送两个操作,降低了上下文切换次数。

协程:

线程之间切换,需要走内核态,消耗大

异步编程方式通过非阻塞系统调用和多路复用,把原本属于内核的请求切换能力,放在用户态的代码中执行。这样,不仅减少了每个请求的内存消耗,也降低了切换请求的成本,最终实现了高并发。然而,异步编程违反了代码的内聚性,还需要业务代码关注并发细节,开发成本很高。

所以,协程的高性能,建立在切换必须由用户态代码完成之上,这要求协程生态是完整的,要尽量覆盖常见的组件。

协程参考内核通过CPU寄存器切换线程的方法,在用户态代码中实现了协程的切换,既降低了切换请求的成本,也使得协程中的业务代码不用关注自己何时被挂起,何时被执行。相比异步编程中要维护一堆数据结构表示中间状态,协程直接用代码表示状态,大大提升了开发效率。

锁:

互斥锁能够满足各类功能性要求,特别是被锁住的代码执行时间不可控时,它通过内核执行线程切换及时释放了资源,但它的性能消耗最大。需要注意的是,协程的互斥锁实现原理完全不同,它并不与内核打交道,虽然不能跨线程工作,但效率很高。

如果能够确定被锁住的代码取到锁后很快就能释放,应该使用更高效的自旋锁,它特别适合基于异步编程实现的高并发服务。

如果能区分出读写操作,读写锁就是第一选择,它允许多个读线程同时持有读锁,提高了并发性。读写锁是有倾向性的,读优先锁很高效,但容易让写线程饿死,而写优先锁会优先服务写线程,但对读线程亲和性差一些。还有一种公平读写锁,它通过把等待锁的线程排队,以略微牺牲性能的方式,保证了某种线程不会饿死,通用性更佳。

另外,读写锁既可以使用互斥锁实现,也可以使用自旋锁实现,我们应根据场景来选择合适的实现。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有