Spark Documentation 문서 번역을 한 번 해보려고 한다.

눈가락번역기의 번역 상태가 많이 좋지 않으니 양해 바람.

 

번역 대상 문서 : https://spark.apache.org/docs/latest/tuning.html

 

Garbage Collection Tuning
Garbage Collection 튜닝하기

JVM garbage collection can be a problem when you have large “churn” in terms of the RDDs stored by your program.

만약 프로그램에 의해 RDD 가 저장되어  생기는 "churn" 이 많이 생긴다면, JVM garbege collection 은 문제가 될 수 있다.

(It is usually not a problem in programs that just read an RDD once and then run many operations on it.)

(RDD 를 한 번 읽고 처리를 하는 프로그램에서는 보통 문제가 되지 않는다.)

When Java needs to evict old objects to make room for new ones, it will need to trace through all your Java objects and find the unused ones.

Java 가 새로운 객체를 위해 공간을 만들려고 오래된 객체를 지울 필요가 있을 때, 사용자의 모든 Java 객체를 추적하고 사용하지 않는 객체를 찾을 필요가 있을 것이다.

The main point to remember here is that the cost of garbage collection is proportional to the number of Java objects, so using data structures with fewer objects (e.g. an array of Ints instead of a LinkedList) greatly lowers this cost.

여기서 기억해야 할 주요한 점은, GC 비용은 JAVA 객체 수에 따라 달라진다는 것이다. 그래서 적은 수의 객체를 갖는 데이터 구조(예를 들어 LinkedList 대신 Int 배열)를 사용하면 비용을 낮출 수 있다.

An even better method is to persist objects in serialized form, as described above: now there will be only one object (a byte array) per RDD partition.

더 나은 방법은, 위에서 설명했듯이 객체를 직렬화 하는 것이다: 지금 RDD 파티션 당 오직 하나의 객체만 있을 수 있다.

Before trying other techniques, the first thing to try if GC is a problem is to use serialized caching.

다른 기술을 시도하기 전, GC 가 문제인 상황에서 첫째로 시도해야 할 것은 캐싱을 직렬화 하는 것이다.

GC can also be a problem due to interference between your tasks’ working memory (the amount of space needed to run the task) and the RDDs cached on your nodes.

GC 는 사용자 task의 워킹 메모리(task 를 실행하기 위해 필요한 메모리공간)와 RDD 캐시 간 간섭때문에 문제가 될 수 있다. (interference 가 왜 들어가있는거지?)

We will discuss how to control the space allocated to the RDD cache to mitigate this.

이를 완화하기 위해, RDD 캐시에 할당된 공간을 어떻게 컨트롤 할 지 의논해보자.

 

Measuring the Impact of GC
GC 영향 측정하기

The first step in GC tuning is to collect statistics on how frequently garbage collection occurs and the amount of time spent GC.

GC 튜닝의 첫번째 절차는, GC 가 얼마나 빈번하게 발생하는지, 그리고 GC 로 인해 소요되는 시간의 양이 얼마인지 통계치를 수집하는 것이다.

This can be done by adding -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps to the Java options.

JAVA 옵션에 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 을 추가하여 측정할 수 있다.

(See the configuration guide for info on passing Java options to Spark jobs.)

(Spark jobs 에 Java 옵션을 전달하는 정보를 담은 configuration guide 문서를 확인하라)

Next time your Spark job is run, you will see messages printed in the worker’s logs each time a garbage collection occurs.

그 후 Spark job 을 실행하면, 워커노드의 로그에 GC 발동 및 걸린 시간에 대한 메세지가 출력되는 것을 볼 수 있다.

Note these logs will be on your cluster’s worker nodes (in the stdout files in their work directories), not on your driver program.

이 로그들은 클러스터의 워커 노드에 생성 되며(워커 directories 에 stdout 파일로), driver 프로그램 노드에는 로그가 생기지 않는다.

 

