用一个动态数据的长度去作为while循环的终止条件?什么样的程序员会这么干?您别说,还真让我给遇到了,而且,通过这件事情,让我觉得有些公司做代码审查还是挺重要的,如果不是万不得已,代码审查一定要做,否则就会出现我接下来所说的事情!
程序逻辑
我们公司有个程序员写了一个项目,需要通过程序去监控摄像头前面有没有东西经过,有的话,就需要每隔一段时间去拍一张照片并保存,这个间隔是很短的,直到当摄像头前面的东西超出了摄像头的监控范围,拍摄并保存的逻辑才会终止,直至下一次摄像头前面重新有东西经过,再执行相同的逻辑,周而复始。
拍到照片以后还需要通过视觉算法去进行运算,但运算速度比不上拍照片的速度,所以拍照片和视觉算法我的这位同事使用了两个线程去处理,而问题恰恰也出现在这!
这个项目在交付给客户使用后,客户反馈过来的结果是拍摄到的照片经常丢帧,有时候甚至就只拍了一张照片。
既然客户说有问题,我首先让写这个项目的程序员自查,结果他琢磨半天也没看出问题,于是,就只能让我去看他写的代码了。我一边看代码,一边问同事相关逻辑,后来总算把他的代码逻辑给理顺了。
他的逻辑大致是这样:
当程序检测到摄像头前面有东西在动的时候,会记录一个信号,当这个东西离开摄像头视野的时候也会记录一个信号。他在两个信号之间使用了一个异步while循环来重复获取摄像头当前帧的图片,因为摄像头取图的速度要快于算法的速度,他每次取完图以后,会直接把图片塞进一个队列(Queue)里面。
之后,他又使用了一个异步while来监控队列的长度,如果有数据,则执行算法逻辑,执行完算法以后再将图片进行保存,直至信号消失。
demo
while循环异常停止
这个逻辑本身是没有问题的,取图逻辑和算法逻辑互不干涉,不会因为算法执行比较耗时而出现取图的时候丢帧的情况,所以一开始我也没有发现他的代码写得有什么问题。
既然客户说保存时丢帧,那么肯定是保存逻辑那里出现的问题,于是我将断点下在了执行算法并保存图片的那个while循环里。
编译运行以后,发现while循环循环了几次就停止了,显而易见,逻辑是有问题的,也很显而易见,这段代码没有经过严谨的测试,但此时我也不想深究这个程序员的责任了,我只想找出哪里有问题。
排查了一圈发现,虽然while循环内部是有好几个用于跳出循环的break,但是,逻辑比较严谨,挑不出毛病。于是,我把问题定位在了while循环的执行条件上。
while循环的执行条件有两个,一个是前面说的那个当摄像头前面有东西经过时给的信号标记,当信号标记变量的值为true的时候,这个while循环显然会一直执行。另外一个我一开始看着感觉有问题,后来越看越觉得有问题,那就是队列(Queue)长度。
发现问题
虽然一时感觉不上来哪里有问题,我还是问了些这段代码的同事,问他什么目的。
结果他说:“因为摄像头拍照的速度大于算法速度,所以我这里直接监控队列长度,如果队列里面没有数据了,说明拍照终止了,那么循环也就可以终止了!”
有一个很显而易见的问题,那就是,我的同事自认为拍照速度大于算法速度,所以只要拍照不停止,队列里面就永远有数据,队列长度就永远大于0。
但是,这种说法只是理论上的,如果突然有那么一回算法的执行速度高于拍照的速度,那么while循环就可能在拍照之前被结束。
我问同事有没有这种可能,同事说:“不可能!”
我笑着问:“你就那么自信?”
我也不想给他难堪,于是就在取图的逻辑那里写了日志,结果出来后,我同事彻底无话可说了!
原来,摄像头在取图时可能会出现丢帧的情况,取100张图可能会丢帧30张,如果取一张图需要消耗10毫秒的话,原本取100张图需要消耗1000毫秒,此时取70张图就消耗了1000毫秒。
算法的执行速度虽然没有取图逻辑执行的快,但是很有可能在连续取图失败后,正好队列里面的数据也被取完了,此时队列就空了,执行算法的while循环就终止了!
demo
极端情况下,当程序刚收到有东西经过摄像头的信号时,触发取图逻辑,但取图逻辑连续取了几张图都丢了帧,导致队列提前空了,因此后面无论取多少图,用来执行算法逻辑的while循环都不会再执行了!
我告诉我的同事,没必要把用来存储图片的队列长度当作while循环的执行条件,因为有触发取图的信号和停止取图的信号,只需要根据信号标记变量来判断是否继续执行算法逻辑即可。
而判断队列长度也不是没有必要,但是应当放到while循环里面去,当队列长度为0时,走跳过(continue)逻辑即可!
解决办法
修改代码后,经过本地测试加上客户现场测试,之前的问题不再出现!
其实我觉得,不管怎么样,像队列(Queue)等不固定长度的数据均不应该成为while循环的终止条件,除非是在单线程里面执行,而且,也尽量不要这么写!
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.