Spark #17 : Spark UI

Bana gore spark ile verimli joblar yazmanin anahtari problemleri iyi analiz etmek ve gerekli optimizasyonlari yapabilmek. Olcemedigin bir seyi iyilestiremezsin derler. Tam bu noktada SparkUI cok degerli bilgiler sunarak calismakta olan Spark job'unu derinlemesine analiz etmemize olanak sagliyor. 

Herhangi bir spark driver program ayaga kalktiginda, basit bit web server calistirarak mevcut program hakinda bilgiler verecektir. Test etmek icin spark-shell'i acip, localhost:4040 adresine gidiyoruz. 


Jobs
Default aktif tab jobs tabidir. Her bir action, yeni bir spark job anlamina gelir. Cunku daha once de bahsetmistik, her bir action, tum execution dag'inin basta calistirilmasini gerektirir. Bu yuzden listelenen job'lar uzerinde de aciklama olarak cagrilan action ve hangi satirda oldugu gorulebilir. 

Tekrar spark-shell'e donup, bir RDD olsuturp bir action calistiralim:

> val nums = sc.parallelize(1 to 1000000)
> nums.count


Bunu yaptiktan sonra SparkUI sekmesinde refresh edersek, calistirilmis olan job'u gorebiliriz.


Stage ve task
Sag tarafta bu job'un kac stage'den olsutugunu da gorebiliyoruz. Bir stage, shuffle yapilmadan yapilabilecek islemlerin tamamdiri. Yani shuffle gerektigi noktadan itibaren yeni bir stage olusturulur. Biz burada basit bir count calistirdigimiz icin tek bir stage'imiz oldugu goruluyor. Onun da yaninda tum stage'ler icin toplamda kac task oldugu gorulebilir. 

Task ise, spark'in paralelde calistirdigi en kucun is parcasidir. Burada 1 milyon elemani olan bir RDD uzerinde count calistirdik. Benim makinemde 6 core oldugu icin toplamda 6 partition olusturdu spark. Bu yuzden de count islemi icin 6 task olusturup paralelde bunlari calistirdi. Ilk etapta her bir partition kendi coun degerini aldi ve daha sonra bu degerler shuffle edilerek driver programda enson netice hesaplandi. 

Stages sekmesine tiklar ve ilgili (tek bir tane var zaten) stage'e tiklarsak bize o stage icerisinde calistirilan task'larin listesini gosterecektir. 


Locality level
Taskin, uzerinde calistigi partitiona olan uzakligidir diyebiliriz. Spark data-locality'e gore hareket etmeye calisir demistik. Yani her task mumkun oldugunca ilgili partition'a yakin olmalidir. Data locality hakkinda guzel bir kaynak surada. Alabilecegi degerler su sekildedir:

PROCESS_LOCAL - Data ve task ayni process icerisinde yeraliyor (biz lokalde calistirdigimiz icin bu degere sahip). Data dedigimiz partition, RAM'de bulunmakta. 

NODE_LOCAL - Data ve task ayni makinede ancak farkli executor process'leri icerisindeler. Bu locality bir onceki process_local'den daha yavastir cunku data'nin tasinmasini gerektirir.

RACK_LOCAL - Data ve task ayni rack icerisinde farkli node'larda bulunuyor anlamina gelir. Bu durumda network uzerinde data tasinacaktir. Ancak farkli rack'lardan data tasimaktan daha az maliyetli olacaktir. 

NO_PREF - Hic bir tercih yok

ANY - Data ve task ayni rack icerisinde degil. 

Duration ve data skew
Buradaki diger bir onemli stun da her bir taskin ne kadar surdugunu gosteren duration stunu. Bu 6 task da paralel bir sekilde ayni donanim ile calistirildigina gore uc asagi bes yukari ayni surede tamamlanmasi gerekir. Ama eger tum tasklar tamamlaniyor ve bir task cok uzun suruyorsa burada data-skew var demektir. Yani partition'larin buyuklukleri esit degil, hatta cogu data tek bir partitiona toplanmis anlamina gelir. Bu da kotu bir data-partitioning stratejisinin urunudur. Yani datanin cogu tek bir partitiona toplanmis ve bu islemin paralelde yapilabilmesinin onune engel konulmustur. Bu konuya ileride daha detayli deginecegiz. 

Storage
Spark UI'daki diger bir sekme de Storage sekmesidir. Simdi bu sayfaya giderseniz bos oldugunu goreceksiniz. Cunku henuz storage ile ilegili birsey yapmadik. spark-shell'de:

> nums.persist
> nums.count

islmei yaparsak bu sefer bu RDD'yi hafizada persist etmis oluruz. Baska bir degisle bu RDD'yi kullanacak baska bir action yazilir ise, bu kisimlar tekrardan compute edilmeyecek ve direk hafizadan okunacaktir. Simdi Spark UI'i refresh edersek,


seklinde, persist edilen RDD'yi gorebiliriz. Burada 6 partition oldugu ve hafizada de-serialized seklinde tutuldugunu gorebiliyoruz. Ayrica toplam ne kadar yer kapladigi bilgisi de var. RDD Name stunundaki linke tiklyarak her bir partition hakkinda daha da detayli bilgi alabiliriz.

Environment
Bu sekmede ise Spark'in calisma kosullariyla ilgili bilgi alabiliriz. Kullanimda olan class path entry'leri, spark icin verilmis argumanlar, resource istekleri gibi cok genis yelpazede bilgilere erisilebilir. Ozellikle spark job'unun istenen argumanlarla calistirilip calistirilmadigini debug etmek icin cok kullanisli bir sekmedir. 

Executors
Bu sekme sayesinde driver da dahil olmak uzere clusterdaki tum makinelerle ilgili bilgilere ulasilabilir. Lokalde calistirdigim icin sadece driver executor'a sahibim. Ama normalde cluster'da birden fazla makine bulunacaktir. 

Burada her bir node'un ne kadar data okuyup yazdigi, ne kadar data shuffle ettigi gorulebilir. Eger spark context hala canli ise, her bir executor icin thread dump alinabilir ve detayli debugging yapilabilir.  

Daha fazlasi icin bkz: https://databricks.com/blog/2015/06/22/understanding-your-spark-application-through-visualization.html

Gorusmek uzere.



Yorumlar

Bu blogdaki popüler yayınlar

Python'da Multithreading ve Multiprocessing

Threat Modeling 1

Encoding / Decoding