hadoop映射器过度消耗内存(堆)

hadoop映射器过度消耗内存(堆),hadoop,mapreduce,hashmap,mapper,Hadoop,Mapreduce,Hashmap,Mapper,我在hadoop map reduce中编写了一个简单的哈希连接程序。其思路如下: 使用hadoop框架提供的DistributedCache将一个小表分发给每个映射器。大表分布在映射器上,拆分大小为64M。 映射器的设置代码创建一个hashmap,读取这个小表中的每一行。在映射程序代码中,在hashmap上搜索(get)每个键,如果该键存在于hashmap中,则将其写出。此时不需要减速器。这是我们使用的代码: public class Map extends Mapper<Lon

我在hadoop map reduce中编写了一个简单的哈希连接程序。其思路如下:

使用hadoop框架提供的DistributedCache将一个小表分发给每个映射器。大表分布在映射器上,拆分大小为64M。 映射器的设置代码创建一个hashmap,读取这个小表中的每一行。在映射程序代码中,在hashmap上搜索(get)每个键,如果该键存在于hashmap中,则将其写出。此时不需要减速器。这是我们使用的代码:

    public class Map extends Mapper<LongWritable, Text, Text, Text> {
        private HashMap<String, String> joinData = new HashMap<String, String>();

        public void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {

            String textvalue = value.toString();
            String[] tokens;
            tokens = textvalue.split(",");
            if (tokens.length == 2) {
                String joinValue = joinData.get(tokens[0]);
                if (null != joinValue) {
                    context.write(new Text(tokens[0]), new Text(tokens[1] + ","
                            + joinValue));
                }
            }
        }

    public void setup(Context context) {
        try {
            Path[] cacheFiles = DistributedCache.getLocalCacheFiles(context
                    .getConfiguration());
            if (null != cacheFiles && cacheFiles.length > 0) {
                String line;
                String[] tokens;
                BufferedReader br = new BufferedReader(new FileReader(
                        cacheFiles[0].toString()));
                try {
                    while ((line = br.readLine()) != null) {

                        tokens = line.split(",");
                        if (tokens.length == 2) {
                            joinData.put(tokens[0], tokens[1]);
                        }
                    }
                    System.exit(0);
                } finally {
                    br.close();
                }
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
公共类映射扩展映射器{
私有HashMap joinData=新HashMap();
公共void映射(可长写键、文本值、上下文)
抛出IOException、InterruptedException{
字符串textvalue=value.toString();
字符串[]标记;
令牌=textvalue.split(“,”);
if(tokens.length==2){
字符串joinValue=joinData.get(标记[0]);
if(null!=joinValue){
write(新文本(标记[0]),新文本(标记[1]+“,”
+(价值),;
}
}
}
公共无效设置(上下文){
试一试{
路径[]cacheFiles=DistributedCache.getLocalCacheFiles(上下文
.getConfiguration());
if(null!=cacheFiles&&cacheFiles.length>0){
弦线;
字符串[]标记;
BufferedReader br=新的BufferedReader(新文件读取器(
缓存文件[0].toString());
试一试{
而((line=br.readLine())!=null){
标记=行分割(“,”);
if(tokens.length==2){
put(令牌[0],令牌[1]);
}
}
系统出口(0);
}最后{
br.close();
}
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
在测试这段代码时,我们的小表是32M,大表是128M,一个主节点和两个从节点

当我有一个256M的堆时,上述输入的代码失败。我在mapred-site.xml文件的mapred.child.java.opts中使用-Xmx256m。当我把它增加到300m时,它的速度非常慢,512m达到最大吞吐量

我不明白我的映射器在哪里消耗了这么多内存。使用上面给出的输入 使用mapper代码,我不希望我的堆内存达到256M,但是由于java堆空间错误,它失败了

如果您能深入了解映射程序消耗如此多内存的原因,我将不胜感激

编辑

13/03/11 09:37:33 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
13/03/11 09:37:33 INFO input.FileInputFormat: Total input paths to process : 1
13/03/11 09:37:33 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
13/03/11 09:37:33 WARN snappy.LoadSnappy: Snappy native library not loaded
13/03/11 09:37:34 INFO mapred.JobClient: Running job: job_201303110921_0004
13/03/11 09:37:35 INFO mapred.JobClient:  map 0% reduce 0%
13/03/11 09:39:12 INFO mapred.JobClient: Task Id : attempt_201303110921_0004_m_000000_0, Status : FAILED
Error: GC overhead limit exceeded
13/03/11 09:40:43 INFO mapred.JobClient: Task Id : attempt_201303110921_0004_m_000001_0, Status : FAILED
org.apache.hadoop.io.SecureIOUtils$AlreadyExistsException: File /usr/home/hadoop/hadoop-1.0.3/libexec/../logs/userlogs/job_201303110921_0004/attempt_201303110921_0004_m_000001_0/log.tmp already exists
    at org.apache.hadoop.io.SecureIOUtils.insecureCreateForWrite(SecureIOUtils.java:130)
    at org.apache.hadoop.io.SecureIOUtils.createForWrite(SecureIOUtils.java:157)
    at org.apache.hadoop.mapred.TaskLog.writeToIndexFile(TaskLog.java:312)
    at org.apache.hadoop.mapred.TaskLog.syncLogs(TaskLog.java:385)
    at org.apache.hadoop.mapred.Child$4.run(Child.java:257)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:416)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)
    at org.apache.hadoop.mapred.Child.main(Child.java:249)

attempt_201303110921_0004_m_000001_0: Exception in thread "Thread for syncLogs" java.lang.OutOfMemoryError: Java heap space
attempt_201303110921_0004_m_000001_0:   at java.io.BufferedOutputStream.<init>(BufferedOutputStream.java:76)
attempt_201303110921_0004_m_000001_0:   at java.io.BufferedOutputStream.<init>(BufferedOutputStream.java:59)
attempt_201303110921_0004_m_000001_0:   at org.apache.hadoop.mapred.TaskLog.writeToIndexFile(TaskLog.java:312)
attempt_201303110921_0004_m_000001_0:   at org.apache.hadoop.mapred.TaskLog.syncLogs(TaskLog.java:385)
attempt_201303110921_0004_m_000001_0:   at org.apache.hadoop.mapred.Child$3.run(Child.java:141)
attempt_201303110921_0004_m_000001_0: log4j:WARN No appenders could be found for logger (org.apache.hadoop.hdfs.DFSClient).
attempt_201303110921_0004_m_000001_0: log4j:WARN Please initialize the log4j system properly.
13/03/11 09:42:18 INFO mapred.JobClient: Task Id : attempt_201303110921_0004_m_000001_1, Status : FAILED
Error: GC overhead limit exceeded
13/03/11 09:43:48 INFO mapred.JobClient: Task Id : attempt_201303110921_0004_m_000001_2, Status : FAILED
Error: GC overhead limit exceeded
13/03/11 09:45:09 INFO mapred.JobClient: Job complete: job_201303110921_0004
13/03/11 09:45:09 INFO mapred.JobClient: Counters: 7
13/03/11 09:45:09 INFO mapred.JobClient:   Job Counters 
13/03/11 09:45:09 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=468506
13/03/11 09:45:09 INFO mapred.JobClient:     Total time spent by all reduces waiting after reserving slots (ms)=0
13/03/11 09:45:09 INFO mapred.JobClient:     Total time spent by all maps waiting after reserving slots (ms)=0
13/03/11 09:45:09 INFO mapred.JobClient:     Launched map tasks=6
13/03/11 09:45:09 INFO mapred.JobClient:     Data-local map tasks=6
13/03/11 09:45:09 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=0
13/03/11 09:45:09 INFO mapred.JobClient:     Failed map tasks=1
13/03/11 09:37:33警告mapred.JobClient:使用GenericOptionsParser解析参数。应用程序应该为相同的应用程序实现工具。
13/03/11 09:37:33信息输入。文件输入格式:要处理的总输入路径:1
13/03/11 09:37:33警告util.NativeCodeLoader:无法为您的平台加载本机hadoop库。。。在适用的情况下使用内置java类
13/03/11 09:37:33警告snappy.LoadSnappy:snappy本机库未加载
2011年3月13日09:37:34信息映射。作业客户端:正在运行作业:作业201303110921\u 0004
13/03/11 09:37:35信息映射。作业客户端:映射0%减少0%
2011年3月13日09:39:12 INFO mapred.JobClient:任务Id:尝试\u 201303110921\u 0004\u m\u000000\u 0,状态:失败
错误:超出GC开销限制
2011年3月13日09:40:43信息映射。作业客户端:任务Id:尝试\u 201303110921\u 0004\u m\u000001\u 0,状态:失败
org.apache.hadoop.io.SecureIOUtils$AlreadyexistException:File/usr/home/hadoop/hadoop-1.0.3/libexec/。/logs/userlogs/job\u 201303110921\u 0004/trust\u 201303110921\u 0004\u m\u000001\u 0/log.tmp已存在
位于org.apache.hadoop.io.SecureIOUtils.secureCreateForWrite(SecureIOUtils.java:130)
在org.apache.hadoop.io.SecureIOUtils.createForWrite(SecureIOUtils.java:157)上
位于org.apache.hadoop.mapred.TaskLog.writeToIndexFile(TaskLog.java:312)
位于org.apache.hadoop.mapred.TaskLog.syncLogs(TaskLog.java:385)
位于org.apache.hadoop.mapred.Child$4.run(Child.java:257)
位于java.security.AccessController.doPrivileged(本机方法)
位于javax.security.auth.Subject.doAs(Subject.java:416)
位于org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)
位于org.apache.hadoop.mapred.Child.main(Child.java:249)
尝试_201303110921_0004_m_000001_0:线程“thread for syncLogs”java.lang.OutOfMemoryError:java堆空间中的异常
尝试\u 201303110921\u 0004\u m\u000001\u 0:at java.io.BufferedOutputStream.(BufferedOutputStream.java:76)
尝试\u 201303110921\u 0004\u m\u000001\u 0:at java.io.BufferedOutputStream.(BufferedOutputStream.java:59)
在org.apache.hadoop.mapred.TaskLog.writeToIndexFile(TaskLog.java:312)上尝试
在org.apache.hadoop.mapred.TaskLog.syncLogs(TaskLog.java:385)上尝试
尝试_201303110921_0004_m_000001_0:org.apache.hadoop.mapred.Child$3.run(Child.java:141)
尝试_201303110921_0004_m_000001_0:log4j:WARN找不到记录器(org.apache.hadoop.hdfs.DFSClient)的附加程序。
尝试_201303110921_0004_m_000001_0:log4j:警告请正确初始化log4j系统。
13/03/11 09:42:18 INFO mapred.JobClient:任务Id:尝试\u 201303110921\u 0004\u m\u000001\u 1,状态:失败
错误:超出GC开销限制
2011年3月13日09:43:48信息映射。作业客户端:任务Id:尝试\u 201303110921\u 0004\u m\u000001\u 2,状态:失败
错误:超出GC开销限制
2011年3月13日09:45:09信息映射。作业客户端:作业完成:作业\u 201303110921\u 0004
13/03/11 09:45:09信息映射。作业客户端:计数器:7
13/03/11 09:45:09信息映射。作业客户端:作业计数器
13/03/11 09:45:09信息映射。作业客户端:插槽