Docker 增长率同比放缓 37%
关于这一部分的详细讲解,请参见《深入理解操作系统》系列文章。 跨界
孙悟空神通广大,一个跟斗就能从人间跑到天上去骂玉帝老儿,程序员就没有这个本领了。普通程序永远也去不了内核态,只能以通信的方式从用户态往内核态传递信息。操作系统为普通程序员留了一些特定的暗号,这些暗号就和普通函数一样,程序员通过调用这些暗号就能向操作系统请求服务了,这些像普通函数一样的暗号就被称为系统调用,System Call,通过系统调用我们可以让操作系统代替我们完成一些事情,像打开文件、网络通信等等。 用户态
什么是用户态?当CPU执行我们写的“普通”代码(非操作系统、驱动程序员)时就处于用户态,粗糙的划分方法就是除了操作系统之外的代码,就像我们写的HelloWorld程序。用户态就好比“人界”,在用户态我们的代码处处受限,不能直接访问硬件、不能访问特定地址空间,否则神仙(操作系统)直接将你kill掉,这就是著名的Segmentation fault、不能执行特权指令,等等。 对于Java 应用,程序员之间一个认识口口相传: 要看一个Java程序跑的快不快,需要多跑几次;另外,Java程序跑一段时间之后会快起来。速度甚至能赶上 C/C++程序的速度。 如果你问为什么跑一段时间就快了呢? 一般都能听到 「因为JVM会把调用次数多的热方法编译再执行」的答案。
更通俗的话来讲, JVM 会把热方法编译成机器码,执行效率会更高。就像公司或工厂里,对于一项任务,一般老手都比新人更快,因为老手更熟悉嘛。所以招聘要求里你很少会见到指明要新人的,大部分都是要有工作经验的。 执行时间154ms 这里看到,仅仅改变了一行代码,虚函数调用就比普通函数慢了几倍,为什么? 虚函数其实最主要的性能开销在于它阻碍了编译器内联函数和各种函数级别的优化,导致性能开销较大,在普通函数中log(10)会被优化掉,它就只会被计算一次,而如果使用虚函数,log(10)不会被编译器优化,它就会被计算多次。如果代码中使用了更多的虚函数,编译器能优化的代码就越少,性能就越低。 虚函数通常通过虚函数表来实现,在虚表中存储函数指针,实际调用时需要间接访问,这需要多一点时间。 然而这并不是虚函数速度慢的主要原因,真正原因是编译器在编译时通常并不知道它将要调用哪个函数,所以它不能被内联优化和其它很多优化,因此就会增加很多无意义的指令(准备寄存器、调用函数、保存状态等),而且如果虚函数有很多实现方法,那分支预测的成功率也会降低很多,分支预测错误也会导致程序性能下降。 如果你想要写出高性能代码并频繁的调用虚函数,注意如果用其它的方式(例如if-else、switch、函数指针等)来替换虚函数调用并不能根本解决问题,它还有可能会更慢,真正的问题不是虚函数,而是那些不必要的间接调用。 正常的函数调用:
而虚函数调用与此完全不同,唯一的区别就是编译时不知道函数的地址,而是:
通常,使用虚函数没问题,它的性能开销也不大,而且虚函数在面向对象代码中有强大的作用。 但是不能无脑使用虚函数,特别是在性能至关重要的或者底层代码中,而且大项目中使用多态也会导致继承层次很混乱。 那么有什么好方法替代虚函数呢?这里提供几个思路,读者请持续关注,后续会具体讲解:
这几种方法是Michael Spertus大佬介绍的,各有各的优缺点,作者都会用,但什么情况下使用哪个,取决于你自己的判断,这里只是教你了一个工具,什么时候用都取决于你自己。 (编辑:衡水站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |