【原创】高性能服务器本质论

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CppExplore/article/details/6085403

作者:CppExplore  http://www.cppblog.com/CppExplore/http://blog.csdn.net/cppexplore同步发布
一 服务器分类
从软件性能角度,高性能服务器分:cpu密集型服务器/IO密集型服务器
(1)CPU密集型:该类服务器没有对io的访问/没有同步点,性能瓶颈在于对cpu的充分利用
典型的如转发服务器/代理服务器/协议转换类服务器/分布式总线服务器等。
(2)IO密集型:该类服务器存在对cache/db/硬盘等的同步访问,或者对fcgi/其他服务器等的同步访问
简单说有同步访问点的均归属此类服务器。当前硬件基础下,有同步操作的服务器,性能瓶颈均在同步点的返回快慢上,而非cpu。
二 网络层机制
对上述两类服务器,均需要同样高效的网络层机制。当前高效的网络层也就是大家熟知的iocp/epoll/kqueue/port/dev.poll等,在各个os下使用宿主os推荐的高效网络层机制,任何通过其他机制绕过这些机制的做法都不可能达到最好性能。这里推荐下boost.asio,文档齐全,示例丰富,学习曲线平缓。
三 CPU密集型服务器设计
(1)单进程单线程是改类服务器的本质特征。
整个进程只存在一个线程,所有代码均运行在同一个线程中,均顺序执行,任何地方不需要加锁。由于网络线程的存在,实际上该类程序的唯一线程就是网络线程,以linux为例,就是epoll线程。
在多核情况下,fork和cpu个数相同的进程数并且如果可能使用sched_setaffinity类函数将进程和cpu绑定。以充分利用多核性能。
该类服务器的代表:tuxedo/nginx.
(2)单进程多线程,但多线程均完成同样的功能,彼此之间互不依赖/互不影响 ,这是该类服务器的变体。
单进程单线程无疑是该类服务器最理想最完美的实现。但有时候为了简化部署,简化业务上报,业务自检,统一日志,尤其是统计类日志/配置动态生效等附加功能考虑,不得已牺牲少许性能而将上述“单进程单线程,fork多个充分利用多核”方案改造为“独立多线程充分利用多核”方案。
该方案中,多线程中的各个线程仍然是顺序执行,任何地方不需要加锁,均为独立的网络线程。
相对方案(1), 该方案编程更复杂,而linux下线程调度又不如进程高效,整体看为方便性牺牲了少许性能。
该类服务器的代表:我们的协议转换网关/分布式总线服务器等。
(3)高效算法
优化耗时较多算法/挑选合适容器,完成固定任务,尽量减少cpu的运算量。
(4)错误设计:区分网络线程/业务线程,将业务线程根据业务特点划分各个线程阶段。
对cpu密集型的服务器来说,关键在于充分利用cpu,尽量减少无用代码的执行。引如中间处理线程,意味着引入锁切换/内存复制/更多无效代码,不可否认,在已有协议栈情况下,根据业务特点化分线程可以简化编程。单纯的单一线程意味着更复杂的编码,尤其是涉及到更多中间状态时。
在该场景下,有位牛人,对线程的点评:“线程是给那些不能将程序执行序转换成状态机的笨人用的” 这句话真是再合适不过了。
四 IO密集型服务器设计
(1)网络层多线程,中间线程按照业务特点设定,同步点操作使用多线程
同步点使用多线程是该类服务器的本质特征。在同步操作的返回时间不能由本服务器控制的前提下,本服务器所能做的也就只能是加多线程数,提供同步并发数。线程数的最优配置取决于网络层入口并发数以及同步操作返回的时间。简单划分可以网络线程数=cpu个数/2.同步点线程数还取决于同步操作的代价,若为廉价的cache操作,则可适当增多,若为昂贵的db操作,则要根据可以分配的连接数决定。
(2)减少人为产生的同步点
尽量减少访问其他系统使用同步接口。
(3)优化同步点
根据同步操作的特点优化: 异步/增大缓存/批量等。

五 内存操作/锁机制/内核态用户态切换/日志操作
(1)内存操作
内存申请:减少内存动态分配,推荐tcmalloc
内存复制:CPU密集型,必须的内存复制:(a)网络读:处从内核态复制到用户态,仅1次 (b)网络写:异步内存复制/用户态到内核态 ,仅2次
                    IO密集型,内存复制非关键点。
