说明 规范与建议以Google代码规范为基础, 以Effective系列等作为补充(去掉了重合的, 过时的, 基本可以省略的内容) Google代码规范的注释及格式等部分考虑使用cpplint工具来完成 版本: 1.0.0 最后更新: 2021-09-01 13:01 作者: orient 主页: http://orientye.com github: https://github.com/orientye 微信公众号: 深入理解计算机系统 Google代码规范 https://google.github.io/styleguide/cppguide.html 中文版: https://google-styleguide.readthedocs.io/zh_CN/latest/google-cpp-styleguide/contents.html (注意:有些并不准确) Effective C++ 3rd Item 04. 确定对象被使用前已被初始化 Item 07. 为多态基类声明virtual析构函数 Item 09. 绝不在构造函数和析构函数中调用virtual函数 Item 11. operator=处理好自我赋值 Item 12. 复制对象时勿忘其每一个成分 Item 16. 成对使用new和delete要采取相同形式 Item 21. 绝不返回局部变量(local stack)的指针或引用 Item 26. 尽可能延后变量定义的出现时间 Item 28. 避免返回handles(包括引用指针迭代器)指向对象内部…
Category: 语言
Beautiful Code — go sort
Beautiful Code — go sort sort: optimize average calculation in symMerge and doPivot. Change code of the form `i + (j-i)/2` to `int(uint(i+j) >> 1)`. The optimized average calculation uses fewer instructions to calculate the average without overflowing at the addition. Analogous to https://golang.org/cl/36332. name old time/op new time/op delta StableString1K-4 49.6µs ± 3% 49.1µs…
C++线程安全分析
C++线程安全分析 除了通过code review或者test来检测线程安全,有没有其它更好的办法? 答案是存在的,通过clang即可以进行这种检测,编译器对存在的线程安全问题会给出警告。 这种分析方法由Google开发,已经被Google大规模应用,参考 https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/42958.pdf 示例example.cpp: 通过然后指定-Wthread-safety编译选项,即clang -c -Wthread-safety example.cpp命令编译即可以给出警告。 更多细节可以参考: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
基于java nio的server设计
最近由于业务需要,写了一个 java server用来与我们的游戏服务器实现交互。 server只实现了最基本的功能: 维护多个长连接,发送与接收消息;连接建立及断开(主动与被动)。 在实现的过程中,最有意思的是java nio里的buffer,但我认为这是一个失败的设计。 java nio buffer三个主要的属性,position, limit, capacity. 通常来讲,传统的ringbuffer都会有一个read index和write index, 但buffer nio将两者统一为postion,然后弄出了读写模式切换的概念。 当从buffer里取出数据,即buffer.getXXX或者channel.write(buffer), 当往buffer里放入数据,即buffer.putXX或者channel.read(buffer), 的前后,经常要考虑模式的切换,比如调用flip,这样的设计增加了复杂性,对库的使用者带来困难(笔者才疏学浅,一直疑惑他们为什么这么设计,求高人指教),这本质上是因为position属性既要当作readindex来使用,又要当作writeindex来使用。 另外一点就是由于postion的大小不能超过limit和capacity, 导致使用的过程中经常需要compact, 每次compact会导致额外的内存拷贝;传统的ringbuffer会在writeindex < readindex在的时候才可能涉及到额外内存的拷贝。 也难怪,netty里抛弃了这种设计。
stl之争
以前,是否使用STL是有争议的,因此很多公司都实现了自己的一套STL。 其实STL有很多有意思的设计,比如实现了数据结构和算法的分离,这也是STL设计的核心思想。 在实现上,STL源代码也是能够给人一些启发的。比如sort算法的实现(这应该不是STL的开创),sort主要采用快速排序,对于初步有序的短系列,采用插入排序,对于快速排序的极端情况,还可能使用堆排序。 性能方面,STL作为通用库,一般来说效率还是比较高的。但是,在大型游戏领域和内存受限领域,以及由于STL在不同平台上的实现不同,其性能还需要改进。关于这一点,可以参考http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html这篇论文,论文还提供了一个性能对比图。 扩展性上,个人认为,仿函数,适配器还是有比较好的扩展性,Allocator(1998 ISO C++)则争议很大,上述论文和http://www.openstd.org/jtc1/sc22/wg21/docs/papers/2005/n1850.pdf这篇论文有比较详细的解释。 易用性上,STL同样备受争议。这主要表现在: (1)需要对库的实现有相当的理解,由于依赖于模版与泛型,然后又加上C++语言,滥用极可能带来性能的严重损失,难以发现的一些Bug等。 (2)调试的不方便,源码也缺乏文档和注释。 (3)一些局部的瑕疵, 比如缺少像树这种层级结构的容器,比如list的sort函数也违背了数据结构和算法的分离思想。 总而言之,作为通用库,STL还是比较不错的,而在某些对性能要求更高的领域,最好慎用。 对STL的改进和替换方面方面,可以参考: EASTL: EASTL依然沿用STL的基本思想,在实现上改进了STL,是一个性能更高,更易于调试的STL。 Doom3: 完全抛弃了迭代器,是一个比较简单,但是非常实用的STL。