一、编程和优化
在早期的编程中,由于标准的简陋和编译器的限制等,对编程其实有一些限定性的要求。比如在前面的c++优化中提到的将变量的计算从for循环中提取出去,可以降低计算量,提高效率。但随着标准的日益进步和编译器的愈发强大,很多的限定性的技术或者要求已经过时,或者没有了意义。这就需要开发者要与时俱进,紧密跟踪技术的发展,而不能沉迷于一些技巧性的东西沾沾自喜,裹足不前。
在下面会就一些常见的编程优化技术随着技术的迭代已经或者在某个版本淘汰的分析说明,这些技术只是一个典型的分析,可能还有不少的类似的现象,或者在更未来的技术发展中,又会发展出一些新的相关标准将其优化甚至淘汰。
还有一些基于特定场合或特定时期的编程技巧,比如内存对齐的处理,都可能随着技术的不断发展,而统一起来。
二、技术进步
这里以c++相关为例,包括操作系统或者硬件等的相关技术。一般来说,技术的进步分为几类:
1、标准的推进和完善
首先当然要谈一谈c++标准的迭代。举一个特别简单的例子,早期的类成员变量只能在构造函数中进行初始化,而从c++11后可以在声明时直接初始化,而后的标准中又提供了列表初始化和结构化绑定初始化。而c++版本不断的稳定推进,使的c++中新标准导致新的应用不断出现,一个最典型的例子就是使用Concepts基本替代了SFINAE技术。
同样,操作系统的不断推进,也引入了大量的新的技术和算法到内核中,使得一些传统的技术被废弃。如果有开发者在Windows上有过SDK的开发经验,就一定会有函数的调用约定的应用实践,在X86的平台上,有标准调用,有C方式调用等等几种而在X64的新系统上,则只有一个快速调用。其它的也还有很多,大家可以自己把在开发中的经验总结一下就会发现这些小的方面的演进还是非常之多的。
2、硬件技术的发展
这个最典型的就是内存的发展,从原来的几十K到现在的几十G,甚至更多。它的直接影响就是操作系统中对内存的分配的变化,最明显的就是大小分配的不同(这也导致了Tmalloc等几种经典的算法分配方式)。另外CPU的发展,也使得缓存的大小和层级发生了变化,不同的调度算法也不断的产生。还有一个比较明显的就是CPU的多核心出现,导致并行编程技术开始流行。不同的CPU核心与不同的内存的处理也相应的有了很大的变化。比如NUMA架构以及并行算法和并行调度的不断的发展。
IO存储中,网卡也是如此,巨大的网络通信需求,导致了网卡性能的不断增加,同时导致了一些新技术如BYPASS和网络卸载技术的不断涌现。而新型硬盘技术的出现,已经在某些场合出现了硬盘与内存融合的趋势,这对未来的编程可能影响极大。
其它还有很多,如显卡的进步,PCIE总线技术的进步,林林总总,不一而足。
3、新技术的出现
新技术包括算法和数据结构也包括相关的框架(库)等。名气比较大的比如谷歌的分布式三论文引出的分布式大数据处理算法,这是分布式技术的一个重要的里程碑。而基础的数据结构里,跳表(SkipList)做一种新的数据结构在分布式的文件系统中体现中了很好的应用价值。
这样的例子,在互联网发展的黄金二十年中,比比皆是。特别是在AI和智能汽车快速发展的今年,更是如此。
更令人期待的是AI的推进,很有可能导致编程模式的巨大的改变,这很可能是一种完全颠覆式的革命,但这种革命的出现在什么时候,还不敢断言。
三、影响和演进
AI对编程以及编译等的发展,虽然目前来看影响甚微,可以认为是一种未来的趋势。但上面阐述的三个方面的变化,已经导致了一些常见技术的落后,下面试举几个例子,大家可以自行再加以补充:
1、网络编程的惊群问题
在前面分析过惊群的问题,也提到过包括Nginx的锁限制等待解决方式。但是Accept的惊群Linux2.6内核已经处理,而epoll的惊群问题在Linux4.5也通过惊群EPOLLEXCLUSIVE进行了解决。那么可以预见到的是,这方面的处理已经勿需在设计中加以考虑了。
2、condition_variable的假唤醒问题
大家都看过陈硕大牛的条件变量假唤醒的文章,在POSIX库的编程中,需要增加一个bool变量,循环判断处理(有兴趣可以在网上搜一下相关资料)。但在新的c++标准中,可以通过增加谓词动作来处理这一现象,虽然处理未必很优雅,但至少可以解决大部分的问题。
3、最新的HTTP3和QUIC
这两个技术非常有用,推荐大家可以好好的学习一下。TCP太重了,QUIC就会出现来解决这个重。
4、高并发大数据量的网络处理技术
一般来说,这种技术都涉及到BYPASS和DIRECT技术。比如常见的DPDK,XDP,零拷贝等。还有一些新的如IO_URING高性能异步IO架构等等。
5、C++的并行算法
这个在前面提到过很多次,c++新的标准中提供了大量的并行算法实现,如find等。另外还有一些并行库(如TBB,OMP等等),大家都可以学习使用。
6、线程和进程的数量及内存空间
在32位架构时,可能一些线程(进程)的创建数量会有所限制,如Linux中最大进程数为4090,但在新的64位的情况下,这就不对了。同样,一些基于内核处理的相关资源处理,在X64位处理器上都有很大的差距。
7、编译器的优化
这个相当明显的是在处理一些整数运算时,不必再拘泥以前的什么除法慢,乘法快,加法更快的编写代码的方式,现代的编译器已经完全可以自动进行优化,哪种快用哪种。当然目前浮点的运算还是需要一些小技巧,不过再过几年可能就和整数一致了。
另外如果函数满足内联,编译器很可能自动将未内联函数变成内联,加快访问的速度。另外一些常量计算,这都是比较常用的编译器优化技术。
硬件是根本,软件是精神,二者互相制约互相推进。但是不管二者哪一种出现大的技术变化,都会对原有的编程方式有着巨大的影响。看看这些年来的软件开发模式的发展和代码编写的优化的演进,都会明白。时代在快速发展,技术在快速的更新。新陈代谢是自然规律,这个规律当然也适用于计算机的技术发展。
四、总结
与时俱进,不断用发展的眼光看待和解决问题。掌握技术发展的规律并不断的跟进,有可能的话甚至参与到技术的创新中去,这才是一个开发者应该具备的基本认知。其实无论任何技术都是如此,最终发展成为一个哲学问题。与诸君共勉!