最近从公司SOP项目转到Data Analysis「DA」项目,开始从事Mean堆栈的开发,一些新的坑也要从头踩起。昨天就遇到了一个深坑,特此记录下来。
拿到之前同事写的代码,看懂流程以后就开始写功能了。我要做的事情是把之前同事写的生成Excel的内容导入到Oracle中,那就尽量调用之前的代码吧。 由于数据量比较大,所以采用Schedule Job的方式,每过一段时间执行一次,将200条BL数据(实际插入2k+的数据)导入DB。100w+的数据筛选后大概需要两天的时间全部导入。
有一段代码是执行一个Promise.all函数,执行完以后进入下一个Promise,在正常执行了很久以后,有一段时间突然变得很慢。于是我就停下job,重启一次发现又能正常执行了,可是总是过一段时间就变得非常慢,看log又看不出端倪,停下来重跑就又正常,这样好难找到原因,即使debug也不一定能重现。
只能耐着性子一句代码一句地看,这样Promise.all里面调用了4个的函数,每个函数里面又至少有几十个函数,所幸的是4个函数里面调用的函数都是类似的,只是改变了一些变量和常数。
就这么看了几个小时,这个时候非常想知道JavaScript有没有什么性能分析的工具,可以查看某一段代码执行花费的时间。在Google和百度搜了都没有找到合适的工具,要急死我了。
苦心人天不负,终于在一个计算时间的函数里面看到了端倪。这个函数是一个计算时间差的函数,中间要排除节假日和下班时间,然后计算真正工作时间花费了多久。
之前同事的逻辑是:
while (endTime > current) {
if (currnt是工作时间){
total += 1 分钟
}
current = current + 1分钟
}
因为节假日和周末都是以天都单位的,可是上下班时间是以分钟为单位的,所以同事选择了每分钟逐渐递加,然后判断是否为工作时间。这样的计算逻辑是没有问题的,不过非常耗费时间,因为节假日不是工作时间,但是还需要每分钟逐渐递加去比较判断。而我在数据库里面发现了一些奇怪的数据,有几百条数据不均匀的分布在数据库中,它们的endTime比startTime大了1-2年。所以在计算这些数据的时候 /(ㄒoㄒ)/~~
咨询资深的同事后,得知这些问题数据是历史残留–系统迁移导致,暂时没有办法解决,而且这些数据还是正确的数据。
为什么重新跑以后就又没有问题了呢,因为在我跑数据的过程中新的数据不断产生,我之前导数据又没有排序,所以每次都是处理最新产生的数据,自然不容易找到问题啦。
这下太开心了,有一句经典的话说是 发现问题比解决问题更难,既然发现了问题,解决起来应该easy啦。
于是改写之前的逻辑,把逐分钟递增改成逐天增加,首先构造一个工作日的对象,里面存着每天的上下班时间和这天总工作时间,然后构造一个节假日对象,存每个节日的年、月、日。 循环的时候,首先判断当天是否为节假日,如果为节假日则直接进入下一天,如果不是节假日就计算当天工作的时间,最后将所有工作时间加起来。
for (let i=0; i<间隔days; i++){
if (current是工作日) {
if (current是start date){
total += (startTime - 下班时间)
} else if (current是end date) {
total += (endTime - 上班时间)
} else{
total += 当天工作时间
}
}
}
按照TDD(测试驱动开发的思想),想到每一个case都是先写测试用例,然后完善代码,终于完成13个测试用例的同时把代码写完。
虽然耗费了我一整个上午加不休息的中午,但是我几乎把之前相关的代码都看懂了,所以让我对整个项目的了解也加深了不少,而且排查问题的过程中我增强了自己导数据的逻辑——添加了排序功能,这样更方便我找到问题数据,相信会对以后的开发提供很大的帮助。