目的

  • 记录一下查了几个月的bug,隐藏深,重现难,修复易

案件还原

  • 我现在有装水容器A,容量为5000ml,又有容器B,容量为2000ml,每小时增加100ml,我每点击一次容器B,就把容器B中已有的全部放入A,然后开始收集,如果不能全部放入A,那么能放多少就放多少,剩下的还留在B,然后B继续增涨,这差不多就是背景。
    bug就是,在你点击B的时候,偶尔有一次只能放部分到A去,实际上A能容纳全部B,真的很难重现,比如这上线一个月,我收了几百次了,一次都没出现,有同事一天就出现两次,而且大家都是在手机上出现的,电脑上跑从来没出现过,本来我都摆着不影响的心态,说随缘了,能找到重现方式就修。

发现

  • 白天无意间发现有一次点击收钱没收上来,A也不满,然后看日志,还原代码,终于确定了原因.

原因

为了维护整数,减少误差,如果计算出来B中容量为浮点数,我们向下取整且把收集时间修(小数部分的时间不算)。所以,在点击收集的时候,如果我们计算出来只能收集0,那么后面的操作就是多余的了,后面的操作有:

  • 修改A的数据并写入数据库
  • 计算浮点数时间
  • 修改收集时间并写入数据库

因为收集0的话,收集时间也不用更新,就上次收集时间就可以,A的数据也不用修改。所以我们可以判断如果收集为0时直接跳过后面的操作以提升效率.
然而就是这个判断,导致了这种难以重现的bug,因为重现步骤比较复杂,大概是:
1) 许久不点击,一计算B就能填满
2) 多次计算B但不收进A
3) 收进A
看似简单的三点,其实中第1点很容易满足,第二点的触发条件很不惹人注意,也就是因为这点导致没法重现bug,因为这需要多次被动更新B容器才能触发,比如被打改变善恶值,升级主城(B的容量),这类被动更新B的值而不收进A,

解决

  • 计算之前先判断B容器是否已满,如果已满,需要修改收集时间..

留言

2016-05-10