Advanced GC Tuning
좀 더 전문적으로 GC 튜닝하기

To further tune garbage collection, we first need to understand some basic information about memory management in the JVM:
조금 더 GC 튜닝을 하기 위해, JVM 에서 메모리 관리에 대한 기본 정보를 어느정도 이해하고 있어야 한다.

  • Java Heap space is divided in to two regions Young and Old.
    Java Heap 공간은 두 가지 영역인 Young, Old 로 나뉜다.
    The Young generation is meant to hold short-lived objects while the Old generation is intended for objects with longer lifetimes.
    Young 세대는 짧게 살았던 객체들이 보유된 것을 의미하고, Old 세대는 긴 시간을 산 객체들을 위해 사용된다.
  • The Young generation is further divided into three regions [Eden, Survivor1, Survivor2].
    Young 세대는 세 가지 영역으로 나뉜다. Eden, Surv1, Surv2
  • A simplified description of the garbage collection procedure:
    GC 작업 절차에 대한 간단한 설명:
    When Eden is full, a minor GC is run on Eden and objects that are alive from Eden and Survivor1 are copied to Survivor2.
    Eden 이 꽉 차면, minor GC 가 Eden 대상으로 동작함. 그러면 Eden, Surv1 내 객체들 중 살아있는 객체들은 Surv 2로 복사된다.
    The Survivor regions are swapped.
    Surv 공간들은 교환된다.
    If an object is old enough or Survivor2 is full, it is moved to Old.
    만약 객체가 충분히 오래 살았거나 Surv2 가 꽉 차면, 그 객체들은 Old 로 옮겨진다.
    Finally, when Old is close to full, a full GC is invoked.
    마지막으로, Old 가 꽉차기 직전에 FullGC 가 발동된다.

The goal of GC tuning in Spark is to ensure that only long-lived RDDs are stored in the Old generation and that the Young generation is sufficiently sized to store short-lived objects.

Spark 에서 GC 튜닝의 목적은 오래 산 RDD 들이 old 세대에 저장하는 것과, Young 세대는 짧게 사는 객체들을 저장할 충분한 크기를 갖는 것이다.

This will help avoid full GCs to collect temporary objects created during task execution.

task 를 실행하는 동안 생성되는 임시 객체를 수집하기 위해 full GC 를 피할 수 있도록 도와준다.

