2015-11-27 17 views
5

Używam pojedynczej maszyny Spark Standalone, z pamięcią 128G i 32 rdzeniami. Poniżej znajdują się ustawienia, które uważam za istotne dla mojego problemu:Aplikacja Spark - Java.lang.OutOfMemoryError: Przestrzeń sterty Java

spark.storage.memoryFraction  0.35 
spark.default.parallelism  50 
spark.sql.shuffle.partitions  50 

Mam aplikację Spark, w której istnieje pętla na 1000 urządzeń. Z każdą pętlą (urządzeniem) przygotowuje wektor cech, a następnie wywołuje k-średnich MLLib. W czasie od 25 do 30 iteracji pętli (przetwarzanie urządzenia od 25 do 30) pojawia się błąd "Java.lang.OutOfMemoryError: Java heap space".

Próbowałem memoryFraction z 0,7 do 0,35, ale to nie pomogło. Próbowałem również równoległości/partycji do 200 bez powodzenia. Opcją JVM jest "-Xms25G -Xmx25G -XX: MaxPermSize = 512m". Mój rozmiar danych to tylko około 2G.

Oto stos ślad:

java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2271) 
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) 
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) 
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153) 
    at java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java:1841) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1533) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) 
    at scala.collection.mutable.HashMap$$anonfun$writeObject$1.apply(HashMap.scala:138) 
    at scala.collection.mutable.HashMap$$anonfun$writeObject$1.apply(HashMap.scala:136) 
    at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:230) 
    at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:40) 
    at scala.collection.mutable.HashTable$class.serializeTo(HashTable.scala:125) 
    at scala.collection.mutable.HashMap.serializeTo(HashMap.scala:40) 
    at scala.collection.mutable.HashMap.writeObject(HashMap.scala:136) 
    at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 

Na początku, aplikacja wygląda dobrze, ale po to trwa chwilę i procesów coraz więcej urządzeń, sterty Java zajmuje stopniowo i pamięci nie została wydana przez JVM. Jak zdiagnozować i rozwiązać taki problem?

+0

Próbuje serializować dane, być może bardzo duże o danych. Proponuję zwiększyć maksymalny rozmiar sterty, aby powiedzieć 100 GB zamiast 25 GB. –

+0

Próbuję teraz sterty wielkości 100G. Dzieki za sugestie. – wdz

+0

Czy próbowałeś ustawić wartość spark.rdd.compress na wartość true? –

Odpowiedz

1

Zawsze można użyć narzędzi do profilowania, takich jak visualVM. do monitorowania wzrostu pamięci. Mam nadzieję, że używasz 64-bitowej maszyny JVM, a nie 32-bitowej maszyny JVM. Proces 32-bitowy może wykorzystywać tylko pamięć 2GB, więc ustawienie pamięci zasadniczo nie będzie użyteczne. Mamy nadzieję, że to pomaga

+0

Dziękujemy za polecenie visualVM. Próbuję teraz monitorować wykorzystanie pamięci. BTW, używam 64-bitowego JVM. – wdz

0

Opcje JVM nie są wystarczające do skonfigurowania pamięci Spark, należy również ustawić spark.driver.memory (dla sterownika, obv.) I spark.executor.memory (dla pracowników). Te są ustawione domyślnie na 1 gb. See this thorough guide, aby uzyskać więcej informacji. Właściwie to zachęcam do przeczytania, jest tam mnóstwo rzeczy, a zapoznanie się z nimi na pewno się opłaci.

+0

W moim ustawieniu mam "spark.driver.memory 16G" i "spark.executor.memory 96G". W rzeczywistości przeszedłem dokumentację konfiguracji Sparka, ale nadal nie mogłem rozwiązać problemu OOM. Próbuję visualVM teraz, aby zobaczyć, co dzieje się w kupie. – wdz

2

Oprócz kierowcy i pamięci Executor, proponuję spróbować następujące opcje: -

  1. Przełącz do Kryo serializacji - http://spark.apache.org/docs/latest/tuning.html#data-serialization
  2. Zastosowanie MEMORY_AND_DISK_SER_2 dla RDD wytrwałości.

Byłoby dobrze, gdyby można było opublikować kod.

+0

Dzięki za sugestię! Użyłem już serializacji Kryo. Ponieważ MEMORY_AND_DISK_SER_2 jest znacznie wolniejsza niż MEMORY_ONLY, niechętnie go używam, chyba że nie mam innego wyboru. – wdz

+0

Zgadzam się, ale celem sugerowania "MEMORY_AND_DISK_SER_2" było upewnienie się, że twoja praca przynajmniej ukończyła. Dzięki temu sprawdzisz, czy twoja logika jest poprawna, ale nie jest zoptymalizowana, możemy ją dostroić, by uzyskać lepszą wydajność, dzięki czemu będzie ona całkowicie dostępna w pamięci. – Sumit

+0

Spróbuję wybrać opcję MEMORY_AND_DISK_SER_2. – wdz

Powiązane problemy