(2)锁机制 CPU密集型:尽量无锁. IO密集型: 非关键点
(3)内核态用户态切换
两类服务器均相同,尽量减少内核态/用户态互相切换:每次调用系统调用尽可能读取更多字符/仅可能减少不必要的系统调用(去除不必要的调用/通过缓存机制减少调用次数)。
(4)日志操作 略

六 进程vs线程vs协程
进程和线程(略)
协程:和进程/线程这种cpu调度单元不同,它更多是线程内对象之间一种调度理念的优化。协程对象有自己的堆栈,可以通过直接跳转直接转换执行点,减少了内存寻址操作。它特别适合用来优化线程内的某些基础组件,包括:状态机/调停者模式(或者线程内队列)。

在CPU密集型服务器的设计中,说道“线程是给那些不能将程序执行序转换成状态机的笨人用的”,而有了协程,我们有了一种新的简化编程的方法。将协程用于网络层,可以手动实现类似select的功能,用于多对象参与的复杂中间状态,可以简化编程。
但从整体性能角度看,协程则是鸡肋的存在,从几年前出现boost.Coroutine,到现在该项目停止开发,boost引入更多其他方案asio/mpl/statechart,协程一路蹒跚。
七 总结
在当前硬件体系架构下,服务器性能的关键仍然是传统的cpu/io/memory.
cpu密集型的服务器,需要最大限度充分利用所有cpu,以及尽量少的进行内存申请/内存复制。
IO密集型服务器,需要最大限度提高io能力,为达到该目的,可以在非同步线程牺牲对cpu的利用率/牺牲对memory的高效使用,一切为提高io并发能力服务。
八  后记
特别感谢张杰同学代替我编译探测程序代码,让我有时间码点文字。

展开阅读全文

****.NET本质论******

04-04

