Writable データ型を Mutable にする必要があるのはなぜですか? Map、Combine、Shuffle、Reduce プロセスで Key/Value のデータ型として Text (vs String) を使用する利点は何ですか?
よろしくお願いします、 ラジャ
選択することはできません。これらのデータ型は変更可能でなければなりません。
その理由は、シリアル化メカニズムにあります。コードを見てみましょう:
// version 1.x MapRunner#run()
K1 key = input.createKey();
V1 value = input.createValue();
while (input.next(key, value)) {
// map pair to output
mapper.map(key, value, output, reporter);
...
そのため、キーと値のペアの同じインスタンスを何度も再利用しています。なんで?当時の設計上の決定についてはわかりませんが、ガベージ オブジェクトの量を減らすためだったと思います。Hadoop は非常に古く、当時のガベージ コレクターは現在ほど効率的ではありませんでしたが、今日でも数十億のオブジェクトをマップし、それらをガベージとして直接破棄すると、ランタイムに大きな違いが生じることに注意してください。
Writable
型を本当に不変にできない本当の理由は、フィールドを として宣言できないからですfinal
。を使って簡単な例を作りましょうIntWritable
:
public class IntWritable implements WritableComparable {
private int value;
public IntWritable() {}
public IntWritable(int value) { set(value); }
...
value
不変にすると、 finalを定義する必要があるため、シリアル化プロセスでは確実に機能しなくなります。キーと値は実行時にリフレクションを介してインスタンス化されるため、これは機能しません。これにはデフォルトのコンストラクターInputFormat
が必要なため、最終的なデータ フィールドを埋めるために必要なパラメーターを推測することはできません。したがって、インスタンスを再利用するという全体の概念は、明らかに不変性の概念と矛盾します。
ただし、不変のキー/値が Map/Reduce でどのような利点を持つべきかを自問する必要があります。Joshua Bloch の『Effective Java』の Item 15 で、彼は不変クラスの方が設計、実装、および使用が容易であると述べています。Hadoop のレデューサーは可変性の最悪の例であるため、彼は正しいです。
void reduce(IntWritable key, Iterable<Text> values, Context context) ...
iterable のすべての値は、same
共有オブジェクトを参照します。したがって、値を通常のコレクションにバッファリングし、なぜ常に同じ値を保持するのかを自問すると、多くの人が混乱します。
最終的には、パフォーマンス (CPU とメモリ - 1 つのキーに対して何十億もの値オブジェクトが RAM に存在しなければならないことを想像してください) とシンプルさのトレードオフになります。