

Spark is the core component of Teads’s Machine Learning stack. We use it for many ML applications, from ad performance predictions to user Look-alike Modeling. A Sparkot olyan intenzív munkák feldolgozására is használjuk, mint például az eszközök közötti szegmens kiterjesztése vagy a parketta az SSTables transzformációhoz az adatok Cassandra-ba történő betöltéséhez.
A Spark használatával rendszeresen elérjük klasztereink erőforrásainak határait a memória, a lemez vagy a CPU szempontjából. A skála-out csak tolja vissza a kérdést, így van, hogy a kezünket piszkos.
itt található a Spark 2.2.0 legjobb gyakorlatainak és optimalizálási tippjeinek gyűjteménye a jobb teljesítmény és a tisztább Spark kód elérése érdekében, amely magában foglalja:
- hogyan lehet kihasználni a volfrámot,
- végrehajtási terv elemzése,
- adatkezelés (gyorsítótár, műsorszórás),
- felhővel kapcsolatos optimalizálások (beleértve az S3-at is).
frissítés 07/12/2018, Lásd még a második részt, amely a hibaelhárítási trükköket és a külső adatforrás-kezelést tartalmazza.
Ez a józan ész, de a kód teljesítményének javításának legjobb módja a Spark erősségeinek megragadása. Az egyik a volfrám.
szabvány az 1.5-ös verzió óta a Tungsten egy Spark SQL komponens, amely nagyobb teljesítményt nyújt a Spark műveletek bytecode-ban történő átírásával, futásidőben. A Tungsten elnyomja a virtuális funkciókat és kihasználja a csupasz fém teljesítményét azáltal, hogy a CPU és a memória hatékonyságára összpontosít.
annak érdekében, hogy a lehető legtöbbet hozzuk ki a volfrámból, a következőkre figyelünk:
adatkészlet-struktúrák használata
annak biztosítása érdekében, hogy kódunk a lehető legnagyobb mértékben részesüljön a Tungsten-optimalizálásból, az alapértelmezett adatkészlet-API-t használjuk a Scala-val (az RDD helyett).
a Dataset mindkét világ legjobbjait hozza létre relációs (DataFrame) és funkcionális (RDD) transzformációk keverékével. Ez az API a legfrissebb, és növeli a típusbiztonságot, valamint a jobb hibakezelést és a sokkal olvashatóbb egységteszteket.
azonban kompromisszummal jár, mivel a térkép és a szűrő függvények rosszabbul teljesítenek ezzel az API-val. A keret nélküli ígéretes megoldás ennek a korlátozásnak a kezelésére.
kerülje a felhasználó által definiált függvényeket (UDF-ek) amennyire csak lehetséges
UDF használata deserializációt jelent az adatok klasszikus Scala-ban történő feldolgozásához, majd újraszerkesztéséhez. Az UDF-ek helyettesíthetők Spark SQL funkciókkal, már sok van belőlük, és rendszeresen újakat adnak hozzá.
az UDFs elkerülése nem generálhat azonnali fejlesztéseket, de legalább megakadályozza a jövőbeni teljesítményproblémákat, ha a kód megváltozik. Továbbá, a beépített Spark SQL funkciók használatával csökkentettük tesztelési erőfeszítéseinket, mivel minden a Spark oldalán történik. Ezeket a funkciókat a JVM szakértői tervezték, így az UDF-ek valószínűleg nem érnek el jobb teljesítményt.
például a következő kód helyettesíthető a beépített coalesce funkcióval:
def currency = udf(
(currencySub: String, currencyParent: String) ⇒
Option(currencyParent) match {
case Some(curr) ⇒ curr
case _ ⇒ currencySub
}
)
ha nincs beépített csere, akkor is lehetséges a Catalyst (Spark SQL optimizer) kifejezésosztályának megvalósítása és kiterjesztése. Jól fog játszani a kód generálásával. További részletekért Chris Fregly itt beszélt róla (lásd az 56.dia). Ezzel közvetlenül hozzáférünk a Tungsten formátumhoz, megoldja a sorosítási problémát és a teljesítményt.
kerülje a felhasználó által definiált összesített függvények (UDAFs)
az UDAF SortAggregate műveleteket generál, amelyek lényegesen lassabbak, mint a HashAggregate. Például, amit egy udaf írása helyett teszünk, amely kiszámítja a medián egy beépített ekvivalens (kvantilis 0,5):
df.stat.approxQuantile("value”, Array(0.5), 0)
az approxQuantile függvény a Greenwald-Khanna algoritmus variációját használja. Esetünkben végül 10 – szer gyorsabb volt, mint az egyenértékű UDAF.
kerülje az UDF-eket vagy Udaf-okat, amelyek egynél több dolgot végeznek
a szoftveres kivitelezés alapelvei nyilvánvalóan érvényesek a big data dolgok írásakor (csinálj egy dolgot, és csináld jól). Az UDF-ek felosztásával a kapott kód egy részéhez beépített funkciókat tudunk használni. Ez nagyban leegyszerűsíti a tesztelést is.
2-nézz a motorháztető alá
A Spark végrehajtási tervének elemzése egyszerű módja a lehetséges fejlesztések észlelésének. Ez a terv szakaszokból áll, amelyek a Spark fizikai végrehajtási egységei. Amikor újraírjuk a kódunkat, az első dolog, amit keresünk, az abnormális számú szakasz. A gyanús terv lehet egy igénylő 10 szakaszok helyett 2-3 egy alapvető join művelet két DataFrames.
a Sparkban és általánosabban az elosztott számítástechnikában az adatok hálózaton keresztüli küldése (más néven Shuffle a Sparkban) a legdrágább művelet. A keverések drágák, mivel magukban foglalják a lemez I / O-t, az adatok sorosítását és a hálózati I/O-t.olyan műveletekhez szükségesek, mint a Join vagy a groupBy, és a szakaszok között történnek.
ezt figyelembe véve a szakaszok számának csökkentése nyilvánvaló módja a munka optimalizálásának. Használjuk a .magyarázza el a(true) parancsot, hogy megjelenítse a végrehajtási tervet, amely részletezi a feladat összes lépését (szakaszát). Itt van egy példa:
The Directed Acyclic Graph (DAG) in Spark UI can also be used to visualize the task repartition in each stage.
Az optimalizálás nagyban támaszkodik mind az adatok ismeretére, mind azok feldolgozására (beleértve. üzleti logika). A Spark SQL optimalizálás egyik korlátja a Catalyst segítségével az, hogy “mechanikus” szabályokat használ a végrehajtási terv optimalizálásához (a 2.2.0-ban).
mint sokan mások, vártunk egy költség-alapú optimalizálási motor túl broadcast csatlakozás kiválasztása. Most úgy tűnik, hogy elérhető a 2.3.0-ban, ezt meg kell vizsgálnunk.
3-Ismerje meg adatait és kezelje hatékonyan
láttuk, hogyan lehet javítani a munka teljesítményét a végrehajtási terv áttekintésével, de rengeteg lehetséges fejlesztés is van az adatoldalon.
erősen kiegyensúlyozatlan adatkészletek
annak gyors ellenőrzéséhez, hogy minden rendben van-e, áttekintjük az egyes feladatok végrehajtási időtartamát, és heterogén folyamatidőt keresünk. Ha az egyik feladat lényegesen lassabb, mint a többi, akkor meghosszabbítja a munka teljes időtartamát, és pazarolja a leggyorsabb végrehajtók erőforrásait.
meglehetősen könnyű ellenőrizni a min, max és medián időtartamot a Spark UI-ban. Itt egy kiegyensúlyozott példa: