WOD代码review结果(重要!)
| 编号 | 问题 | 优先级 | 修改难易程度 |
| 322001 | stringstream对象使用方式不对, 现在是每次使用ss对象都构造一个, 实际上不需要构造一个, 可以通过以下方式优化 static thread_local std::stringstream ss; ss.clear(); ss.str(“”); |
较高 | 简单 工作量比较大 |
| 322002 | 避免C String的使用 底层被频繁调用的库函数, 要避免使用c string当作API 可以将接口改成const std::string&的形式, 减少不必要的拷贝 |
较高 | 简单 |
| 322003 | log库内一条log使用了多个stringstream对象 做了多次拷贝 因为log库使用地方非常多, 所以这个优化很有必要 |
较高 | 简单 |
| 322004 | 消息解码尽量移到网络线程来做, 给主线程足够的时间比例来处理逻辑 现在网络线程只是在做分帧, 应该把解码也放到网络线程内 可以通过两步优化: 第一步先做rsb的缓冲, 只需要增加一个指针成员, 在消息被push到主循环之前调用get_rsb()函数完成解码工作 第二步, 可以在分帧之后直接完成解码, 少一次内存拷贝, 这个修改比较复杂 |
较高 | 第一步简单 第二步较难, 看实际情况, 可以不做 |
| 322005 | 发送尽量从主线程里面挪开 现在发送大部分都是在主线程内完成, 只有Socket缓冲区满了, 才会因为send失败而进入ET模式, 变成异步发送 需要将send的过程从主线程分离, 增加主线程处理逻辑消息的时间比例 做法是弄成asio类似接口的网络库, 或者简单一点的做法就是增加一两个发送线程 |
低 | 比较复杂 |
| 322006 | base_server等依赖改成库/工程级别的依赖 现在这种源码级别的依赖, 会导致编译时间较长 |
低 | 比较简单 |
| 322007 | DBServer派发Command给Worker的Queue, 改成通过Condition variable来通知 而不是通过pull/sleep来做 可以降低系统的消耗, 减少延迟, 提升worker的吞吐量 |
低 | 简单 |
| 322008 | 修改volatile关键字的代码, 换成std::atomicXXX形式 VC下volatile有atomic语义, GCC下没有 |
高 | 简单 但是工作量大 遗留代码很多 |
| 322009 | 传递std::string参数的代码修改成const std::string&或者std::string& 现在代码里面有多处传递std::string参数的函数 虽然拷贝一次, 程序运行没有问题, 但是效率比较低 |
中等 | 简单 |
| 322010 | 传递std::shared_ptr<T>参数的代码改成const std::shared_ptr<T>& 智能指针需要传递const引用 减少不必要的消耗 |
中等 | 简单 |
| 322011 | const错误使用 代码里面有一些传递const参数的代码, 应该编写的时候少敲了一个&符号 参数不能传递const, 要传递就要传递const & 例如void f(const std::string&), 而不能写void f(const std::string) |
高 | 简单 |
| 322012 | 减少malloc/new混用 这个在DB Server内很严重, 可以通过unique_ptr和shared_ptr来减少编写代码的复杂度 |
高 | 简单 |
| 322013 | 生成环境链接jemalloc/tcmalloc 系统内动态内存分配比较频繁, 建议生产环境链接上面两个库 |
低 | 简单 |
| 322014 | 正确使用range-based for for(auto item : items) 这样的代码在服务器内出现多次 这种严格来讲是错误的代码, 要不然写auto&要不然写const auto& 不能直接写auto, 复杂对象会产生一次无效的拷贝, 而且有时候会导致一些很难查询的逻辑BUG |
高 | 简单 要让程序员养成习惯 |
| 322015 | MySQL escape string API修改 现在API是基于c string的, 难以编写逻辑 DBServer内有大量因为escape string写的new/delete 可以通过替换成std::string&来替代, 一方面提高编码的效率, 减少编码心智负担, 一方面还可以提高运行的效率(strtingstream对const char*需要求一次strlen, std::string自带length) |
较高 | 简答 |
| 322016 | .str().data()/.str().c_str() 需要禁止程序员手动调用string的data()函数和c_str()函数 这种编码习惯会导致多拷贝一次对象 服务器内有200+处这样的代码 |
较高 | 简单 |
| 322017 | 数据库表的初始化, 不需要stringstream对象 可以直接写: const char* sql = “create table if not exists `table1`(” “`mail_id` int,” “`exp` int” …… 不需要通过stringstream来拼接 |
低 | 简单 |
| 322018 | LOGI日志级别是不是写错了 现在info级别是5, 是最高级别, 比fatal都高, 这个是不是写错了? |
高 | 简单 |
| 322019 | 逻辑处理有大量的LOGI(rsb.toString())代码 这种代码应该是调试时才用的, 线上环境如果每个逻辑消息都dump出来的话, 服务器应该会扛不住 |
高 | 简单 |
| 322020 | RSB消息的toString()实现有缓冲区溢出风险 该函数内部有一个256字节的栈变量, 通过sprintf来格式化 如果消息过大, 是有可能破坏栈帧 |
非常高 | 简单 |
| 329001 | auto使用导致的拷贝过多 现在很多auto都在做拷贝, 建议查看准确语义增加&, 减少不必要的拷贝 |
低 | 简单 量比较大 |
| 329002 | 禁止逻辑代码里面对json cpp的直接使用 现在对json这两个配置文件的使用, 是直接使用Json::Value对象去做动态的解析, 而不是在服务器启动时解析一次, 然后程序使用解析后的数据 导致技能初始化的时间过长 建议把json一次性解析成程序需要的对象, 而不是简单的映射(程序使用的时候还需要构造一次) |
高 | 中等 |
| 329003 | 技能代码里面对make_shared的过多使用 例如SkillEvent对象内部, 有5个shared_ptr, 一个vector, 可以考虑将该对象内的vector<shared_ptr>改造成C数组, 减少new的次数 |
中 | 简单 但是需要查看代码确定哪些可以修改 |
| 329004 | DBConnection对SQL语句的执行, 是一次性的, 没有考虑云数据库的可用性问题 需要对数据库不可用时做合适的处理(例如等待等), 否则该SQL语句就直接被抛弃了 云数据库在发生故障的时候, 会有短暂的不可用(通常时秒级) |
中 | 简单 |
| 329005 | GameZone上的Cell, 建议做惰性的初始化, 有实体在上面的时候再插入, 而不需要一次性构造一个很大的vector, 可以减少内存的使用 | 低 | 简单 |
| 329006 | GameZone上Cell的单位是不是1米 如果是1米的话, 对象移动的时候, 经常会出入格子; 对象的移动需要经常计算AOI 给服务器造成不必要的负担 |
中 | 中等 |
