0

Hadoop プロジェクトに取り組んでいます。私のreduceフェーズは非常にメモリを消費します。私は現在 HashMap を使用していますがError: Java Heap space、Reduce で巨大なハッシュマップ (データセットは 32GB) を構築しているため、 を取得します。解決策は、ディスク フォールバックを備えたインメモリ Hashmap である可能性があり、MapDB は私のニーズに合っているようです。しかし、私は使用法について確信が持てません。diskMap は各 Reduce タスクに固有であり、inMemory マップは各 Reduce 'key' に固有です。テスト用に設定したとしてもexpireMaxSize(3)、onDisk マップがいつ使用され、ロジックが正しいかはわかりません。繰り返しますが、テストのために、ハッシュマップに 20 個の偽のエントリを入力しました。基本的に、ヒープ オーバーフローを回避するには、inMemory マップの成長を制御する必要があります。

public class TestReducer extends Reducer<LongWritable, BytesWritable, String, IntWritable> {

private int id;
DB dbDisk;
protected void setup(Context context) throws IOException, InterruptedException {
    id = context.getTaskAttemptID().getTaskID().getId();
    File diskmap = new File("tmp/diskmap"+id);
    diskmap.delete();
    dbDisk = DBMaker
                .fileDB("tmp/diskmap"+id)
                .make();
}

@Override
protected void reduce(LongWritable key, Iterable<BytesWritable> values, Context context)
        throws IOException, InterruptedException {

    DB dbMemory = DBMaker
            .memoryDB()
            .make();

    HTreeMap<Long,Integer> onDisk = dbDisk
            .hashMap("onDisk")
            .keySerializer(Serializer.LONG)
            .valueSerializer(Serializer.INTEGER)
            .createOrOpen();
    // fast in-memory collection with limited size
    HTreeMap<Long,Integer> inMemory = dbMemory
            .hashMap("inMemory")
            .expireMaxSize(3)
            .keySerializer(Serializer.LONG)
            .valueSerializer(Serializer.INTEGER)
            //this registers overflow to `onDisk`
            .expireOverflow(onDisk)
            .createOrOpen();

    for(int k=0;k<20;k++){
        inMemory.put((long)k,k*2);
    }
Set set = inMemory.entrySet();
    Iterator it = set.iterator();
    while(it.hasNext()) {
      Map.Entry<Long,Integer> entry = (Map.Entry<Long,Integer>)it.next();
      System.out.print("Key is: "+entry.getKey() + " & ");
      System.out.println("Value is: "+entry.getValue());
    }

}
protected void cleanup(Context context) throws IOException,InterruptedException {
    dbDisk.close();
}

}
4

1 に答える 1

0

MapDB は、ダイレクト メモリまたはアプリケーションのヒープにメモリを割り当てることができます。

ダイレクト メモリを使用するには、

DB dbMemory = DBMaker
             .memoryDB()
             .make();

DB dbMemory = DBMaker
              .memoryDirectDB()
              .make();

Javaプロパティがあります

XX:MaxDirectMemorySize

使用する最大メモリを設定するように設定できます。

データに十分なメモリを確保するために割り当てを管理する必要がありますが、アプリケーションのヒープがこのデータで大きくなることはなく、アプリケーション自体がメモリ不足の例外をスローしたり、最大ヒープ制限に達したりすることはありません (アプリケーションは悪です)。

于 2016-12-12T23:01:48.240 に答える