.net 本质论rn------------------------------------------------------------rn上海 家乐 jia_le@263.netrn------------------------------------------------------------rnrn记者:现在,市场仍然对.net感到困惑。... .net的实质到底是什么?rn盖茨:.net是我们对下一代internet的设想。... 举个简单的例子,rn .net不仅允许你查看自己喜爱的棒球队的时间安排,rn 并且还能够对这个时间安排进一步加以利用。rnrn.net 是什么? 比尔.盖茨地回答真是莫名其妙,这叫什么回答?rn什么叫进一步利用?难道现在地软件技术不能达到吗??rn rn.NET 技术有两个语言:vb.net和C#rnC/C++功能强大,可以完成任何事情,rn但是用来开发应用软件(不是系统软件),rn在RAD时代,已经落后了。rn所以,微软的首要的开发工具VC++rn 在当今时代,开始显得地有点落后和被动,rn如果微软没有发现这个问题,那么rn在未来的几年里,微软就失去了软件行业的开发工具的龙头老大地位,rn当然,微软还有VB,但是,VB被Delphi和C++Builderrn和pb和java 等开发工具显得弱小不堪.rnrn但是微软还有办法,它凭借Windowsrn系统的优势,来使自己继续领导软件业,怎么做呢?rn 一 : 微软对系统进行革新,美名为.net系统 。(用系统升级rn 来领导用户向我看齐,真是个好办法!!)rn 这样,在Windows系统上的开发工具都得要和它来看齐,rn二:微软请来Turbo Pascal和Delphi之父(这个人太厉害了,rn 我怀疑他有中国的九阳神功、葵花宝典什么的。rn 如果你不知道他的 名字,那你应该学习一下语言工具的发展历史)rn 让他带领一群人来开发新的语言C#,专门开发.net 系统的.rn三:做广告宣传。rnrn这样,几乎大家都知道.net了,但是.net的本质是什么呢?rn 盖次的回答你看明白了?呵呵~~~rn rn在研读了VB.net 和C# 后,有了心得:rn 1: VB.net 和 VB 不是一个档次上的工具,rn vb.net 里的语法都和vb的语法,rn 几乎都不一样,我猜可能是这样的原因:rn 在近几年里,由于快速开发RAD的概念和需求增大,rn 对于开发企业应用系统来说, 如果对网络依赖比较大,rn 那么大部分开发者选择java的工具,这样rn 可以轻松实现电子商务什么的.....,rn 如果是数据库管理系统,那么Borland的工具是首选,rn 用过Delphi的人都 迷恋Delphi, 如果还用VB来开发,rn 那么这个人可能是外行了, 所以95年Delphi1.0出来后,rn 越来越多的VB开发者转道了Delphi, 毕竟,只要微软愿意,rn Delphi可以实现任何VC要做的东西。因为win 系统是人家的。rn 虽然VB不断的改善,但先天性因素是改不了的,rn 微软现在推出VB.net,是VB开发者的终点,rn 因为vb.net完全面向对象的语法再也rn 不是vb鼠标点击、写个过程解决问题的开发概念,rn 从侧面说明VB is Killed!rn vb.net语法里的很多的新东西(vb里没有的,所以叫做新东西)rn 在Delphi/java里早都有了, 没有什么新鲜的!rn 2:C# rn 如果java出现的是因为开发者的需要(或者说是社会生产力的需要),rn 那么c#的出现, 我个人认为是微软的需要,rn 在现在的时代,开发工具很多,为了快速实现企业的需要,rn 有谁去用复杂的工具呢? 在很多人看来c/c++是主流,rn 我见过很多的外行人(不是做软件开发的人)看到某某rn 用VC++开发,就禁不止的赞叹:牛人!厉害!呵呵~~rn 其实,VC++是和Borland C++一个时代的产物,rn Boralnd C++ 3.1 在Dos时代,可以说,是一流的,rn 比当时的 Microsoft C++要强的n多倍,rn 以至于微软拼命的去挖Borland的人才....................................rn (如果你喜欢,你去打听 一下,去问问当时的知情人士。)rn 现在RAD盛行, 用VC开发应用软件实在是:别人佩服你,rn 自己在吃苦! 所以现在用VC来做项目的人也不多了,rn 当然也还有人继续用。萝卜白菜,各有所爱嘛!rn 但是微软已经注意到了这个问题,rn 盖次的高明就在这里,看的比人家远!rn 微软发现自己的开发工具(VB/VC)都即将落后,于是就再开发的新的C#rn C# 的面向对象的语法类似Java/Delphi的,rn C#就是从C++分娩出来去靠近Java/Delphi的东西(从语法上讲);rn rn 除了C# 是专门为.net设计的-- 再也看不到它比java/Delphi优秀到那里??!!rn 只要Java 或Delphi 支持.net系统 (被牵着鼻子走),rn 那 C# 没有什么高明之处,毕竟 Delphi 和C# 都是一个娘的孩子!!rn (都是 Anders Hejlsberg 主持设计的),rn 看看C# 的语法就知道类似Object Pascal.rn rn现在真的需要.net呢? 但问题是什么是.net ???? rn .net 的到底是什么,连盖次都说不明白 。rnrn其实是 盖次说的不明白,但他心里明白:rn 恩,这个问题很难回答,因为说白了就是:rn 我们微软要继续做软件业的霸主,我们不想再rn 推出什么Window 2002/ Window 2003/ Window 2004/rn Window 2005 了,因为这样下 去rn 会使用户对我们这样牵着他们鼻子走而感到疲乏和厌倦!!rn 所以我们得改个名字,叫做 .net系统,rn 还有一套.net 开发工具,.net 架构...... 当然,rn 我们会在.net系统里加入一些新的东西,要使整个系统对于rn 人们感到新鲜,譬如把Windows 里的.exe 文件格式变化点,rn 使老的系统程序在我们的.net 就不能执行,rn 这样,人们就必须跟我们走......这样微软还是利润滚滚来。rn 恩。。。但是这样的目的当然不能在广告宣传里,rn 所以大家对.net 就感到 困惑了!非常抱歉。rn ---------------------------------------------------------rnrn以上是 本人在学习了Java/Delphi/C#/VB.net/.net框架 后的心得和体会;rn如有异议,建议你也把Java/Delphi/C#/VB.net/.net框架 学习一下,你就发现rn很多很有意思的问题。rn jia_le: jia_le@263.netrn---------------------------------------------------------- 论坛

没有更多推荐了,返回首页