DEBUG日记:同样的代码在不同的环境却得出不同的结果。

 案例一:

  由于成员变量的初始化写在了构造方法里,以致于原本每次模型计算都要初始化一次,变成了创建一次对象才初始化一次,一批量的计算才初始化一次。

 现象:在WINDOWS的本地测试类上单次计算调试结果正确,而相同的代码放到LINUX上批量计算结果错误。

刚开始发现Linux上批量计算出来的结果非常离谱,我们首先想到的就是包打错了。我们的代码分为两块,一块是JAVA从数据库取模型的输入参数,然后JAVA调用C++进行模型计算,计算结果返回JAVA再入数据库。我们检查Linux打的包大小和测试环境上的包大小是否一样,结果发现是一样的。接着我们推测是不是只修改了程序的部分内容导致包大小没有明显变化。我们重新打了C++和JAVA的包,发现现象还是一样。本地上单步调试就是和Linux上跑出来的结果不一样。当时我们的测试类只支持单次模型计算而不支持批量计算。我们压根就没有想到是代码的问题,而想的是环境问题和配置问题。因为经过代码比对,我的本地上的代码和打包的代码是完全一致的,我本地上单次计算模型结果都正确,就认为代码是正确的。Linux上不能像本地一样设断点单步调,只好不断的加日志,查日志。然而多进程同时批量计算写的却是同一个日志文件,导致日志是混起来的。那就关掉多余进程只留一个进程,这样日志就不会混了。但是计算量贼大,进程关了只剩1个,每一次全流程计算都耗了大量时间,但是结果就是和本地的不一样,绝不绝望?日志文件很大,且没有把输入参数的主键ID传到C++里,导致我本地上测的模型参数在日志文件里很难定位出来。我坚信我的代码没问题,要不然我在本地上跑出来的结果就不会正确了。查这问题重上午到第二天凌晨,人都傻了,细想每一步有没有可能出错,不断的试验,啥办法都试过了。最后陪加班的组长建议,把本地上的测试类改成和Linux上的流程一致,改成支持批量计算。我依旧认为是环境问题,而不是代码问题,改测试类是浪费时间,时间又很晚了,改代码的欲望十分低落,但还花了点时间把代码改了,不抱希望的地丢了几笔参数跑跑看。他娘的,居然错误复现了。不花两分钟的时间就定位出了问题把它改了。

代码原因,每个计算任务都是跑一批模型输入参数的,但每个任务只创建一次同种类型的模型输入参数对象。我把输入参数的默认值初始化写在了构造方法里,每次计算都要求初始化才行。在构造方法里初始化模型参数的结果就是一批模型参数只被初始化一次,所以跑单笔模型参数是复现不出问题的。

案例二:

 模型参数的组合主键新增了一个"场景"字段,而代码中用HashMap进行缓存的key没改,导致不同"场景"下的模型输入参数不同,但是不同"场景"的计算结果却完全一样。

现象:导致不同"场景"下的模型输入参数不同,但是不同"场景"的计算结果却完全一样。

立马决定要复现问题,単测了一笔模型输入,发现和Linux上跑的结果不一样。首先把测试类改成支持多"场景"。接着在本地准备和Linux上测试条件,这是一个繁琐的过程...最后由于测试条件不是完全一致,计算结果本地和Linux上跑的结果不一样,但这并不是问题,因为Bug现象被成功复现了,所有不同“场景”下取的参数不同,结果却全部一样。

最后发现是缓存中的Key值没有加上"场景"字段,Key依旧是原来的id主键,导致取的关联参数都是第一个相同id模型参数的关联参数。所以计算的结果都是第一个同id的模型参数的结果。

猜你喜欢

转载自blog.csdn.net/superSmart_Dong/article/details/106308908