Some steps which may be useful are:
유용할 수 있는 몇 가지 스텝은 다음과 같다.

  • Check if there are too many garbage collections by collecting GC stats.
    GC 수치 수집에 의해 GC 가 너무 많이 발동되는지 확인하라.
    If a full GC is invoked multiple times before a task completes, it means that there isn’t enough memory available for executing tasks.
    만약 task 가 마무리 되기 전에 full GC 가 여러번 발동된다면, 이것은 task 를 실행하기에 충분한 메모리가 없다는 것을 의미한다.
  • If there are too many minor collections but not many major GCs, allocating more memory for Eden would help.
    Major GC 보다 minor GC 가 더 많이 발생한다면, Eden 영역 크기를 더 주는 것이 도움이 될 수 있다.
    You can set the size of the Eden to be an over-estimate of how much memory each task will need.
    각 태스크가 얼마나 많은 메모리를 필요로 할지 과하게 추정해서 Eden 영역 사이즈를 설정하라.
    If the size of Eden is determined to be E, then you can set the size of the Young generation using the option -Xmn=4/3*E.
    만약 Eden 크기가 E 로 결정되었다면, -Xmn=4/3*E옵션을사용해서 Young 영역의 사이즈를 설정할 수 있다.
    (The scaling up by 4/3 is to account for space used by survivor regions as well.)
    (4/3 으로 크기를 올리는 것은 Surv 영역에 의해 사용되는 공간 또한 고려한다.)
  • In the GC stats that are printed, if the OldGen is close to being full, reduce the amount of memory used for caching by lowering spark.memory.fraction;
    출력된 GC 수치에서, OldGen 영역이 거의 꽉 찼다면, spark.memory.fraction 을 줆여서 캐싱을 위한 메모리 양을 줄여야한다.
    it is better to cache fewer objects than to slow down task execution.
    작업 속도를 늦추는 것 보다는, 캐싱 객체를 적게 만드는 편이 더 좋다.
    Alternatively, consider decreasing the size of the Young generation.
    대안으로 Young 영역의 크기를 줄이는 것도 고려해봐라.
    This means lowering -Xmn if you’ve set it as above.
    이것은, 위에서 말한대로 -Xmn 옵션으로 크기를 줄이는 걸 의미한다.
    If not, try changing the value of the JVM’s NewRatio parameter.
    혹은, JVM 의 NewRatio 파라미터 값을 바꾸는 걸 시도해봐라.
    Many JVMs default this to 2, meaning that the Old generation occupies 2/3 of the heap.
    많은 JVM 의 기본 값은 2로 되어있는데, 이것은 old 영역이 힙메모리의 2/3 을 차지한다는 것을 의미한다.
    It should be large enough such that this fraction exceeds spark.memory.fraction.
    이것은 spark.memory.fraction 을 넘는 비율이 되도록 충분히 커야 한다.
  • Try the G1GC garbage collector with -XX:+UseG1GC.
    -XX:+UseG1GC 옵션으로 G1GC 사용을 하라.
    It can improve performance in some situations where garbage collection is a bottleneck.
    GC 가 보틀넥이 되는 몇몇 상황에서 성능을 개선시켜준다.
    Note that with large executor heap sizes, it may be important to increase the G1 region size with -XX:G1HeapRegionSize.
    큰 executor 힙 사이즈를 사용한다면, -XX:G1HeapRegionSize 옵션으로 G1 영역 크기를 증가하는 것이 중요할 지 모른다.
  • As an example, if your task is reading data from HDFS, the amount of memory used by the task can be estimated using the size of the data block read from HDFS.
    예를 들어 task 가 HDFS 로부터 데이터를 읽는 중이라면, task 에 의해 사용되는 메모리의 크기는 HDFS 로부터 읽는 데이터 블럭의 크기를 사용하여 추정된다.
    Note that the size of a decompressed block is often 2 or 3 times the size of the block.
    종종 압축을 푼 블럭의 크기는 블럭 크기의 두 세배이다.
    So if we wish to have 3 or 4 tasks’ worth of working space, and the HDFS block size is 128 MiB, we can estimate the size of Eden to be 4*3*128MiB.
    그래서 서너개의 task 가 동작중이고 HDFS 크기가 128mb 라면, Eden 의 사이즈는 4(task 수) x 3(block 수) x 128(block 크기) 라고 추정할 수 있다.
  • Monitor how the frequency and time taken by garbage collection changes with the new settings.
    새로운 세팅을 적용 한 이후, GC 가 얼마나 빈번하게 일어나는지 또 얼마나 걸리는지 모니터링하라.

Our experience suggests that the effect of GC tuning depends on your application and the amount of memory available.
GC 튜닝의 영향은 사용자 application 과 가용한 메모리 크기에 따라 달라진다.
There are many more tuning options described online, but at a high level, managing how frequently full GC takes place can help in reducing the overhead.
온라인에는 더 많은 튜닝 옵션들이 설명되어있지만, 전반적으로 볼 때,  full GC 가 얼마나 빈번히 일어나는지 관리하는 것은 오버헤드를 줄이는 데 도움이 된다.

GC tuning flags for executors can be specified by setting spark.executor.defaultJavaOptions or spark.executor.extraJavaOptions in a job’s configuration.

executor 를 위한 GC 튜닝 flags 는, job 의 설정에서 spark.executor.defaultJavaOptions 혹은 spark.executor.extraJavaOptions 를 세팅하는 것으로 명시할 수 있다.

 

 

 

+ Recent posts