portaldacalheta.pt
  • Põhiline
  • Tooteinimesed Ja Meeskonnad
  • Ux Disain
  • Protsess Ja Tööriistad
  • Andmeteadus Ja Andmebaasid
Tagumine Ots

Mälulekkide silumine Node.js-i rakendustes



Kunagi sõitsin Audiga, mille sees oli V8 topeltturbo mootor, ja selle jõudlus oli uskumatu. Sõitsin kell 3 hommikul Chicago lähedal IL-80 maanteel 140MPH paiku kell 3 hommikul, kui teel polnud kedagi. Sellest ajast peale on termin “V8” minu jaoks seotud suure jõudlusega.

Node.js on Chrome'i V8 JavaScripti mootorile ehitatud platvorm kiirete ja skaleeritavate võrgurakenduste hõlpsaks loomiseks.

Ehkki Audi V8 on väga võimas, olete siiski piiratud oma bensiinipaagi mahutavusega. Sama kehtib ka Google'i V8 kohta - Node.js-i taga olev JavaScripti mootor. Selle jõudlus on uskumatu ja Node.js-l on palju põhjuseid töötab hästi paljude kasutusjuhtumite korral , kuid teid piirab alati kuhja suurus. Kui peate oma Node.js rakenduses rohkem taotlusi töötlema, on teil kaks valikut: kas vertikaalne skaala või horisontaalne skaala. Horisontaalne skaleerimine tähendab, et peate käitama rohkem samaaegseid rakenduse eksemplare. Kui see on õigesti tehtud, suudate lõpuks esitada rohkem taotlusi. Vertikaalne skaleerimine tähendab, et peate parandama oma rakenduse mälukasutust ja jõudlust või suurendama rakenduse eksemplari jaoks saadaolevaid ressursse.



Mälulekkide silumine Node.js-i rakendustes



Mälulekkide silumine Node.js-i rakendustes Piiksuma

Hiljuti paluti mul töötada ühe ApeeScape'i kliendi Node.js-i rakenduses, et parandada mälulekke probleem. Rakendus, API-server, oli mõeldud selleks, et iga minut saaks töödelda sadu tuhandeid päringuid. Algne rakendus hõivas peaaegu 600 MB RAM-i ja seetõttu otsustasime võtta kuumad API-punktid ja need uuesti rakendada. Üldkulud muutuvad väga kalliks, kui peate teenima palveid.



Uue API jaoks valisime taaskasutamiseks natiivse MongoDB draiveri ja Kue tausttööde jaoks. Tundub väga kerge stäkk, eks? Mitte päris. Tippkoormuse ajal võib uus rakenduse eksemplar tarbida kuni 270 MB RAM-i. Seetõttu kadus minu unistus saada kaks rakenduse eksemplari 1X Heroku Dyno kohta.

Node.js mälulekke silumisarsenal

Memwatch

Kui otsite „Kuidas leida sõlmes lekkeid”, on esimene tõenäoliselt leitud tööriist memwatch . Originaalpakendist loobuti juba ammu ja seda ei hooldata enam. GitHubi lehelt leiate selle uuemad versioonid hõlpsasti hoidla kahvlite loend . See moodul on kasulik, kuna see võib tekitada lekkesündmusi, kui ta näeb, et hunnik kasvab viie järjestikuse prügikollektsiooni ulatuses.



Hunnik

Suurepärane tööriist, mis võimaldab Node.js arendajad hunniku hetktõmmise tegemiseks ja hiljem Chrome'i arendaja tööriistade abil kontrollimiseks.

Sõlme-inspektor

Isegi kasulikum alternatiiv heapdumpile, sest see võimaldab teil ühenduda töötava rakendusega, võtta kuhjaga dump ja isegi siluda ja kompileerida selle käigu pealt.



Spinniks 'sõlme-inspektori' võtmine

Kahjuks ei saa te ühendust luua tooterakendustega, mis töötavad Herokul, kuna see ei võimalda käimasolevatele protsessidele signaale saata. Kuid Heroku pole ainus hostimisplatvorm.

serveripoolne renderdus vs kliendipoolne renderdus

Node-inspektori tegutsemise kogemuse saamiseks kirjutame lihtsa Node.js-i rakenduse, kasutades restify-d ja paneme selle sisse väikese mälulekke allika. Kõik siinsed katsed tehakse Node.js v0.12.7-ga, mis on kokku pandud V8 v3.28.71.19-ga.



