Sparkパフォーマンスの最適化
主にメモリ使用量のために調整
Sparkパフォーマンス最適化テクノロジー
- 高性能シリアル化ライブラリを使用する
- データ構造を最適化する
- 複数のRDDの永続化とチェックポイント
- 永続性レベル:MEMORY_ONLY-> MEMORY_ONLY_SERシリアル化
- Java仮想マシンのガベージコレクションのチューニング
- シャッフル調整
I. Sparkのメモリ使用量を判断する
まず、ターゲットを絞った最適化を実行するために、メモリ使用量を確認する必要があります
(1)メモリコスト
- すべてのJavaオブジェクトには、16バイトを占めるオブジェクトヘッダーがあり、そのクラスへのポインターなど、オブジェクトに関するメタ情報が含まれています。オブジェクト自体はintのように小さいが、オブジェクトヘッドがオブジェクト自体よりも大きい場合
- JavaのStringオブジェクトは、メモリ内の元のデータよりも40バイト多くなります。String内で使用されるchar配列は、内部の文字列シーケンスを保持し、出力長などの情報も保存します。CharはUTF-16エンコーディングを使用し、各文字は2バイトを占有します。たとえば、10文字を含む文字列、2 * 10 + 30 = 60バイト
- HashMapやLinkedListなどのJavaのコレクション型は、リンクリストのデータ構造を内部的に使用します。リンクされたリストの各データは、Entryオブジェクトでラップされます。エントリオブジェクト、オブジェクトヘッダーだけでなく、8バイトを占める次のエントリを必要とするだけのポインタ
- 要素タイプは元のデータタイプ(int)であり、通常、元のデータタイプのパッケージタイプ(整数)が要素の格納に使用されます。
- RDDの並列処理を設定します(parellelizeとtextFileの2つのメソッドでRDDを作成し、これらの2つのメソッドで2番目のパラメーターを渡し、RDDパーティションの数を設定します。SparkConfigでパラメーターを設定します。spark.default.parallelismは均一に設定できますこのアプリケーションのすべてのRDDのパーティション数)
- RDDのキャッシュ
- 観測ログ:ドライバーログ(Sparkの作業フォルダーの下)
- このMemoryStoreメモリ情報を追加してください、それはRDDメモリです
- キャッシュのサイズを最適化します(登録済みのカスタムタイプが非常に大きい(100フィールド)場合、オブジェクトのシリアル化が大きくなりすぎます。現時点では、kyro自体を最適化する必要があります。kryoの内部キャッシュはそれほど大きく保存されない可能性があるためですクラスオブジェクト。spark.kryoserializer.buffer.maxパラメータを設定し、それを増やします)
- カスタムタイプを事前に登録します(kryoはカスタムタイプを登録しなくても正常に機能しますが、完全修飾クラス名のコピーを保存してメモリを消費します。シリアル化するカスタムタイプを事前登録することをお勧めします)
- コレクションクラスではなく配列と文字列を使用することをお勧めします(できればArrayList、LinkedList、HashMapの代わりにArrayを使用します)。int[]を使用すると、リストよりもメモリを節約できます
- オブジェクトを文字列に変換
- ネストされたオブジェクト構造の複数のレイヤーの使用を避ける
- 回避できるシナリオでは、Stringの代わりにintを使用してみてください
(2)メモリ消費量を判断する
第二に、高性能シリアル化クラスライブラリを使用する
1.データのシリアル化データのシリアル化とは、オブジェクトまたはデータ構造を特定の形式に変換して、ネットワーク上で送信したり、メモリやファイルに保存したりできるようにすることです
逆シリアル化は反対の操作で、シリアル化されたデータからオブジェクトを復元します
シリアル化されたデータ形式は、バイナリ、xml、jsonなどの任意の形式にすることができます。
オブジェクトとデータのシリアル化の焦点は、データの交換と送信にあります
どの分散システムでも、シリアライゼーションは重要な役割を果たします
シリアライゼーションテクノロジーを使用すると、操作が非常に遅くなるか、シリアライゼーション後のデータ量が非常に多くなり、分散システムアプリケーションのパフォーマンスが低下します。
Spark自体は、デフォルトでShuffleなどの一部の場所でデータをシリアル化します。さらに、外部データ(カスタムタイプ)を使用しましたが、シリアル化も可能にしました
デフォルトでは、Sparkは、Java自体が提供するシリアル化メカニズムを使用して、シリアル化の利便性を優先します。ただし、Javaシリアル化メカニズムのパフォーマンスは高くなく、シリアル化速度が遅く、シリアル化されたデータが大きく、メモリ領域を消費します。
2.実行Sparkはkryoクラスライブラリを使用したシリアル化をサポートします
高速でフットプリントが小さく、Javaシリアル化データの10分の1
3. kryoシリアル化メカニズムを使用する(1)Spark設定を設定する
spark.master spark://6.7.8.9:7077
spark.executor.memory 4g
spark.eventLog.enabled true
spark.serializer org.apache.spark.serializer.KryoSerializer
(2)kryoを使用し、クラスをシリアル化する必要があり、事前に登録して高いパフォーマンスを得る
conf.registerKryoClasses(Array(classOf [Count]、...))
4. kryoライブラリの最適化第三に、データ構造を最適化します
概観
メモリ消費量を削減するには、効率的なシリアライゼーションライブラリの使用に加えて、Java構文機能によって引き起こされる追加のメモリオーバーヘッドを回避するためにデータ構造も最適化する必要があります
コア:演算子関数内で使用されるローカルデータまたは演算子関数外のデータを最適化します
目的:メモリの消費と占有を減らす
練習
4番目に、Java仮想マシンのチューニング
1.概要
RDDが永続化されるときに大量のデータが永続化されると、Java仮想マシンのガベージコレクションがボトルネックになる可能性があります。
Java仮想マシンは定期的にガベージコレクションを実行します。このとき、すべてのJavaオブジェクトが追跡され、ガベージコレクション中に、使用されなくなったオブジェクトが検出され、古いオブジェクトがクリーンアップされ、新しいオブジェクトのためのスペースが作成されます。
ガベージコレクションのパフォーマンスオーバーヘッドは、メモリ内のオブジェクトの数に比例します
Java仮想マシンのチューニングを行う前に、前のチューニング作業を実行してから、それを理解する必要があります。
第二に、Spark GCの原則
3.ガベージコレクションの監視
最初のレベルのガベージコレクションに費やされた時間などを監視する
spark-submit脚本中、追加--conf "spark.executor.extraJavaOptions = -verbose:gc -XX:+ PrintGCDetails -XX:+ PrintGCTimesStamps"
ワーカーログ:Sparkの下のログフォルダー
ドライバーログ:Sparkの下のワーカーフォルダー
4番目に、Executorのメモリ比率を最適化します
目的:GCの数を減らす
GCチューニングの場合、最も重要なことは、オペレーターが実行されたときに作成されたオブジェクトが占めるメモリスペースに対するRDDキャッシュが占めるスペースの比率を調整することです。
デフォルトの場合、Sparkは各エグゼキューターのメモリスペースの60%を使用してRDDをキャッシュし、メモリスペースの40%のみがタスク中に作成されたオブジェクトの格納に使用されます。
配置:conf.set( "spark.storage.memoryFraction"、0.5)