本帖最后由 fish_tx 于 2015-10-22 18:00 编辑
[大牛翻译系列]Hadoop(15)MapReduce 性能调优:优化MapReduce的用户JAVA代码
Mapperpackage com.fish.had.cellphonenumbercount;
import java.io.IOException;
import org.apache.commons.lang.StringUtils; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper;
public class CellPhoneNumberMapper extends Mapper<LongWritable, Text, Text, LongWritable>{
final LongWritable ONE = new LongWritable(1L); Text v2 = new Text();
@Override protected void map(LongWritable k1, Text v1, Mapper<LongWritable, Text, Text, LongWritable>.Context context) throws IOException, InterruptedException { String v = v1.toString(); /* if(null != v && !"".equals(v)){ String[] ss = v.split("\t");//2 if(ss.length > 2){ if(ss[2].length() == 11 && ss[2].indexOf(".") < 0){ context.write(new Text(ss[2]), ONE); } } } */ //--优化----------------------------------------------------------------- if(null != v && !"".equals(v)){ String[] ss = StringUtils.split(v, "\t"); if(ss.length > 2){ if(ss[2].length() == 11 && ss[2].indexOf(".") < 0){ v2.set(ss[2]); context.write(v2, ONE); } } } } }
正则表达式 正则表达式有非常丰富灵活的特性。然而灵活性意味着性能下降。有的时候,性能会降低到不可接受的地步。那么,作为一般准则,就应该在MapReduce中避免使用正则表达式。如果非用不可,也应该尽量寻找替代方法。
字符串令牌化(TOKENIZATION)
JAVA的文档推荐使用String.split和Scanner类来实现字符串令牌化。实际上,它们都是基于正则表达式,在MapReduce中 会很慢。然后,就要考虑用JAVA文档不推荐的StringTokenizer。但是,StringTokenizer的算法性能也不是最优。 Apache commons中的StringUtils类效率要更好。 String[] ss = StringUtils.split(v, "\t");
对象重用 第二个消耗CPU时间的是类似如下的代码: context.write(new Text(ss[2]), ONE); 由于这段代码在每个键值对都要执行一次,就要执行成千上万次。代码就会在对象分配上浪费大量的时间。对象分配在JAVA中是非常昂贵的,包含创建时调用CPU,销毁时调用垃圾收集器。如果能够重用,将节约大量的时间。以下代码介绍如何达到最大重用率: Text v2 = new Text();
.....
if(ss[2].length() == 11 && ss[2].indexOf(".") < 0){ v2.set(ss[2]); context.write(v2, ONE);
}
|