代码高效性和健壮性的权衡

简介:

当时CLIENT-SERVER的通讯封包格式有两种方案

a. 以7E为开头和结尾, PAYLOAD中所有7E的字节, 都在其后扩展一个BYTE, 写为7E, 7D, (称为转义). 封包中不带CHECKSUM, CRC等校验用的字段

b. 以7E为开头和结尾, 带一个CHECKSUM字段, PAYLOAD中不进行7E->7E 7D的转义.

几个同事就这个通信封包格式, 采用方案一或方案二, 开会激烈讨论了个把小时。
我原先反对转义方案的出发点比较模糊, 只是觉得原先转义的方案"不优雅"; 后来才想清楚了不优雅的"本质"在哪里.

 

所有的代码, 可以在抽象意义上分作两大块, 两者的着重点是不同的.

(1) 正常运行的代码. 首要追求高效性, 
    这个"高效性"如果从逻辑的角度来解释, 那么一方面是"高效"地对正确的数据执行正确的算法(方法/策略), 另一方面是"高效"地找出异常, 然后丢给异常处理代码去处理.

(2) 处理异常的代码. 首要追求健壮性. 
    就是程序必须能从异常中自我恢复. 由于代码多数时间跑的是"正常"逻辑, 少数情况下才不得不处理"异常", 所以"异常"处理的代码中, 首要任务是健壮, 跑不死, 而高效性则是次要的.

 

那么回到转义的策略上来看,原先的7E -> 7E 7D, 使得装包和拆包的时候, 时间上都必须挨字节扫描过去, 空间上必须另开一块内存, 这些"不优雅"的工作是为了应对网络传输时包数据丢失. 包数据丢失是一个异常情况,而转义策略本质上就是不论好包坏包,一棍子打死, 统统要经过转义算法. 用上面的观点解释, 即"为了异常情况下的健壮性,牺牲了正常情况下的高效性".

而用Header + Length + CheckSum + Payload + Tailer的做法, 逻辑上是这样的

复制代码
if  ( 以Length为基础, 得知CheckSum正确 和 Tailer正确)
{
    正确的包,走正常处理流程, 直接把Payload传给上层逻辑处理

else
{
    错误的包,走异常处理流程,挨字节扫描下一个Header, 然后再算length, checksum, tailer等
}
复制代码

这是在上面"正常->高效性 & 异常->健壮性"指导思想下的做法. 那么现在就剩最后一个问题, 计算checksum和转义的工作相比, 哪一个更快? 如果转义处理的效率, 比checksum更高,那么上面的假设就不成立了.

所以我做了个实验, 代码如下

代码

上面这段代码,在SAMSUNG 2442 400MHz的CPU, WM 6.1系统上运行结果是

copy 1024 bytes * 100K times, use 11677 ms
check sum 1024 bytes *100K times,  use 7504 ms

所以, 一个正确的数据包, 经过CHECKSUM计算的时间, 比其经过转义计算的时间要快得多, 仅为其64%.  这是手机上的情况, 服务器上的百分比不太清楚是什么样,但至少有一点是肯定的,就是用CHECKSUM的方案比用转义的方案,在正常逻辑情况下速度更快、内存开销更少。当服务器同时处理十万数量级网络数据包的时候, 性能提升还是比较可观的。

 

这篇文章的重点不在于哪个方案更严谨,或者上面的逻辑对不对,而是在于这么一个思想:

(1) 正常运行的代码. 首要追求高效性,

(2) 处理异常的代码. 首要追求健壮性. 


本文转自Walzer博客园博客,原文链接:http://www.cnblogs.com/walzer/archive/2009/12/14/1623945.html,如需转载请自行联系原作者


相关文章
|
3月前
|
存储 缓存 监控
如何提高数据驱动方式的性能和可维护性?
【10月更文挑战第13天】 本文深入探讨了提高数据驱动方式性能与可维护性的关键方法和策略,包括优化数据结构选择、数据缓存策略、合理的数据更新策略、数据压缩与精简、代码结构优化、测试与监控、版本控制与协作管理、文档化与知识共享、持续优化的意识及结合实际案例分析,旨在为数据驱动的高效和可持续发展提供全面指导。
|
2月前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
77 4
|
2月前
|
缓存 算法 Swift
Swift 应用性能优化的重要性及基本原则,包括理解性能瓶颈、针对性优化和平衡性能与代码质量
本文深入探讨了 Swift 应用性能优化的重要性及基本原则,包括理解性能瓶颈、针对性优化和平衡性能与代码质量。具体介绍了优化数据结构、减少对象创建、合理使用缓存、优化算法和内存管理等技巧,并通过实际案例展示了如何有效提升应用性能和用户体验。
50 3
|
2月前
|
算法 Java 数据处理
提升效率与可读性的双重探索
【10月更文挑战第22天】提升效率与可读性的双重探索
|
3月前
|
存储 缓存 持续交付
后端世界的微妙平衡:性能与可维护性的博弈###
【10月更文挑战第15天】 在软件开发的浩瀚宇宙里,后端开发犹如一颗星辰,既需璀璨夺目以支撑业务辉煌,又得稳若磐石确保系统长青。本文探讨了后端开发中性能优化与代码可维护性之间的微妙平衡,通过实例分析与策略建议,揭示了如何在追求极致速度的同时,保持代码的清晰、可读与易于迭代,实现技术与艺术的和谐共生。我们相信,正如印度圣雄甘地所言:“你必须成为你希望在世界上看到的改变。”开发者在面对复杂系统挑战时,也应主动寻求变革,探索更高效的解决方案。 ###
42 3
|
3月前
|
存储 算法 NoSQL
分布式系统:常见陷阱和复杂性
分布式系统:常见陷阱和复杂性
27 0
|
5月前
|
微服务
软件设计与架构复杂度问题之理解软件复杂性的递增性如何解决
软件设计与架构复杂度问题之理解软件复杂性的递增性如何解决
|
6月前
|
存储 自然语言处理 开发者
通用性与灵活性对大模型的影响
通用性与灵活性对大模型的影响
|
8月前
|
存储 负载均衡 并行计算
实现优雅并行编程:确保正确性与提升性能的关键要素
在程序开发中,并行编程一种利用多个处理器或计算资源同时执行多个任务的编程方式,它能够提高计算效率和性能,是提高计算效率和性能的关键手段,但它也带来了一系列复杂的问题,涉及到任务分解、数据同步、资源分配等诸多复杂问题,稍有不慎就可能导致性能瓶颈、死锁甚至数据不一致等状况。编写优雅的并行程序需要在保证程序正确性的前提下,实现高效的并行计算。那么本文就来探讨一下如何在保证程序正确性的前提下,实现优雅的并行程序,以提升计算效率和性能,包括任务分解、数据同步和资源分配等方面的关键要素,希望能够为读者提供一些有用的指导和启示。
157 2
实现优雅并行编程:确保正确性与提升性能的关键要素
|
8月前
|
程序员
如何成为高质量程序猿与软件质量的十个指标:正确性、健壮性、可靠性、性能、易用性、清晰性、安全性、可扩展性、兼容性和可移植性
如何成为高质量程序猿与软件质量的十个指标:正确性、健壮性、可靠性、性能、易用性、清晰性、安全性、可扩展性、兼容性和可移植性
209 0

热门文章

最新文章