4.2)代码调优。从我的经验上来讲,代码上的调优有下面这几点:
- 字符串操作。这是最费系统性能的事了,无论是strcpy, strcat仍是strlen,最需要注意的是字符串子串匹配。所以,能用整型最好用整型。举几个例子,第一个例子是N年前做银行的时候,我的同事喜欢把日期存成字符串(如:2012-05-29 08:30:02),我勒个去,一个select where between语句相当耗时。另外一个例子是,我以前有个同事把一些状态码用字符串来措置,他的来由是,这样可以在界面上直接显示,后来性能调优的时候,我把这些状态码全改成整型,然后用位操作查状态,因为有一个每秒钟被挪用了150K次的函数里面有三处需要查抄状态,颠末改良以后,整个系统的性能上升了30%左右。还有一个例子是,我以前从事的某个产品编程规范中有一条是要在每个函数中把函数名定义出来,如:const char fname[]="functionName()", 这是为了好打日志,可是为什么不声明成 static类型的呢?
- 多线程调优。有人说,thread is evil,这个对系统性能在某些时候是个问题。因为多线程瓶颈就在于互斥和同步的锁上,以及线程上下文切换的本钱,怎么样的少用锁或不消锁是底子(比如:多版本并发节制(MVCC)在散布式系统中的应用 中说的乐不雅锁可以解决性能问题),别的,还有读写锁也可以解决年夜大都是读操作的并发的性能问题。这里多说一点在C++中,我们可能会使用线程平安的智能指针AutoPtr或是别的一些容器,只要是线程平安的,其不管三七二十一都要上锁,上锁是个本钱很高的操作,使用AutoPtr会让我们的系统性能下降得很快,如果你可以包管不会有线程并提问题,那么你应该不要用AutoPtr。我记得我上次我们同事去失落智能指针的引用计数,让系统性能提升了50%以上。对Java对象的引用计数,如果我猜的没错的话,处处都是锁,所以,Java的性能问题一直是个问题。别的,线程不是越多越好,线程间的调剂和上下文切换也是很夸大的事,尽可能的在一个线程里干,尽可能的不要同步线程。这会让你有很多的性能。
- 内存分派。不要小观点度的内存分派。malloc/realloc/calloc这样的系统调很是耗时,尤其是当内存呈现碎片的时候。我以前的公司出过这样一个问题——在用户的站点上,我们的法度有一天不响应了,用GDB跟进去一看,系统hang在了malloc操作上,20秒都没有返回,重启一些系统就好了。这就是内存碎片的问题。这就是为什么很多人埋怨STL有严重的内存碎片的问题,因为太多的小内存的分派释放了。有很多人会以为用内存池可以解决这个问题,可是实际上他们只是重新发现了Runtime-C或操作系统的内存办理机制,完全于事无补。当然解决内存碎片的问题仍是通过内存池,具体来讲是一系列不合尺寸的内存池(这个留给年夜家自己去思考)。当然,少进行动态内存分派是最好的。说到内存池就需要说一下池化手艺。比如线程池,毗连池等。池化手艺对一些短作业来讲(如http办事) 相当相当的有效。这项手艺可以削减链接成立,线程成立的开消,从而提高性能。
- 异步操作。我们知道Unix下的文件操作是有block和non-block的体例的,像有些系统挪用也是block式的,如:Socket下的select,Windows下的WaitforObject之类的,如果我们的法度是同步操作,那么会很是影响性能,我们可以改成异步的,可是改成异步的体例会让你的法度变复杂。异步体例一般要通过队列,要注间队列的性能问题,别的,异步下的状态通知通常是个问题,比如消息事件通知体例,有callback体例,等,这些体例同样可能会影响你的性能。可是通常来讲,异步操作会让性能的吞吐率有很年夜提升(Throughput),可是会牺牲系统的响应时间(latency)。这需要业务上支持。
- 语言和代码库。我们要熟悉语言以及所使用的函数库或类库的性能。比如:STL中的很多容器分派了内存后,那怕你删除元素,内存也不会收受领受,其会造成内存泄露的假像,并可能造成内存碎片问题。再如,STL某些容器的size()==0 和 empty()是不一样的,因为,size()是O(n)复杂度,empty()是O(1)的复杂度,这个要小心。Java中的JVM调优需要使用的这些参数:-Xms -Xmx -Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold,还需要注意JVM的GC,GC的霸气年夜家都知道,尤其是full GC(还整理内存碎片),他就像"恐龙特级克赛号"一样,他运行的时候,整个世界的时间都停止了。