MapReduce中使用字符串拼接导致的问题

今天在帮业务方优化mapreduce作业时遇到一个用字符串拼接的问题。

reduce中字符串拼接代码:

while (it.hasNext()) {line = it.next().toString();artID+=line+",";ct++;}采用的是String直接拼接,结果是该作业作业只剩一个reduce一直在运行,而且时间长达6小时,其他已经完成的reduce只用了10多分钟。

咨询了一下业务方,artID有的会很长,这个时候会一直进行字符串拼接。

我又看了一下未完成和已完成的reduce处理的数据量差别不大,未完成的需要处理60M的数据,已完成的处理了50M的数据。

1、查看该reduce的java进程的堆内存使用情况,不存在堆内存不够用,导致一直FGC的情况。

2、查看该reduce的java进程的cpu使用情况:

[mapred@yz5102 ~]$ top -p 39257top – 14:48:37 up 393 days, 20:34, 2 users, load average: 8.75, 15.84, 15.53Tasks: 43 total, 1 running, 42 sleeping, 0 stopped, 0 zombieCpu(s): 28.8%us, 7.2%sy, 0.0%ni, 61.7%id, 0.9%wa, 0.0%hi, 1.3%si, 0.0%stMem: 49374704k total, 41905644k used, 7469060k free, 2167520k buffersSwap: 8388600k total, 341168k used, 8047432k free, 27925176k cached PID USERPR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND39258 mapred 20 0 2432m 1.6g 15m R 94.1 3.4 303:47.63 java39263 mapred 20 0 2432m 1.6g 15m S 5.7 3.4 11:31.72 java39265 mapred 20 0 2432m 1.6g 15m S 5.3 3.4 11:32.03 java39268 mapred 20 0 2432m 1.6g 15m S 5.3 3.4 11:34.02 java39271 mapred 20 0 2432m 1.6g 15m S 5.3 3.4 11:32.73 java发现39258这个线程的cpu使用率很高。

打印出该reduce的java进程的线程堆栈信息并找到39258线程相关的信息,39258的十六进制为0x995a,找到nid=0x995a的线程就可以了:"main" prio=10 tid=0x00007f36e000d000 nid=0x995a runnable [0x00007f36e6ab6000] java.lang.Thread.State: RUNNABLEat java.util.Arrays.copyOfRange(Arrays.java:3209)at java.lang.String.<init>(String.java:215)at java.lang.StringBuilder.toString(StringBuilder.java:430)at weMedia.create.ArticleInfoReduce.reduce(ArticleInfoReduce.java:23)at weMedia.create.ArticleInfoReduce.reduce(ArticleInfoReduce.java:13)at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:171)at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:627)at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389)at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:167)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:396)at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1550)at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:162)

线程堆栈信息显示,该线程cpu使用率高是因为一直在进行字符串拼接,虽然代码直接使用的是String,但是JVM底层转化成了StringBuilder的操作,按理说转换成了StringBuilder效果不应该低,但是实际结果并不理想。

最后让业务方显示的修改了字符串拼接部分的代码,,使用StringBuffer,重新执行了一下该作业,作业全部运行完成只用了10多分钟,和修改之前的6个小时,运行效率提高了很多倍。

小结:

虽然直接用String拼接,底层实际使用的是StringBuilder进行操作,但是效率还是不尽人意,最好还是显示的用StringBuilder或者StringBuffer吧,不要寄希望于底层转换。

如果没法忘记他,就不要忘记好了。真正的忘记,是不需要努力的。

MapReduce中使用字符串拼接导致的问题

相关文章:

你感兴趣的文章:

标签云: