4.7 性能调优
一个程序可以完成基本功能其实还不够,还有一些具有实际意义的问题需要解决,比如性能是不是足够好、有没有提高的空间等。具体来讲包括两个方面的内容:一个是时间性能;另一个是空间性能。衡量性能的指标就是,能够在正确完成功能的基础上,使执行的时间尽量短,占用的空间尽量小。
前面只是实现了程序基本应该实现的功能,对性能问题并没有加以考虑。下面就从不同的角度来简单地介绍一下提高性能的方法。
4.7.1 输入采用大文件
在前面的例子当中,笔者的实验数据包含1000个文件,在HDFS中共占用了1000个文件块,而每一个文件的大小都是2.3MB,相对于HDFS块的默认大小64MB来说算是比较小的了。如果MapReduce在处理数据时,Map阶段输入的文件较小而数量众多,就会产生很多的Map任务,以前面的输入为例,一共产生了1000个Map任务。每次新的Map任务操作都会造成一定的性能损失。针对上述2.2GB大小的数据,在实验环境中运行的时间大概为33分钟。
为了尽量使用大文件的数据,笔者对这1000个文件进行了一次预处理,也就是将这些数量众多的小文件合并成大一些的文件,最终将它们合并成了一个大小为2.2GB的大文件。然后再以这个大文件作为输入,在同样的环境中进行测试,运行的时间大概为4分钟。
从实验结果可以很明显地看出二者在执行时间上的差别非常大。因此为了提高性能,应该对小文件做一些合理的预处理,变小为大,从而缩短执行的时间。不仅如此,合并前的众多文件在HDFS中占用了1000个块,而合并后的文件在HDFS中只占用36个块(64MB为一块),占用空间也相应地变小了,可谓一举两得。
另外,如果不对小文件做合并的预处理,也可以借用Hadoop中的CombineFileInputFormat。它可以将多个文件打包到一个输入单元中,从而每次执行Map操作就会处理更多的数据。同时,CombineFileInputFormat会考虑节点和集群的位置信息,以决定哪些文件被打包到一个单元之中,所以使用CombineFileInputFormat也会使性能得到相应地提高。