var restify = require('restify'); var server = restify.createServer(); var tasks = []; server.pre(function(req, res, next) { tasks.push(function() { return req.headers; }); // Synchronously get user from session, maybe jwt token req.user = { id: 1, username: 'Leaky Master', }; return next(); }); server.get('/', function(req, res, next) { res.send('Hi ' + req.user.username); return next(); }); server.listen(3000, function() { console.log('%s listening at %s', server.name, server.url); });

Siin on rakendus väga lihtne ja sellel on väga ilmne leke. Massiiv ülesandeid kasvab kogu rakenduse eluea jooksul, põhjustades selle aeglustumist ja lõpuks krahhi. Probleem on selles, et me ei lekita mitte ainult sulgemist, vaid ka kogu päringuobjekte.

V8-s asuv GC kasutab maailma peatamise strateegiat, seetõttu tähendab see, et rohkem mälu on objekte, mida kauem kulub prügi kogumiseks. Allpool olevast logist näete selgelt, et rakenduse elu alguses kulub prügi kogumiseks keskmiselt 20 ms, kuid hiljem võtab paarsada tuhat päringut umbes 230 ms. Inimesed, kes üritavad meie rakendusele juurde pääseda, peaksid ootama 230 ms nüüd enam GC tõttu. Samuti näete, et GC-d kutsutakse iga paari sekundi järel, mis tähendab, et iga mõne sekundi tagant on kasutajatel probleeme meie rakendusele juurdepääsemisega. Ja viivitus kasvab üles, kuni rakendus kokku kukub.



[28093] 7644 ms: Mark-sweep 10.9 (48.5) -> 10.9 (48.5) MB, 25.0 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. [28093] 7717 ms: Mark-sweep 10.9 (48.5) -> 10.9 (48.5) MB, 18.0 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. [28093] 7866 ms: Mark-sweep 11.0 (48.5) -> 10.9 (48.5) MB, 23.2 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. [28093] 8001 ms: Mark-sweep 11.0 (48.5) -> 10.9 (48.5) MB, 18.4 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. ... [28093] 633891 ms: Mark-sweep 235.7 (290.5) -> 235.7 (290.5) MB, 357.3 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. [28093] 635672 ms: Mark-sweep 235.7 (290.5) -> 235.7 (290.5) MB, 331.5 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested]. [28093] 637508 ms: Mark-sweep 235.7 (290.5) -> 235.7 (290.5) MB, 357.2 ms [HeapObjectsMap::UpdateHeapObjectsMap] [GC in old space requested].

Need logiread prinditakse, kui rakendus Node.js käivitatakse –Jälg_gc lipp:

node --trace_gc app.js

Oletame, et oleme selle lipuga oma Node.js rakenduse juba käivitanud. Enne rakenduse ühendamist sõlme-inspektoriga peame saatma selle töötavale protsessile signaali SIGUSR1. Kui käivitate Node.js klastris, veenduge, et oleksite ühendatud ühe orjaprotsessiga.



kill -SIGUSR1 $pid # Replace $pid with the actual process ID

Seda tehes paneme rakenduse Node.js (täpsemalt V8) silumisrežiimi. Selles režiimis avab rakendus pordi 5858 automaatselt V8 silumisprotokoll .

Meie järgmine samm on käivitada sõlmede inspektor, mis loob ühenduse töötava rakenduse silumisliidesega ja avab pordil 8080 teise veebiliidese.

$ node-inspector Node Inspector v0.12.2 Visit http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858 to start debugging.

Juhul kui rakendus töötab tootmises ja teil on tulemüür paigas, saame tunnistada kaugporti 8080 localhostile:

ssh -L 8080:localhost:8080 [email protected]

Nüüd saate avada oma Chrome'i veebibrauseri ja saada täieliku juurdepääsu kaugtootmisrakendusele lisatud Chrome'i arendustööriistadele. Kahjuks ei tööta Chrome'i arendaja tööriistad teistes brauserites.

Leiame lekke!

Mälulekked V8-s ei ole tõelised mälulekked, kuna me teame neid C / C ++ rakendustest. JavaScripti muutujad ei kao tühjusesse, vaid lihtsalt ununevad. Meie eesmärk on leida need unustatud muutujad ja tuletada neile meelde, et Dobby on tasuta.

hea andmebaasi disain ei sisalda:

Chrome'i arendaja tööriistades on meil juurdepääs mitmele profileerijale. Oleme eriti huvitatud Salvestage kuhja jaotused mis töötab ja teeb aja jooksul mitu kuhjaga pilti. See annab meile selge pilgu, millised objektid lekivad.

Alustage hunnikute jaotuste salvestamist ja simuleerime Apache Benchmarki abil meie kodulehel 50 samaaegset kasutajat.

Ekraanipilt

ab -c 50 -n 1000000 -k http://example.com/

Enne uute hetktõmmiste tegemist teostaks V8 prügikoristuse märk-pühkimisega, seega teame kindlasti, et hetktõmmises pole vana prügi.

Lekke parandamine lennult

Pärast kuhjaga jaotamise hetktõmmiste kogumist 3 minutit meil on lõpuks midagi sellist:

Ekraanipilt

Näeme selgelt, et hunnikus on ka hiiglaslikke massiive, palju IncomingMessage, ReadableState, ServerResponse ja Domain objekte. Proovime analüüsida lekke allikat.

Kui valite hunniku diff diagrammi vahemikus 20–40, näeme ainult objekte, mis lisati pärast 20-ndat alates profileri käivitamisest. Nii võite välistada kõik tavalised andmed.

Pidades meeles, kui palju igas tüübis objekte süsteemis on, laiendame filtrit 20 sekundilt 1 minutini. Näeme, et juba üsna hiiglaslikud massiivid muudkui kasvavad. „(Massiivi)” all näeme, et palju on objekte „(objekti omadused)”, mille vahemaa on võrdne. Need objektid on meie mälulekke allikas.

Samuti näeme, et ka '(sulgemine)' objektid kasvavad kiiresti.

Võib olla mugav vaadata ka paelu. Stringiloendi all on palju fraase “Hi Leaky Master”. Need võivad anda ka meile aimu.

Meie puhul teame, et stringi „Hi Leaky Master” sai kokku panna ainult marsruudi „GET /” all.

Kui avate hoidjate tee, näete, et sellele stringile on kuidagi viidatud küsima , siis luuakse kontekst ja see kõik lisati mingile hiiglaslikule sulgemiste kogumile.

Ekraanipilt

Nii et praegu teame, et meil on mingisugune hiiglaslik sulgemiste hulk. Lähme ja paneme reaalajas nime kõigile meie sulgemistele vahekaardi Allikad all.

Ekraanipilt

Kui oleme koodi muutmise lõpetanud, võime käskude salvestamiseks ja uuesti kompileerimiseks vajutada klahvikombinatsiooni CTRL + S!

Nüüd salvestame veel ühe Hunnikute eraldamise hetktõmmis ja vaata, millised sulgemised hõivavad mälu.

nimetatakse ebaefektiivsust, mille on tekitanud üha rohkem inimesi koos töötades

See on selge SomeKindOfClojure () on meie kaabakas. Nüüd näeme seda SomeKindOfClojure () mõnele nimega massiivile lisatakse sulgemisi ülesandeid globaalses ruumis.

On lihtne mõista, et see massiiv on lihtsalt kasutu. Saame seda kommenteerida. Kuidas aga vabastada mälu juba hõivatud mälust? Väga lihtne, määrame lihtsalt tühja massiivi ülesandeid ja järgmise taotlusega tühistatakse see ja mälu vabaneb pärast järgmist GC sündmust.

Ekraanipilt

Dobby on tasuta!

Prügielu V8-s

Noh, V8 JS-il pole mälulekkeid, on ainult unustatud muutujad.

Noh, V8 JS-il pole mälulekkeid, on ainult unustatud muutujad. Piiksuma

V8 kuhi on jagatud mitmeks erinevaks ruumiks:

  • Uus ruum : See ruum on suhteliselt väike ja selle suurus jääb vahemikku 1–8 MB. Enamik objekte on siin eraldatud.
  • Vana osutiruum : Omab objekte, millel võivad olla viited teistele objektidele. Kui objekt elab uues ruumis piisavalt kaua, siis viiakse see vanasse osutiruumi.
  • Vana andmeruum : Sisaldab ainult algandmeid, näiteks stringe, lahtrites olevaid numbreid ja lahtriteta topeltmassiive. Objektid, mis on GC-d uues ruumis piisavalt kaua üle elanud, liigutatakse ka siia.
  • Suur objektiruum : Selles ruumis luuakse liiga suured objektid, mis sobivad teistesse ruumidesse. Igal objektil on mälus oma mmap ‘piirkond
  • Koodiruum : Sisaldab JIT-kompilaatori loodud koostekoodi.
  • Lahtriruum, omaduste lahtriruum, kaardiruum : Selles ruumis on Cell s, PropertyCell s ja Map s. Seda kasutatakse prügiveo lihtsustamiseks.

Iga ruum koosneb lehtedest. Leht on operatsioonisüsteemist mmap eraldatud mälupiirkond. Iga leht on alati 1 MB suurune, välja arvatud suures objektiruumis olevad lehed.

V8-l on kaks sisseehitatud prügikoristusmehhanismi: Scavenge, Mark-Sweep ja Mark-Compact.

Scavenge on väga kiire prügikoristustehnika ja töötab objektides Uus ruum . Scavenge on rakendamine Cheney algoritm . Idee on väga lihtne, Uus ruum jaguneb kaheks võrdseks poolruumiks: Kosmosesse ja Kosmosest. Scavenge GC tekib siis, kui To-Space on täis. See vahetab lihtsalt ruumidesse ja ruumidest ning kopeerib kõik elusad objektid kosmosesse või tõstavad need ühte vanasse ruumi, kui need on üle elanud kaks koristust, ja kustutatakse seejärel kosmosest täielikult. Püüdmised on väga kiired, kuid neil on kahekordse suurusega hunniku hoidmine ja objektide pidev kopeerimine mällu. Pesurite kasutamise põhjus on see, et enamik esemeid sureb noorelt.

Mark-Sweep & Mark-Compact on veel üks V8-s kasutatav prügikoguja tüüp. Teine nimi on täielik prügivedaja. See tähistab kõik elusad sõlmed, pühib seejärel kõik surnud sõlmed ja killustab mälu.

GC jõudluse ja silumise näpunäited

Kuigi veebirakenduste puhul ei pruugi kõrge jõudlus nii suur probleem olla, soovite siiski lekkeid iga hinna eest vältida. Märkimisfaasis kogu GC-s on rakendus tegelikult peatatud, kuni prügivedu on lõpule viidud. See tähendab, et mida rohkem on kuhjas objekte, seda kauem kulub GC sooritamiseks ja kauem peavad kasutajad ootama.

mis on ostjate läbirääkimisjõud

Pange sulgemisele ja funktsioonidele alati nimed

Kui kõikidel teie sulguritel ja funktsioonidel on nimed, on virnade jälgi ja hunnikuid palju lihtsam kontrollida.

db.query('GIVE THEM ALL', function GiveThemAllAName(error, data) { ... })

Vältige kuumades funktsioonides suuri esemeid

Ideaalis soovite vältida suuri funktsioone kuumade funktsioonide sees, et kõik andmed sobiksid Uus ruum . Kõik protsessori ja mäluga seotud toimingud tuleks sooritada taustal. Vältige ka kuumade funktsioonide deoptimeerimise käivitajaid, optimeeritud kuumfunktsioon kasutab vähem mälu kui optimeerimata.

Kuumad funktsioonid tuleks optimeerida

Kiired funktsioonid, mis töötavad kiiremini, kuid tarbivad ka vähem mälu, põhjustavad GC töötamist harvemini. V8 pakub mõningaid abistavaid tööriistu optimeerimata funktsioonide või optimeerimata funktsioonide leidmiseks.

Vältige kuumade funktsioonide korral IC-de polümorfismi

Sisemisi vahemälusid (IC) kasutatakse mõnede kooditükkide käivitamise kiirendamiseks kas objekti atribuudile juurdepääsu vahemällu salvestamise abil obj.key või mõni lihtne funktsioon.

function x(a, b) { return a + b; } x(1, 2); // monomorphic x(1, “string”); // polymorphic, level 2 x(3.14, 1); // polymorphic, level 3

Millal x (a, b) käivitatakse esimest korda, loob V8 monomorfse IC. Kui helistate x teist korda kustutab V8 vana IC ja loob uue polümorfse IC, mis toetab mõlemat tüüpi operandi täisarvu ja stringi. Kui helistate IC-le kolmandat korda, kordab V8 sama protseduuri ja loob teise 3. taseme polümorfse IC.

Siiski on piirang. Pärast IC taseme jõudmist 5-ni (seda saab muuta –Max_inlining_levels lipp) funktsioon muutub megamorfseks ja seda ei peeta enam optimeeritavaks.

On intuitiivselt mõistetav, et monomorfsed funktsioonid töötavad kõige kiiremini ja neil on ka väiksem mälujälg.

Ärge lisage mällu suuri faile

See on ilmne ja tuntud. Kui teil on töötlemiseks suured failid, näiteks suur CSV-fail, lugege seda rea ​​kaupa ja töötlege väikeste tükkidena, selle asemel et laadida kogu fail mällu. On üsna haruldasi juhtumeid, kus üks CSV-rida oleks suurem kui 1 MB, võimaldades seega seda sobitada Uus ruum .

Ärge blokeerige põhiserveri lõime

Kui teil on mõni kuum API, mille töötlemiseks kulub veidi aega, näiteks piltide suuruse muutmise API, teisaldage see eraldi lõimes või muutke see tausttööks. Protsessorimahukad toimingud blokeeriksid põhilõnga, sundides kõiki teisi kliente ootama ja päringuid saatma. Töötlemata päringu andmed koguneksid mällu, sundides kogu GC-d selle lõpuleviimiseks kauem aega võtma.

Ärge loo tarbetuid andmeid

Mul oli kunagi imelik kogemus restify-ga. Kui saadate paarsada tuhat päringut kehtetule URL-ile, suureneb rakenduse mälu kiiresti kuni saja megabaidini, kuni mõni sekund hiljem algab täielik GC, mis tähendab, et kõik peaks normaliseeruma. Selgub, et iga kehtetu URL-i jaoks genereerib restify uue veaobjekti, mis sisaldab pikki virnajälgi. See sundis äsja loodud objekte eraldama aastal Suur objektiruum pigem kui sisse Uus ruum .

Juurdepääs sellistele andmetele võib olla arendamise ajal väga kasulik, kuid loomulikult pole seda tootmisel vaja. Seetõttu on reegel lihtne - ärge genereerige andmeid, kui te seda kindlasti ei vaja.

Tunne oma tööriistu

Viimane, kuid kindlasti mitte vähem oluline on teada oma tööriistu. Seal on erinevaid silujaid, lekkekogureid ja kasutusgraafikute genereerijaid. Kõik need tööriistad aitavad teil tarkvara kiiremaks ja tõhusamaks muuta.

Järeldus

Rakenduse jõudluse võti on V8 prügiveo ja koodi optimeerija töö mõistmine. V8 kompileerib JavaScripti natiivkoosseisu ja mõnel juhul võib hästi kirjutatud kood saavutada GCC kompileeritud rakendustega võrreldava jõudluse.

Ja kui te mõtlete, töötab minu ApeeScape'i kliendi uus API-rakendus, ehkki on arenguruumi, väga hästi!

Joyent avaldas hiljuti uue versiooni Node.js-ist, mis kasutab üht V8 uusimat versiooni. Mõni Node.js v0.12.x jaoks kirjutatud rakendus ei pruugi uue v4.x väljaandega ühilduda. Rakenduste toimivus ja mälukasutuse paranemine on Node.js uues versioonis siiski tohutu.

Tüpograafia anatoomia nõtkuste lahutamine (koos infograafikaga)

Tööriistad Ja Õpetused

Tüpograafia anatoomia nõtkuste lahutamine (koos infograafikaga)
Kuidas ehitada ja säilitada kaugkultuuri

Kuidas ehitada ja säilitada kaugkultuuri

Puldi Tõus

Lemmik Postitused
Äriplaani anatoomia
Äriplaani anatoomia
Ladina-Ameerika ühinemiste ja ühinemiste parimad tavad
Ladina-Ameerika ühinemiste ja ühinemiste parimad tavad
Tarkvara kulude hindamine agiilses projektijuhtimises
Tarkvara kulude hindamine agiilses projektijuhtimises
Andekus pole kaup
Andekus pole kaup
Veebi juurdepääsetavus: miks W3C standardeid sageli eiratakse
Veebi juurdepääsetavus: miks W3C standardeid sageli eiratakse
 
Bränding on surnud, CX Design on kuningas
Bränding on surnud, CX Design on kuningas
Chatbot UX - disaininõuanded ja kaalutlused
Chatbot UX - disaininõuanded ja kaalutlused
Uus ettevõtluslaine
Uus ettevõtluslaine
Optimeeritud järjestikune keskmine kvantimise teisendus
Optimeeritud järjestikune keskmine kvantimise teisendus
Kasutajauuringute väärtus
Kasutajauuringute väärtus
Lemmik Postitused
  • tarkvaratehnika projektdokumentatsioon
  • c ettevõtted pakuvad omanikele suuremat õiguskaitset kui ettevõtted.
  • parimad tegevjuhi kirjad aktsionäridele
  • kui palju on Interneti-tutvumise veebisaite
  • kas ettevõtte sotsiaalne vastutus suurendab kasumit
  • console.log ei ole funktsioon
Kategooriad
  • Tooteinimesed Ja Meeskonnad
  • Ux Disain
  • Protsess Ja Tööriistad
  • Andmeteadus Ja Andmebaasid
  • © 2022 | Kõik Õigused Kaitstud

    portaldacalheta.pt