帮客户做网站图片被告侵权,怎么自创公众号,建网站要多少钱用自己的服务器,媒体软文发稿上一篇《主题匹配》入选CSDN的区块链领域内容榜#xff0c;最早我看到的时候是排行榜34名#xff0c;写这篇文章的时候已经落到了46名。虽然我没有觉得和区域链有什么关系#xff0c;估计入选的原因是那篇文章涉及到几个算法吧。
在整个高性能服务系列中#xff0c;我很少…上一篇《主题匹配》入选CSDN的区块链领域内容榜最早我看到的时候是排行榜34名写这篇文章的时候已经落到了46名。虽然我没有觉得和区域链有什么关系估计入选的原因是那篇文章涉及到几个算法吧。
在整个高性能服务系列中我很少提及算法倒不是说和算法没有关系确切地说性能本身是很难脱离算法的。一个原因是算法涉及的内容过于庞杂见《算法导论》和高纳德的《计算机程序设计艺术》另外一个原因性能涉及到的算法并不会太多反而是追求简单加上系统级别的加成。
我们在总结高性能服务系列的核心关键是减少等待时间而尽可能让CPU有效的跑满重点提示是有效的CPU时间。排除显而易见的网络IO、磁盘IO或者其他慢速服务以及代码BUG导致死锁等。
我们假设一切都是正常的没有低级错误那么影响性能的几个因素在之前几个篇章都提到过这里做下总结。
一、锁互斥
这个不需要太多解释锁互斥对性能的影响有两个1、临界区资源只能被一个线程访问其他线程等待导致的性能损失2、等待线程被系统调度切换出执行区间再次进入可执行状态需要重新加载内存。
为了降低锁互斥导致的等待时间就要缩小临界区使得进出临界区的执行时间尽可能的小。然后再加上自旋锁使得等待线程不需要被切换让出CPU执行时间。
或者更干脆地采用无锁数据结构避免锁互斥标本兼治。但无锁数据结构极为复杂要编写一个正确的无锁数据结构殊为不易性价比太低。
如果从架构设计上去减少需要被互斥共享的临界区也是个不错的解决方案从理论上讲是可行的。
二、系统调用
系统调用并不像锁那样容易理解因为调用系统API简单而自然。一般不会注意到一个简单的系统调用需要从用户空间切换到系统空间要经过多个调用链。
我们之前提到过linux的futex调用就是尽量将锁停留在用户空间除非迫不得已才会进行系统调用。windows下也有类似的API。
三等待唤醒
有了等待也同样有唤醒比如条件变量windows和Linux下都有。使用条件变量就会涉及到互斥锁见第一节。条件变量和信号量唤醒机制都会出现虚假唤醒和唤醒丢失。虚假唤醒比如惊群效应最多损失性能而唤醒丢失就比较严重了不单是损失性能甚至导致程序错误。唤醒丢失在条件变量时还特别容易出现需要警惕。windows下的事件Event算是一种特殊的信号量不单独论述。
四、内存分配
内存分配所需要的时间也很容易被忽视。考察那些高性能软件源码大部分都会自己定制一个内存分配器或者引入第三方tcmalloc和jemalloc。传统的ptmalloc分配小块内存的代价比较大远不如tcmalloc和jemalloc效果好ptmalloc2已经做了不少优化。 内存分配之所以代价比较大有这么几个方面。1、内存和地址空间是全局因此在分配时存在互斥的。2、小内存分配和释放是基本操作调用频繁所以对性能的影响很明显。
要自己定制一个内存分配器代价比较大还不如tcmalloc和jemalloc但在一些特殊场景下比如类似流水线的场景就容易实现也值得去定制一个内存分配器。
五、内存刷新
内存一致性协议导致的等待因为是纳秒级别的基本被忽视。只有用到原子操作追求高性能的时候才会被重视。题外话用到原子操作时必须特别注意到内存屏障。c11引入了原子std::memory_order集成了内存屏障因此需要理解每个memory_order的含义。