之前把HDFS-RAID迁移到Hadoop-2.2.0中,在公司的集群内测试,用Java语言实现的EC算法超慢,下面是一些测试分析数据:
生成算法性能测试
测试目的:根据生成EC的三个流程,读原始数据,计算EC校验码,写校验数据,我们要测试三个流程各自对总时间的占比,这样方便我们分析性能瓶颈在什么地方。
预制条件:HDFS中存在测试文件。分析HDFS-RAID中的源代码,在编码器类Encoder的具体实现类ReedSolomonEncoder中的encodeStripe()方法中,存在如下逻辑:假定编码策略为RS(K,M),首先从流中读入大小为bufSize的K路数据,然后对这些读入内存中的K路数据按字节进行EC运算,算出结果后,再把bufSize的M路数据写出去HDFS。这三个小步骤计算完后,重新一个循环,直到把一个条带内的块数据计算完。对上面三个步骤的间隙我们分别记下时间戳,d0,d1,d2,d3。相互的差值刚好算出每部分的时长:
读取原始数据时长 = t1 = d1 – d0
计算EC校验码时长 = t2 = d2 – d1
写EC校验数据时长 = t3 = d3 – d2
总时间 = t = d3 – d0
我们在程序中设置bufSize为1M大小,程序运行时把上面的时间戳分别输出,就可扑捉占比信息。
测试结果:
|
耗时(毫秒) |
|||||||||
bufSize |
K |
M |
t1 |
% |
t2 |
% |
t3 |
% |
t |
% |
1M |
10 |
4 |
32 |
8% |
378 |
91% |
6 |
1% |
416 |
100% |
1M |
10 |
4 |
16 |
4% |
446 |
95% |
6 |
1% |
468 |
100% |
1M |
10 |
4 |
16 |
4% |
405 |
93% |
12 |
3% |
433 |
100% |
1M |
10 |
4 |
20 |
3% |
551 |
96% |
7 |
1% |
578 |
100% |
在记录上面数据时,同时用top命令检测机器上CPU的使用情况。当前机器配置了24个CPU核,检测发现,在某个时刻,24核中总有一个核的CPU使用率维持在95%以上,而其他23核基本维持在空置情况。通过进程追踪发现,促使CPU使用在95%以上的那个进程正是执行EC运算的程序。
结果分析:
通过对上表数据进行线性回归,粗略可以估算每个步骤的时间占比:读取原始数据占比5%,计算EC数据占比93%,写EC校验数据占比2%。由此看出,在这个小串行的执行过程中,计算EC数据的整个性能的瓶颈。考虑计算EC数据的CPU使用情况,推知HDFS-RAID上基于Java原生态函数实现的EC算法,性能非常低,并且没有把算法并行或并发化,没有充分利用多核CPU的效力。(通过对源代码的分析,佐证了这个推测。)
于是决定使用Jerasure替换HDFS-RAID中的计算模块,Jerasure采用较为旧的1.2版本,据说最新的2.0拥有更快的速度。
替换后,发现之前计算1M的数据大约在500ms左右,而替换后降为100ms左右。通过执行计算时分析CPU使用情况发现,Jerasure依然没有发挥多核的优势,估计作者Plank依然没有对EC进行并行化计算。
由于公司对这块的计算速度有特殊的要求,打算继续引入另一个可能更快的计算库:ISA-L。到时对三者进行对比。