Overleaf-Benchmark.pdf
Tiivistelmä
Itse isännöityjen Overleaf-asennusten kapasiteetti mitoitetaan yleensä yhdellä nyrkkisäännöllä: yksi prosessoriydin ja yksi gigatavu muistia viittä–kymmentä samanaikaista käyttäjää kohden. Osoitamme, että tämä sääntö ei ole pelkästään epätarkka vaan rakenteellisesti väärä, koska se olettaa kapasiteettia rajoittavan yhden resurssiulottuvuuden, vaikka todellisuudessa rajoja on kaksi toisistaan riippumatonta, ja koska kaksi ohjelmistoparametria — kumpikaan ei laitteistoon liittyvä — ratkaisee lopputuloksen jopa nelinkertaisella erolla. Mittaamme vakiomuotoista Ayakaleaf Pro v6.2.2 -asennusta hiekkalaatikoidulla käännöksellä (TeX Live 2025) 21 suoritin- ja muistikokoonpanossa QEMU/KVM-vierasjärjestelmissä, joiden isäntäytimien kellotaajuus on lukittu 3,0 GHz:iin. Kuormana on todellinen 63-sivuinen XeLaTeX-opinnäyte, jonka jopa useat sadat eri käyttäjätilit kääntävät samanaikaisesti. Havaitsemme, että alle 32 GiB:n vierasmuistilla ydinmäärällä ei ole juuri merkitystä — 16 GiB:n muistilla 4, 8 ja 16 vCPU:n vierasjärjestelmien mitattu kapasiteetti eroaa alle 8 % — ja että kapasiteettia rajoittaa sen sijaan superlineaarinen muistiraja, joka syntyy TeX Live -puun jaetusta sivuvälimuistista. Selvittääksemme, pätevätkö nämä lait myös suuruusluokkaa suuremmassa mittakaavassa, toistamme mittaussarjan yhdellä 64-ytimisellä, 995 GiB:n palvelimella. Se selviää 1024 samanaikaisesta kylmästä käännöksestä 100 %:n onnistumisasteella — kahdeksankertaisesti säikeidensä määrään nähden — emmekä koskaan saavuta sen ylärajaa. Hyödyllinen luku ei ole tuo yläraja vaan sen alapuolella oleva taitekohta: hännän viive kasvaa 20–40 % jokaista kaksinkertaistusta kohden arvoon asti ja sitten 190 % arvossa . Kapasiteetti, joka ilmoitetaan “suurimpana samanaikaisuutena, joka ei epäonnistu”, liioittelisi siis käyttökelpoista toimintapistettä nelinkertaisesti. Tällä koneella muisti ei koskaan ole rajoittava resurssi; rajana on suoritin yhdessä sen nopeuden kanssa, jolla konttidaemon pystyy ottamaan vastaan uusia hiekkalaatikoita, ja tämä kyllästyy noin 200:n kohdalla riippumatta siitä, kuinka monta käännöstä pyydetään. Tunnistamme lisäksi kaksi toteutustason vaikutusta, jotka eivät näy kapasiteettisuunnittelussa. Ensinnäkin CLSI pakottaa kovakoodatun 65 samanaikaisen käännöksen ylärajan, jota ei voi muuttaa minkään ympäristömuuttujan kautta; sen ylittyessä käyttäjät saavat välittömästi HTTP 503 -vastauksen sen sijaan, että heidät asetettaisiin jonoon. Toiseksi Docker-suorittimen konttikohtainen muistiraja on ollut tehoton sen käyttöönotosta vuonna 2018 lähtien sekä suuruutensa että sijoittelunsa vuoksi, joten muistin loppuminen kaataa koko isäntäkoneen yksittäisen käännöksen sijaan. Samanaikaisuusrajan poistaminen ja oletusarvoisen käännösaikakatkaisun nostaminen 180 sekunnista 300 sekuntiin kasvattaa 8 vCPU / 48 GiB -vierasjärjestelmän mitatun kapasiteetin 64:stä 268 samanaikaiseen käännökseen — 4,2-kertaisesti ilman laitteistokustannuksia. Lopuksi osoitamme, että samanaikaisuus tässä järjestelmässä tuo vain aikajakoa ja että kuormaa rajoittaa pelkästään kellotaajuus. Sovitettu heikkenemislaki antaa tulokseksi , mikä on lähellä täydellistä suhteellista hidastumista, ja kellotaajuussarja koneen koko 1,0–5,5 GHz:n alueella tiivistää kolmekymmentä mittausta yhtälöön , jossa ja jäännöshajonta on 5,1 %. 5,5-kertainen kellotaajuus tuo 5,5-kertaisen nopeutuksen ilman vähenevää hyötyä, ja tässä mielessä kellotaajuus ja ytimet tuovat eri asioita: kellotaajuus nopeuttaa jokaisen käyttäjän käännöstä, ytimet vain päästävät sisään enemmän käyttäjiä.1. Johdanto
Overleaf on hallitseva yhteiskäyttöinen LaTeX-editori, ja sen paikallisesti asennettava jakeluversio on laajalti käytössä yliopistoissa ja tutkimusryhmissä, jotka eivät voi lähettää julkaisemattomia käsikirjoituksia kolmannen osapuolen pilveen. Tällaisen asennuksen mitoittaminen on toistuva käytännön kysymys: kuinka moni ihminen voi kiinteällä laitteistobudjetilla todella painaa “Recompile”-painiketta samaan aikaan? Virallinen ohjeistus on lineaarinen sääntö — suunnilleen yksi ydin ja yksi gigatavu viittä–kymmentä samanaikaista käyttäjää kohden — joka olettaa kapasiteetin skaalautuvan tasaisesti ja yhdessä molempien resurssien mukana. Mittauksemme kumoavat tämän kolmella tavalla.1.1 Kapasiteettia rajoittaa kaksi toisistaan riippumatonta rajaa, ei yksi
Kokoonpano epäonnistuu joko siksi, että muisti loppuu, jolloin Overleaf-pino itse kaatuu ja palauttaa HTTP 502 -vastauksen, tai siksi, että käännökset ylittävät palvelinpuolen aikakatkaisun, jolloin CLSI raportoi tilantimedout gigatavujen muistia ollessa käyttämättä. Näillä kahdella tilalla on täysin erilainen skaalautumiskäyttäytyminen ja erilaiset korjauskeinot. Ytimien lisääminen muistirajoitteiseen kokoonpanoon ei ole pelkästään tehotonta, vaan joskus jopa haitallista: mittasimme kokoonpanoja, joissa ydinmäärän kasvattaminen pienentää kapasiteettia, koska useammat ytimet saavat samanaikaiset käännökset etenemään tahdissa, jolloin niiden muistihuiput osuvat samaan aikaan lomittumisen sijaan.
1.2 Ohjelmistoparametrit ovat laitteistoa ratkaisevampia
Käännösaikakatkaisu on MongoDB:n käyttäjäkohtainen kenttä, jonka oletusarvo 180 s rajoittaa huomaamatta suoritinrajoitteisia kokoonpanoja. Sen nostaminen 300 sekuntiin moninkertaistaa mitatun kapasiteetin jopa 4,2-kertaiseksi samalla laitteistolla. Tästä riippumatta CLSI kieltäytyy yli 65 samanaikaisesta käännöksestä kovakoodatun vakion vuoksi. Mikä tahansa kapasiteettitutkimus — ja mikä tahansa asennus — joka ei huomioi kumpaakin, mittaa ohjelmistoa eikä konetta.1.3 Samanaikaisuus on aikajakoa, ei rinnakkaisuutta
Koska LaTeX-käännös on yksisäikeinen, samanaikaisen käyttäjän palveleminen ytimellä ei saa järjestelmää valmistumaan nopeammin; se saa jokaisen käyttäjän odottamaan suhteellisesti pidempään. Kysymys “kuinka montaa samanaikaista käyttäjää tuetaan” on siksi huonosti asetettu, kunnes päätetään, kuinka kauan käyttäjä on valmis odottamaan. Teemme tämän riippuvuuden näkyväksi ja kvantifioimme sen.1.4 Kontribuutiot
- Kapasiteettimatriisi 21 suoritin- ja muistikokoonpanosta, mitattuna kellotaajuuslukituissa, toistolla varmennetuissa olosuhteissa, ja kunkin kokoonpanon rajoittava tekijä tunnistettuna sen virhesignatuurista.
- Kaksi sovitettua mallia: kapasiteettimalli, joka erottaa superlineaarisen muistirajan suoritinrajasta, ja viivemalli, joka osoittaa puhtaan aikajakokäyttäytymisen.
- Kahden käytössä olevan järjestelmän toteutusongelman tunnistaminen ja kokeellinen vahvistaminen, mukaan lukien kontin muistiraja, joka on ollut toimimaton vuodesta 2018.
- Käännösaikakatkaisun ja kapasiteetin välisen kompromissin kvantifiointi, joka on mielestämme ilmoitettava jokaisen samanaikaisuusluvun yhteydessä.
2. Tausta
2.1 Käännöspolku
Overleafin käännöspyyntö kulkee reittiäweb clsi käännöskontti. Hiekkalaatikoidun käännöksen asennuksessa (SIBLING_CONTAINERS_ENABLED=true) CLSI ei suorita latexmk-ohjelmaa omassa prosessissaan; se pyytää isäntäkoneen Docker-daemonia, johon se pääsee liitetyn socketin kautta, käynnistämään uuden kontin TeX Live -kuvasta niin, että projektihakemisto on liitetty polkuun /compile. Yksi käännös on siis yksi lyhytikäinen kontti, jossa suoritetaan yksi latexmk-prosessi.
Tästä seuraa kolme seurausta, ja kaikki kolme muovaavat tämän artikkelin mittauksia. Ensinnäkin työyksikkö on yksisäikeinen prosessi: XeLaTeX ei rinnakkaistu. Toiseksi käännöskohtainen resurssieristys on mitä tahansa Docker-suoritin pyytää — osoitamme luvussa §6.2, että se ei käytännössä pyydä mitään. Kolmanneksi työjoukkoa hallitsee asiakirjan sijaan TeX Live -puu, noin 32 GiB:n kokoinen vain luku -aineisto, josta jokainen samanaikainen käännös lukee ja jonka ne siksi jakavat isäntäkoneen sivuvälimuistin kautta. Tämä jakaminen on havaitsemamme superlineaarisen muistiskaalautumisen alkuperä.
2.2 Hiekkalaatikoidun käännöksen käyttöönotto
Overleafin yhteisöversio suorittaalatexmk-ohjelman itse sovelluskontin sisällä. Ayakaleaf Pro voi Overleaf Server Pron tavoin suorittaa sen sijaan jokaisen käännöksen sisarkontissa — kontissa, jonka sovellus käynnistää isäntäkoneen Docker-daemonissa sen sijaan, että se olisi sisäkkäin sovelluskontin sisällä. Kaksi Toolkit-asetusta ottaa tämän käyttöön:
SANDBOXED_COMPILES=true, SANDBOXED_COMPILES_SIBLING_CONTAINERS=true ja SANDBOXED_COMPILES_HOST_DIR, joista viimeinen on käännöshakemiston isäntäkoneen polku. Tällä polulla on merkitystä: koska käännöskontin käynnistävä daemon on isäntäkoneen, sille annetun liitoksen on oltava selvitettävissä isäntäkoneen nimiavaruudessa, ei sovelluskontin. Server Pron config/env.sh pakottaa lisäksi tässä tilassa asetuksen TEXLIVE_IMAGE_USER=www-data, jotta käännöskontin kirjoittamien tiedostojen omistajuus on yhdenmukainen.
Varmistus on suoraviivainen: käännöksen aikana isäntäkoneella näkyy kontti nimeltä project-{projectId}-{userId}-{hash}, joka suorittaa latexmk-ohjelmaa TeX Live -kuvasta ja päättyy koodiin 0. Tämä on yksikkö, jonka lukumäärää mittaamme koko artikkelin ajan ja jonka resurssirajojen täydellisestä puuttumisesta raportoimme luvussa §6.2.
Sisarkontit tekevät mittauksesta puhtaan — jokainen käännös on havaittava, itsenäisesti ajoitettu käyttöjärjestelmäentiteetti — mutta ne tarkoittavat myös, että suorittimen ja muistin jakamisesta käännösten välillä päättää vierasjärjestelmän ydin eikä Overleaf. Jokainen tämän artikkelin skaalautumislaki on siis Linuxin ajastimen ominaisuus, kun sitä sovelletaan yksisäikeiseen prosessiin, minkä vuoksi ne ovat niin säännönmukaisia.

clsi noutaa ne. Kumpikaan ei ole hallitseva — projektin käännöskustannuksen määrää 32 GiB:n TeX Live -puu, josta jokainen samanaikainen käännös lukee jaetun sivuvälimuistin kautta.

git-bridge-palvelun kustannuksella. Toolkitin oletus (b), jota mittaamme, on kertoimeltaan yksi, joten yhdelle kaluston jäsenelle mitoitetusta vakiosta tulee koko asennuksen yläraja.

clsi-cache-palvelussa. Projekti kuvataan kaavalla , eli hash-avaruus jaetaan niin moneen yhtä suureen sektoriin kuin sirpaleita on. Tämä on modulo-hajautusta, ei rengaspohjaista johdonmukaista hajautusta: kaluston kasvattaminen kolmesta sirpaleesta neljään jakaa koko avaruuden uudelleen ja siirtää käytännössä jokaisen projektin (a, b). Juuri siksi toteutus tarvitsee eksplisiittisen verkossa tapahtuvan uudelleensirpaloinnin rampin, joka siirtää lineaarisesti kasvavan osuuden projekteista currentShards-joukosta desiredShards-joukkoon aikaikkunan kuluessa, sen sijaan että siirrettäisiin , kuten johdonmukaisen hajautuksen renkaassa. Kun sirpaleen virrankatkaisin laukeaa, suolaa kasvatetaan ja sirpale poistetaan ehdokasluettelosta, joten haku jatkaa eteenpäin epäonnistumisen sijaan (c).
2.3 Kaksi virhetilaa
Jokainen mittaamamme kokoonpano epäonnistuu täsmälleen toisella kahdesta tavasta, ja ero näkyy vastauksen tilakoodista eikä sitä tarvitse päätellä:- Muistin loppuminen — Overleaf-pino itse lakkaa vastaamasta ja pyyntö palauttaa HTTP 502 -vastauksen. Vierasjärjestelmän käytettävissä oleva muisti on epäonnistuvalla tasolla tyypillisesti alle 500 MiB.
- Käännöksen aikakatkaisu — CLSI lopettaa käännöksen käyttäjäkohtaisen aikakatkaisun kohdalla ja raportoi tilan
timedout. Käytettävissä olevaa muistia on epäonnistuvalla tasolla usein useita gigatavuja.
3. Menetelmät
3.1 Testiympäristö ja kellotaajuuden hallinta
Kaikki vierasjärjestelmät toimivat QEMU/KVM:n alla yhdellä Intel Core i9-14900K -isäntäkoneella, jossa on 62 GiB RAM-muistia ja NVMe-tallennus. Vierasjärjestelmä on Ubuntu 24.04, jossa on Docker 29.7 ja Overleaf Toolkit, joka ottaa käyttöön Ayakaleaf Pro v6.2.2:n hiekkalaatikoidulla käännöksellätexlive-full:2025.1-kuvaa vasten.
Tavallinen pöytäkoneen suoritin on huono palvelimen vastine, ellei sen kellotaajuutta hallita. KVM ei tarjoa keinoa asettaa virtuaalista kellotaajuutta: vCPU on isäntäkoneen säie ja toimii sillä taajuudella, jolla isäntäydin toimii. Siksi rajoitamme isäntäkonetta suoraan poistamalla turbon käytöstä ja kiinnittämällä scaling_max_freq-arvon 3,0 GHz:iin jokaisella ytimellä, ja kiinnitämme vierasjärjestelmän vCPU:t fyysisiin P-ytimiin taskset-komennolla. Erolla on merkitystä hybridiydinsuorittimessa: tämän piirin E-ytimien peruskellotaajuus on 2,4 GHz, eivätkä ne pysty saavuttamaan 3,0 GHz:iä turbon ollessa pois käytöstä, joten niille eksynyt ajo mittaa huomaamatta hitaampaa konetta. Täydellä kuormalla varmistamme tasan 3000 MHz:n taajuuden kaikilla kuudellatoista kiinnitetyllä säikeellä. Valvontaskripti tarkistaa tämän invariantin ennen jokaista suorituskykytestiä ja kieltäytyy muuten käynnistymästä; se havaitsi tutkimuksen aikana yhden taajuussäätimen huomaamattoman nollautumisen.
3.2 Toinen testiympäristö: yksi suuri ajokone
QEMU-matriisi eristää yhden muuttujan kerrallaan, mutta sen yläraja on kuusitoista kiinnitettyä säiettä. Selvittääksemme, pätevätkö samat lait vielä suuruusluokkaa korkeammalla, toistimme samanaikaisuussarjan yhdellä suurella palvelimella: yksi AMD EPYC 7773X (Milan-X, 64 ydintä / 128 säiettä, 768 MiB L3-välimuistia) ja 995 GiB RAM-muistia, ajaen samaa Ayakaleaf Pro v6.2.2 -kuvaa samaatexlive-full:2025.1-kuvaa vasten. Toisin kuin QEMU-vierasjärjestelmissä, tämän koneen kellotaajuutta ei ole lukittu: se on tuotantotason palvelin, ja mittaamme sitä sellaisena.
Kaksi operatiivista varotoimea oli välttämättömiä, ja ne kannattaa mainita, koska ilman niitä koe mittaa testivaljaita eikä palvelinta. Ensinnäkin jokainen kontti rajattiin systemd-osioon asetuksella MemoryMax=940 GiB, jotta karkuun lähtenyt mittaussarja kuluttaa loppuun cgroupin eikä isäntäkonetta. Toiseksi hiekkalaatikoidut käännökset luo isäntäkoneen daemon, ja kukin niistä kirjoittaa omaan copy-on-write-kerrokseensa — mitattuna 116 MiB konttia kohden, vaikka 20,6 GiB:n peruskuva on jaettu — joten Dockerin datahakemisto siirrettiin erilliselle NVMe-laitteelle. Mittaussarja arvolla kirjoittaa noin 119 GiB väliaikaisia kerroksia, mikä ei mahdu vakiomuotoiseen juuritiedostojärjestelmään.
3.3 Kuorma
Asiakirja on todellinen 63-sivuinen pro gradu -tutkielma (SJTU-mallipohja), joka käännetään XeLaTeXillalatexmk-ohjelman kautta ja joka sisältää TikZ-kuvia, biblatex-lähdeluettelon käsittelyn ja upotettuja PDF-resursseja — eli realistinen eikä synteettinen kuorma. Yksi käännös kuormittamattomassa vierasjärjestelmässä kestää kaikissa kokoonpanoissa 8,6–9,8 s, ja käytämme tätä vapaan suorituksen perustasona .
3.4 Kuorman tuottaminen
Luomme 512 todellista käyttäjätiliä ja annamme kullekin oman kopion projektista, jotta samanaikaiset käännökset kilpailevat täsmälleen kuten itsenäiset käyttäjät eivätkä jaa projektilukkoa. Pyynnöt lähetetään isäntäkoneelta vierasjärjestelmän välitettyyn porttiin, jotta kuorman tuottaminen ei kuluta vierasjärjestelmän suoritinaikaa. Samanaikaisuus on yhtäaikaista, ei porrastettua. Jokainen istunto muodostetaan ensin — kirjautuminen, CSRF-tunniste, kääntäjän valinta — ja vasta sitten jokainen säie nukkuu yhteiseen, kerran laskettuun ja jaettuun seinäkellohetkeen asti ennen kuin se lähettääPOST /project/:id/compile -pyyntönsä. Ero ei ole saivartelua. Porrastettu ramppi mittaa suoritustehoa vakaassa jonossa; yhtäaikainen purske mittaa, mitä tapahtuu, kun luentosalillinen opiskelijoita painaa samaa painiketta saman määräaikailmoituksen jälkeen, ja juuri tätä ylläpitäjät todella pelkäävät. Nämä kaksi eroavat enemmän kuin vakiokertoimella, koska jälkimmäinen täyttää käännösjonon nopeammin kuin daemon ehtii sitä tyhjentää.
Neljä käytännön estettä oli poistettava ennen kuin purske voitiin toimittaa uskollisesti. Jokainen niistä kannattaa kirjata, koska jokainen heikentää koetta huomaamatta testivaljaiden eikä palvelimen mittaukseksi.
3.4.1 Kaksi nopeusrajoitinta, ei yksi
Overleaf rajoittaa kirjautumisia lähdeosoitetta kohden — 20 yritystä minuutissa — ja kaikki liikenteemme lähtee yhdeltä isäntäkoneelta. Kun jokaiselle simuloidulle käyttäjälle annetaan omaX-Forwarded-For-osoite, tämä raja poistuu, mutta vastaan tulee heti toinen, karkeampi raja: aliverkkokohtainen noin 200 yrityksen minuuttibudjetti. Käyttäjien levittäminen yhtenäiselle lohkolle epäonnistuu siksi 201. tilin kohdalla. Sen sijaan johdamme synteettisen osoitteen käyttäjän indeksistä niin, että peräkkäiset käyttäjät päätyvät eri /24-verkkoihin,
mikä pitää molemmat rajoittimet väljinä koko 1024 käyttäjän joukolle.
3.4.2 Lisätty otsake hylätään oletuksena
Otsakkeen asettaminen ei riitä. Express huomioiX-Forwarded-For-otsakkeen vain vertaisilta, joihin sen on käsketty luottaa, ja Overleafin trustedProxyIps-asetuksen oletusarvo on loopback. Koska kuormageneraattori tavoittaa sovelluksen kontin sillan kautta eikä loopback-rajapinnan kautta, otsake jäsennetään ja heitetään sitten pois, ja jokainen simuloitu käyttäjä romahtaa takaisin yhteen osoitteeseen. Oireena on HTTP 429 -aalto täsmälleen kahdennenkymmenennen kirjautumisen kohdalla, mikä on helppo tulkita väärin palvelimen ylikuormitukseksi. Yhdyskäytäväverkko on lisättävä luottamusketjuun eksplisiittisesti; luvun §4.3 klusteroidussa asennuksessa myös pod- ja service-CIDR:t on lisättävä.
3.4.3 Kuormantasaaja korvaa otsakkeen, joka sen piti säilyttää
Kun instanssi on välityspalvelimen takana, tavanomainenoption forwardfor lisää todellisen asiakkaan osoitteen ketjuun, mikä on oikea toiminta tuotannossa ja juuri väärä tässä: synteettinen osoite syrjäytyy kuormageneraattorin omalla osoitteella. Direktiivi on tarkennettava muotoon option forwardfor if-none, jotta välityspalvelin lisää arvon vain, jos asiakas ei antanut sitä.
3.4.4 Asiakkaalta loppuvat tiedostokahvat ennen kuin palvelimelta loppuu kapasiteetti
Arvolla generaattori pitää auki yli tuhat samanaikaista socketia, ja oletusarvoinen 1024 kahvan pehmeä raja täyttyy istuntojen muodostamisen eikä mittauksen aikana. Virhe on hiljainen: kolme istuntoa ei muodostu ja ajo raportoi 1021 eikä 1024, ja konttimääriä varten komentotulkkia kutsuva näytteenottosäie kuolee virheeseenEMFILE ja katkaisee telemetrian huomaamatta. Generaattorin pehmeää rajaa on nostettava — isäntäkoneemme kova raja oli jo 1048576 — ja ajo toistettava. Raportoimme molemmat ajot luvussa §4.3: korjattu ajo suorittaa 1024/1024 käännöstä mediaanin ollessa 1,2 s:n päässä katkaistusta ajosta, minkä vuoksi pidämme ensimmäistä käyttökelpoisena mutta ei määräävänä.
3.5 Mittausprotokolla
Useat menetelmälliset valinnat osoittautuivat välttämättömiksi toistettavuuden kannalta.3.5.1 Lämmittely
Juuri käynnistetyssä vierasjärjestelmässä sivuvälimuisti on tyhjä, ja ensimmäiset käännökset mittaavat kylmäkäynnistyksen I/O:ta eivätkä vakaan tilan kapasiteettia: sama 2 vCPU / 2 GiB -kokoonpano antaa kylmänä 36,5 s ja lämpimänä 9,8 s, eli 3,7-kertaisen eron. Jokainen kokoonpano suorittaa siksi käynnistyksen jälkeen kaksi hylättävää yksittäisen käännöksen lämmittelyä.3.5.2 Hyväksymiskriteeri
Samanaikaisuustaso hyväksytään vain, jos jokainen käännös onnistuu ja taso kestää toiston. Tämä on tiukempi kuin onnistumisasteen kynnysarvo, ja sillä on merkitystä: 4 vCPU / 16 GiB -kokoonpanossa taso 32 meni kerran läpi 80,2 s:n mediaanilla ja aikakatkaisi sitten kaikki 32 käännöstä toistettaessa, joten raportoimme arvon 31.3.5.3 Haku
Tasot paikannetaan eksponentiaalisella haarukoinnilla mallin ennustamasta lähtöarvosta, minkä jälkeen tehdään tarkka kokonaislukupuolitus. Koska kriteeri on kaikki tai ei mitään, taso ratkeaa ensimmäiseen epäonnistumiseen, joten hylkäämme jäljellä olevat käynnissä olevat pyynnöt heti, kun yksi epäonnistuu — paitsi pienillä tasoilla, joilla hylätyt käännökset jumittavat pienen vierasjärjestelmän niin pahasti, ettei se koskaan toivu.3.5.4 Tasojen välinen eristys
Käännöskontit tyhjennetään ja verkkosovellusta kysellään, kunnes se vastaa jälleen, ennen kuin seuraava taso alkaa. Ilman tätä kaatumista seuraava taso kirjaa virheellisen nollan istunnon epäonnistumisen.3.5.5 Isäntäkoneen hygienia
Isäntäkoneen muut virtuaalikoneet sammutettiin: kun 24 GiB isäntäkoneen muistia oli varattuna muualle, sama vierasjärjestelmäkokoonpano raportoi kuormitukseksi 11,7 eikä 3,2 samalla samanaikaisuudella. Isäntäkoneen muistipaine välittyy vierasjärjestelmään ja mitätöi mittauksen.4. Tulokset
4.1 Kapasiteettimatriisi
Taulukko 1 ja kuva 4 esittävät mitatun ylärajan jokaiselle kokoonpanolle. Ensimmäinen yllätys paljastuu, kun taulukkoa lukee riveittäin. 4 GiB:n muistilla 2, 4 ja 8 vCPU:n vierasjärjestelmät saavuttavat kaikki tasan 9 — ytimien nelinkertaistaminen ei muuta mitään. 16 GiB:n muistilla ne saavuttavat 54, 45 ja 57: siirtyminen 4 ytimestä 16 ytimeen tuo 6 %, ja 8-ytiminen vierasjärjestelmä on itse asiassa huonompi kuin 4-ytiminen (§5.2). Vasta 48 GiB:n muistilla ydinmäärä erottaa kokoonpanot ratkaisevasti: 143, 268 ja 331.
Taulukko 1. Onnistuneesti valmistuvien samanaikaisten käännösten enimmäismäärä mitattuna 300 s:n käännösaikakatkaisulla CLSI:n samanaikaisuusrajan ollessa poistettu. Lihavoitu tarkoittaa suoritinrajoitteista kokoonpanoa (käännökset aikakatkaistaan muistia vielä riittäessä); muut ovat muistirajoitteisia (pino kaatuu HTTP 502 -virheeseen). 2 GiB:n rivissä on luvussa §5.2 käsitelty korjaus.
4.2 Samanaikaisuus on aikajakoa
Kuva 5 käy läpi jokaisen samanaikaisuustason kiinteällä 8 vCPU / 16 GiB -vierasjärjestelmällä. Kaksi tilaa erottuu terävällä taitekohdalla täsmälleen yhden käännöksen kohdalla ydintä kohden. Sen alapuolella käännöksen keskimääräinen kesto on tasainen — se muuttuu 8,7 sekunnista arvolla 9,1 sekuntiin arvolla , eli 5 %. Sen yläpuolella aika kasvaa tiukasti suhteessa arvoon : arvoilla mittaamme 18,5 s ja 27,1 s, eli suhteen ihanteellisen suhteen sijaan.

4.3 Vertikaalinen skaalaus 1024 samanaikaiseen käännökseen
Taulukko 2 ja kuva 7 raportoivat suuren ajokoneen mittaussarjan. Jokainen taso on kylmä käännös: ennen jokaista tasoa tyhjennämme jokaisen osallistuvan projektin käännöshakemiston ja CLSI-välimuistin pyynnölläDELETE /project/:id/output, joten mikään taso ei hyödy alemman tason tekemästä työstä. Yksittäisen käännöksen perustaso tällä koneella on 28,8 s, mikä on kylmä luku, eikä sitä pidä verrata aiemmin käytettyyn 8,6–9,8 s:n vakaan tilan perustasoon; QEMU-vierasjärjestelmien kylmä perustaso on 28,3 s, joten säiettä kohden koneet ovat tällä kuormalla kahden prosentin päässä toisistaan.
Taulukko 2. Samanaikaisuussarja yhdellä EPYC 7773X -suorittimella (64 ydintä / 128 säiettä, 995 GiB). Kaikki tasot kylmiä; perustaso 28,8 s. Konttien huippumäärä on samanaikaisesti elossa olleiden hiekkalaatikoiden enimmäismäärä.

4.3.1 Kone ei koskaan epäonnistu
Jokainen taso valmistuu 100-prosenttisesti, mukaan lukien — kahdeksankertaisesti säikeiden määrään nähden. Emme löytäneet tämän koneen kapasiteettirajaa; kärsivällisyytemme loppui ennen kuin sen liikkumavara. Tämä on tutkimuksen ensimmäinen kokoonpano, jossa rajoittava tekijä ei ole muisti: arvolla käännösten cgroup on huipussaan 184 GiB, viidesosa sen 940 GiB:n rajasta, kun taas suoritin on 100 %:n käyttöasteella ja kuormitus on 166.4.3.2 Heikkeneminen on alilineaarista, koska sisäänpääsyä rajoitetaan
Naiivi aikajako ennustaa, että säikeitä maksaa viiveen. Mitattu kustannus on suhteessa yksittäiseen käännökseen, mutta vain suhteessa arvoon — kahdeksankertaisella tarjotun kuorman kasvulla. Syy näkyy kuvassa 7(b) ja taulukon 2 viimeisessä sarakkeessa: vaikka 1024 pyyntöä lähetetään samanaikaisesti, todellisuudessa elossa olevien hiekkalaatikoiden määrä ei koskaan ylitä 205:tä. Daemon ei pysty luomaan kontteja niin nopeasti kuin asiakkaat pyytävät, joten pyynnöt jonoutuvat sisäänpääsyssä sen sijaan, että ne kilpailisivat suorittimella. Jonoutuminen pelastaa tässä hännän, ja se tekee sen vahingossa.4.3.3 Taitekohta on 512:ssa, ei epäonnistumispisteessä
Arvojen ja välillä -viive kasvaa kuorman kaksinkertaistuessa; jokainen aiempi kaksinkertaistus maksoi –. Kapasiteetti ilmoitettuna “suurimpana :nä, joka ei epäonnistu” raportoisi arvon 1024 ja olisi ylläpitäjälle hyödytön: siinä kohdassa hännän odotus on lähes kahdeksan minuuttia.4.4 Käännösaika on kääntäen verrannollinen kellotaajuuteen
Koska kuorma on suoritinrajoitteinen, sen kustannuksen pitäisi skaalautua kuten . Testaamme tämän suoraan käymällä isäntäkoneen kellotaajuuden läpi koneen koko alueella, 1,0–5,5 GHz kymmenessä portaassa, muuten muuttumattomalla vierasjärjestelmällä (kuva 8). Yksittäisen käännöksen aika muuttuu 26,5 sekunnista 4,8 sekuntiin: 5,5-kertainen kellotaajuus tuo 5,5-kertaisen nopeutuksen ilman vähenevää hyötyä missään kohdassa aluetta. Tulo on vakio 2 %:n tarkkuudella kaikilla kymmenellä kellotaajuudella. Normalisointi ydinosuudella tiivistää kaikki kolmekymmentä mittausta — kolme samanaikaisuustasoa kymmenellä kellotaajuudella — yhdeksi vakioksi: jäännöshajonnan ollessa 5,1 % alueella, jolla kellotaajuus itse vaihtelee 5,5-kertaisesti. Kaarevuuden puuttuminen on itsessään tulos: jos kuorma olisi ollut muistikaistan tai I/O:n rajoittama, tasaantuisi suurilla kellotaajuuksilla suorittimen ohittaessa toisen resurssin.
5. Analyysi
5.1 Kaksi rajaa erikseen sovitettuina
Jokainen kokoonpano luokitellaan virhesignatuurinsa perusteella (§2.3), ja muistiraja ja suoritinraja sovitetaan sitten vain niihin kokoonpanoihin, jotka todella törmäävät niihin: jossa on gibitavuina ja vCPU:ina. Muistirajan eksponentti on johdonmukaisesti superlineaarinen, : yhden lisäkäännöksen marginaalinen muistikustannus pienenee kokonaismuistin kasvaessa, noin 312 MiB:stä käännöstä kohden 3 GiB:n vierasjärjestelmässä noin 194 MiB:iin 32 GiB:n vierasjärjestelmässä. Mekanismi on luvussa §2.1 kuvattu TeX Live -puun jaettu sivuvälimuisti: samanaikaiset käännökset lukevat päällekkäisiä fontti- ja makrotiedostoja, joten suurempi välimuisti jakautuu useammalle niistä. Tämän vuoksi naiivi “yksi gigatavu viittä käyttäjää kohden” -sääntö aliarvioi suuria koneita ja yliarvioi pieniä.
5.2 Missä useammat ytimet pahentavat tilannetta
Yhtälö (2) on kahden termin minimi ja siksi monotoninen :n suhteen, mutta mittaukset eivät ole. Havaitsemme kaksi käänteistä tapausta, joissa ytimien lisääminen pienensi kapasiteettia: 16 GiB:n muistilla (54 vs. 45) ja 32 GiB:n muistilla (145 vs. 135). Molemmat esiintyvät muistirajoitteisessa tilassa, ja mekanismi on kummassakin sama: useammilla ytimillä samanaikaiset käännökset etenevät tahdissa ja saavuttavat suurimman muistikokonsa samalla hetkellä, kun taas vähemmillä ytimillä ajastin lomittaa ne ja huiput porrastuvat. Vierasjärjestelmässä, jonka muistivara on jo valmiiksi niukka, porrastus pitää sen hengissä. Keskimääräiseen resurssien käyttöön perustuva kapasiteettimalli ei pysty ilmaisemaan tätä; kyse on huippujen yhteensattumisen ominaisuudesta. Kolmannen näennäisen käänteisen tapauksen, 2 GiB:n muistilla, jätämme nyt huomiotta. Haku kirjaa kapasiteetiksi 2 kahdella vCPU:lla mutta 1 neljällä ja kahdeksalla vCPU:lla, mikä näyttää samalta ilmiöltä. Raakamittausten uudelleentarkastelu paljastaa jotain yksinkertaisempaa: 2 GiB:n muistilla taso onnistui ensimmäisellä yrityksellä kaikilla kolmella ydinmäärällä ja epäonnistui sitten vahvistusajossaan kahdella kolmesta. Taso ei ole kapasiteetti vaan kolikonheitto, ja 2 vCPU:n arvo on heitto, joka sattui osumaan. Raportoimme siksi toistettavan arvon 1 kaikilla kolmella ydinmäärällä emmekä tee erosta johtopäätöksiä. Kirjaamme korjauksen tähän sen sijaan, että muuttaisimme taulukkoa hiljaa, koska hylätty lukema on juuri sellainen, joka olisi tukenut kiinnostavaa väitettä.6. Toteutusta koskevat havainnot
6.1 Kovakoodattu samanaikaisuusraja
Riittävän suurilla vierasjärjestelmillä kapasiteetti pysähtyi täsmälleen 65 samanaikaiseen käännökseen pyydetystä samanaikaisuudesta riippumatta: arvoilla mittasimme onnistumista ja välitöntäunavailable-vastausta konttien määrän pysyessä 65:ssä, useiden gigatavujen muistin ollessa käyttämättä ja käännöksen mediaaniajan pysyessä vakaana 77 sekunnissa — selvästi minkään aikakatkaisun alapuolella.
Syy on CLSI:n vakio:
success=65, unavailable=15, raportoi sen sijaan success=80.
6.2 Toimimaton kontin muistiraja
Käynnissä olevan käännöskontin tarkastelu osoittaa, ettei resurssieristystä ole lainkaan:HostConfig-osion sisään, jossa Docker API odottaa sitä, joten se hylätään — minkä havaittu Memory=0 vahvistaa. Molemmat virheet ovat mukana tiedoston lisänneessä commitissa (9a519f0d3d, maaliskuu 2018), ja ne ovat selvinneet muunnoksesta CoffeeScriptistä, koko tietovaraston uudelleenmuotoilusta ja CJS-to-ESM-siirrosta, joista mikään ei tarkastellut semantiikkaa uudelleen. Huomionarvoista on, että samassa commitissa oleva MAX_OUTPUT = 1024 * 1024 // 1MB on oikein, mikä viittaa lipsahdukseen eikä väärinymmärrykseen.
Seuraus näkyy matalan muistin mittauksissamme. Koska käännöksiä ei rajoiteta, muistin loppuminen ei ilmene siten, että Docker lopettaa yhden ongelmallisen kontin; se kaataa koko vierasjärjestelmän. 2 vCPU / 2 GiB -kokoonpanossa havaitsimme valvontaan käytetyn SSH-istunnon jumittuvan 300 sekunniksi, kuormituksen olevan 68 kahdella ytimellä ja vierasjärjestelmän lopulta käynnistävän itsensä uudelleen. Toimiva konttikohtainen raja heikentäisi toimintaa paljon hallitummin: liian suuri käännös epäonnistuisi ja palvelu säilyisi.
Ainoa raja, joka todella vaikuttaa, on RLIMIT_CPU, joka on asetettu arvoon sekuntia. Se rajoittaa suoritinaikaa, ei seinäkelloaikaa, ja yksittäinen käännös kuluttaa vain noin 9 s suoritinaikaa, joten se ei koskaan rajoita millään samanaikaisuudella; se suojaa patologisilta syötteiltä, kuten karkuun lähteneeltä makrolta. Se on kuitenkin hyödyllinen oraakkeli: arvon Soft:305 havaitseminen vahvistaa, että 300 s:n aikakatkaisuasetus on todella välittynyt konttiin asti.
6.3 Käännösaikakatkaisu on ratkaisevin säädettävä arvo
Käyttäjäkohtaisen kentänfeatures.compileTimeout oletusarvo on 180 s. Suoritinrajoitteisissa kokoonpanoissa tämä ei ole turvamarginaali vaan kapasiteettiasetus, koska kone, joka yhä laskee oikein, julistetaan epäonnistuneeksi. Sen nostaminen 300 sekuntiin — yksi MongoDB-päivitys — muuttaa mitattua kapasiteettia jopa 4,2-kertaisesti (taulukko 3). Yläraja on 600 s, jonka RequestParser.MAX_TIMEOUT pakottaa ja jonka ylittävä arvo katkaistaan hiljaa.
Taulukko 3. Käännösaikakatkaisun vaikutus mitattuun kapasiteettiin.
Kaksi viimeistä riviä ovat tuloksen vastaintuitiivinen puolikas ja syy siihen, että mittasimme jokaisen kokoonpanon uudelleen yhdellä aikakatkaisulla. Muistirajoitteisissa kokoonpanoissa pidempi aikakatkaisu pienentää kapasiteettia, koska jokainen käännös pitää muistijoukkoaan pidempään ja useampi niistä on päällekkäin. Kapasiteettiluku on siksi merkityksetön, ellei kerrota, millä aikakatkaisulla se on mitattu, eikä näitä kahta voi sekoittaa samassa taulukossa.
7. Aiempi tutkimus
7.1 Toimittajan ohjeistus
Overleafin oma laitteistodokumentaatio toteaa ne laadulliset tosiasiat, jotka tässä kvantifioimme: että LaTeX on yksisäikeinen, että yhden ytimen suorituskyky siksi määrää käännösajan ja että “useammat ytimet auttavat vain, jos yrität kääntää enemmän asiakirjoja kuin sinulla on vapaita suoritinytimiä” [1]. Sen jälkeen se antaa lineaarisen mitoitussäännön — 2 ytimen / 3 GiB:n perustaso sekä yksi ydin ja yksi gigatavu viittä–kymmentä samanaikaista käyttäjää kohden — joka motivoi tätä tutkimusta. Kontribuutiomme on muuttaa nämä toteamukset mitatuiksi laeiksi (yhtälöt (1) ja (2)) ja osoittaa, missä lineaarinen sääntö pettää: siinä ei ole termiä jaetulle sivuvälimuistille, joka tekee muistirajasta superlineaarisen, eikä termiä kahdelle tulosta hallitsevalle ohjelmistoparametrille.7.2 Koonti- ja CI-kapasiteettitutkimukset
Koontijärjestelmien mittaaminen samanaikaisuuden alaisena on vakiintunutta LaTeX-ympäristön ulkopuolella. LightSys raportoi, että Docker-konteissa kääntävien tavanomaisten CI-järjestelmien I/O heikkenee pull requestien saapumistahdin kasvaessa, ja pullonkaula ilmenee noin yhdentoista samanaikaisen pyynnön kohdalla [17]; TAOS-CI havaitsee, että kääntäminen hallitsee CI:n seinäkelloaikaa ja vastaa suurissa projekteissa 60–67 % koko putken kestosta [18]. Järjestelmämme eroaa yhdessä suhteessa, joka osoittautuu ratkaisevaksi: LaTeX-käännös on interaktiivinen. Kaksi kertaa pidempään kestävä CI-työ on haitta; kaksi kertaa pidempään kestävän käännöksen havaitsee suoraan esikatseluruutua odottava käyttäjä, minkä vuoksi käsittelemme aikakatkaisua kapasiteettiparametrina emmekä epäonnistumiskynnyksenä.7.3 Konttien yleiskustannukset
Tuore tutkimus erittelee Docker-konttien käynnistysviiveen tallennustasoittain [19] ja kuvaa konttien suorituskykyä reunalaskennassa [20]. Meidän ympäristössämme käännöskohtainen kontin käynnistys jakautuu: se on pieni vakio suhteessa 9 sekunnin käännökseen, ja sovittamamme vapaan suorituksen aika sisältää sen. Kontin ominaisuus, jolla on merkitystä, on resurssirajojen puuttuminen (§6.2), joka muuttaa käännöskohtaisen muistin ylityksen koko isäntäkoneen kaatumiseksi.7.4 LaTeX epäluotettavana syötteenä
Hiekkalaatikoitu kääntäminen on olemassa, koska TeX on ohjelmointikieli ja asiakirjat ovat epäluotettavaa syötettä [21, 22]. Tämä suunnitteluratkaisu tekee tästä tutkimuksesta mahdollisen — jokainen käännös on eristetty kontti, jonka resurssikäyttäytyminen on havaittavissa — ja tekee myös puuttuvasta muistirajasta merkittävän, koska sen käyttöön ottavat ylläpitäjät olettavat eristyksen.7.5 Kääntäjä tutkimuskohteena
TeX itse on hyvin dokumentoitu kielenä [16], mutta sen käyttäytyminen koontikohteena on herättänyt huomiota vasta äskettäin. Tan ja Rigger [8] kääntävät suuren arXiv-lähdekorpuksen eri moottoreilla ja jakeluversioilla ja havaitsevat, että moottorit eivät ole keskenään korvattavissa: vain prosentin murto-osa asiakirjoista tuottaa tavulleen identtisen tulosteen XeTeXillä ja pdfTeXillä. Tämä tulos koskee suoraan menetelmäämme. Kapasiteetti on asiakirjan ja moottorin ominaisuus, joten suorituskykytesti, joka ei kiinnitä kumpaakin, ei ole toistettavissa; kiinnitämme siksi koko ajan yhden asiakirjan, yhden moottorin ja yhden jakelun (texlive-full:2025.1) ja ilmoitamme moottorin jokaisen kuvan kuvatekstissä. Se myös rajaa lukujemme yleistettävyyttä tavalla, joka kannattaa sanoa suoraan: ne kuvaavat XeLaTeXia tällä asiakirjalla, eivät TeXiä yleisesti.
LaTeX-koonti_järjestelmiä_ koskeva työ on pitkälti käytännön toimijoiden vetämää. LaTeX3-projektin l3build [13] standardoi regressiotestauksen ja paketoinnin, ja itsenäiset suorituskykytestit vertailevat käärintätyökaluja — 26 koontijärjestelmän katsaus havaitsee esikäännetyn johdanto-osan tuovan noin 20 % pelkkään ajoon ja 40 % latexmk-ohjelmaan verrattuna [14]. Nämä optimoivat yksittäistä käännöstä. Ne ovat ortogonaalisia mittaamallemme ja yhdistettävissä siihen: johdanto-osan välimuisti lyhentää aikaa , ja jokainen tämän artikkelin kapasiteettiluku skaalautuu :n mukana.
7.6 Samanaikaisuuden hallinta editorissa, ei kääntäjässä
Overleafin yhteistyöpuoli perustuu vakiintuneeseen tutkimuslinjaan. Operaatiomuunnos (operational transformation) on peräisin Ellisiltä ja Gibbsiltä [9], ja Jupiter-järjestelmä [10] teki siitä käytännöllisen suuren viiveen asiakkaille; sen suunnittelu on tunnistettavissadocument-updater-palvelussa: palvelin, joka järjestää operaatiot, ja asiakirjakohtainen puskuri, jota vasten asiakkaat synkronoivat. Ristiriidattomat replikoidut tietotyypit (CRDT) [11] ratkaisevat saman ongelman ilman keskitettyä järjestäjää. Tämä ero saa luvun §4.3 topologian ylipäätään toimimaan: koska odottavien päivitysten puskuri sijaitsee jaetussa Redisissä eikä instanssin muistissa, mihin tahansa replikaan ohjattu käännös näkee viimeisimmät näppäilyt, ja käännösaffiniteetti voidaan valita välimuistin paikallisuuden eikä oikeellisuuden perusteella.
7.7 Kapasiteettimallit
Amdahlin laki [24] rajaa rinnakkaisuudesta saatavaa nopeutusta, ja Littlen laki [23] yhdistää käyttöasteen saapumistahtiin ja palveluaikaan; molempia on käytetty edellä. Guntherin universaali skaalautuvuuslaki [12] laajentaa ensimmäistä koherenssiviiveen taantumatermillä ja ennustaa, että suoritusteho saavuttaa huippunsa ja alkaa sitten laskea. Toteamme, että järjestelmämme ei ilmennä tätä taantumatilaa arvoon asti: suoritusteho kyllästyy ja viive kasvaa, mutta mikään ei romahda. Syy on rakenteellinen eikä onnekas — käännökset eivät jaa mitään tilaa, jota pitäisi pitää koherenttina, joten lain lisäämä termi on lähellä nollaa, ja luvun §4.3 sisäänpääsytasanne rajoittaa kilpailua ennen kuin sillä voi olla merkitystä.8. Suositukset ylläpitäjille
1
Korjaa kaksi ohjelmistoparametria ennen laitteiston ostamista
Molemmat ovat ilmaisia, ja kumpikin on arvokkaampi kuin mikään yksittäinen mittaamamme laitteistopäivitys. Nosta
features.compileTimeout arvoon, jota käyttäjäsi todella sietävät — CLSI:n hyväksymä enimmäisarvo on 600 s — ja jos odotat ylittäväsi 65 samanaikaista käännöstä, joko nosta compileConcurrencyLimit-arvoa johdetussa kuvassa tai skaalaa horisontaalisesti. Jos et tee kumpaakaan, maksat ytimistä, joita ohjelmisto kieltäytyy käyttämästä.2
Mitoita yksi kone sen taitekohdan, ei ylärajan mukaan
Suuren ajokoneen mittaussarja (§4.3) erottaa kaksi lukua, jotka sekoitetaan rutiininomaisesti. Yläraja — suurin samanaikaisuus, jolla jokainen PDF vielä palautuu — on 64-ytimisellä palvelimella vähintään 1024, emmekä koskaan saavuttaneet sitä. Taitekohta — piste, jonka jälkeen hännän viive lakkaa kasvamasta maltillisesti ja alkaa kaksinkertaistua — on 512:ssa, ja viimeinen mukava toimintapiste sen alapuolella on 256. Arvojen ja välillä -odotus kasvaa kahdesta minuutista lähes kuuteen; arvojen 512 ja 1024 välillä se saavuttaa kahdeksan. Ylläpitäjä, joka mitoittaa ylärajan mukaan, toimittaa järjestelmän, joka teknisesti toimii mutta jota kukaan ei halua käyttää.Tälle koneelle ja tälle asiakirjalle suositeltu toimintapiste on siksi 256 samanaikaista käännöstä, mikä on fyysisten ytimien määrä ja säikeiden määrä ja pitää -arvon noin 120 sekunnissa. Suosittelemme asettamaan
compileConcurrencyLimit-arvon tähän sen sijaan, että se jätettäisiin korkeaksi: 1024 käännöksen päästäminen sisään kerralla saa kaikki odottamaan kahdeksan minuuttia, kun taas 256 käännöksen päästäminen sisään ja muiden asettaminen jonoon palvelee useimpia käyttäjiä kahdessa minuutissa. Jonoutuminen heikentää myöhään saapuvien kokemusta; kilpailu heikentää kaikkien.3
Käsittele näitä pahimman tapauksen lukuina
Jokainen taulukon 2 taso on samanaikaisesti käynnistetty kylmä käännös. Kumpikaan ehto ei toteudu tuotannossa: saman asiakirjan lämmin käännös kestää 8,6 s verrattuna kylmän 28,3 sekuntiin, eli -kertaisesti nopeammin, eivätkä todelliset käyttäjät paina painiketta samalla sekunnilla. Vakaan tilan käyttäjäjoukko, joka kääntää uudelleen kahden minuutin välein tyypillisellä välimuistin osumaprosentilla, kestää siksi huomattavasti enemmän kirjoittajia kuin pelkkä samanaikaisuusluku antaa ymmärtää — suuruusluokaltaan tuhat tai enemmän aktiivista kirjoittajaa toimintapisteessä 256. Samanaikaisuusluku on hetkellisen purskeen raja, ei paikkamäärä.
4
Päätä ensin viivebudjetti ja lue sitten koko
Yhtälö (1) kääntyy suoraan. Tavoiteodotukselle kellotaajuudella ja ytimellä sopiva samanaikaisuus on , jossa tälle asiakirjalle . 60 s:n budjetti 8 ytimellä ja 3 GHz:llä antaa ; 120 s:n budjetti kaksinkertaistaa sen. Budjetin julkaiseminen kapasiteetin rinnalla on ainoa rehellinen tapa ilmoittaa kumpikaan.
5
Osta ensin muistia, sitten ytimiä, ja tarkista, mihin rajaan törmäät
Alle 32 GiB:n muistilla mittasimme lisäytimistä lähes olematonta hyötyä. Diagnoosi on edullinen: jos virheet ilmenevät HTTP 502 -vastauksina vierasjärjestelmän muistin ollessa vähissä, lisää muistia; jos ne ilmenevät
timedout-tilana muistia riittäessä, lisää ytimiä tai nosta aikakatkaisua. Ylläpitäjät voivat lukea tämän samasta virhesignatuurista, jota käytimme kokoonpanojen luokitteluun.6
Suosi kellotaajuutta kokemuksen ja ytimiä käyttäjämäärän vuoksi
Koska pätee ilman kaarevuutta (2 % alueella 1,0–5,5 GHz), nopeampi kellotaajuus nopeuttaa jokaista käännöstä jokaiselle käyttäjälle. Useammat ytimet eivät nopeuta yhtäkään yksittäistä käännöstä; ne vain päästävät sisään useampia samanaikaisia. Asennusten, joissa valitetaan “käännökset ovat hitaita”, kannattaa ostaa kellotaajuutta; asennusten, joissa valitetaan “käännökset epäonnistuvat määräajan lähestyessä”, kannattaa ostaa muistia ja ytimiä.
7
Skaalaa ylärajan jälkeen horisontaalisesti eikä vertikaalisesti
Yli 65 samanaikaisen käännöksen tuettu tie on horisontaalinen skaalaus (kuvat 2c ja 10, tarkemmin luvussa §9): useita sovellusinstansseja evästepohjaisella istuntoaffiniteetilla varustetun kuormantasaajan takana, jotka jakavat keskitetyn MongoDB:n, Redisin ja S3-yhteensopivan tallennuksen ja joissa
git-bridge jätetään yksittäiseksi instanssiksi. Tämä moninkertaistaa instanssikohtaisen ylärajan instanssien määrällä, ja juuri näin SaaS-asennus saavuttaa oman kapasiteettinsa.8
Älä luota käännöskohtaiseen eristykseen
Kunnes Docker-suorittimen muistiraja korjataan (§6.2), yksittäinen patologinen asiakirja voi kuluttaa loppuun isäntäkoneen sen sijaan, että vain se lopetettaisiin. Ylläpitäjien, jotka tarvitsevat tämän takuun, kannattaa asettaa se itse sen sijaan, että odottaisivat sitä. Suurella isäntäkoneella käyttämämme mekanismi on kovan ylärajan sisältävä systemd-osio, johon Docker-daemon sitten ohjataan niin, että jokainen sen luoma kontti lasketaan sen sisään:Yksi yksityiskohta maksaa iltapäivän, jos sen ohittaa.
docker-capped.slice-niminen osio ei sijaitse docker.slice-osion rinnalla vaan sen sisällä, koska yhdysmerkki on hierarkian erotin eikä osa nimeä. Yläraja, jolla ei näytä olevan vaikutusta, on yleensä asetettu tason päähän siitä, missä kontit todellisuudessa sijaitsevat. Varmista lukemalla huippuarvo memory.max_usage_in_bytes-tiedostosta ajon jälkeen äläkä luota määritystiedostoon — isäntäkoneellamme käännösten cgroup ei koskaan ylittänyt viidesosaa ylärajastaan edes 1024 samanaikaisella käännöksellä, mikä on itsessään todiste siitä, että rajoittava tekijä oli daemon eikä muisti.
git-bridge, joka säilyttää tietovarastot paikallisella levyllä ilman replikointimahdollisuutta ja jonka on toimittava yksittäisenä instanssina yhden nimetyn replikan rinnalla.
9. Referenssiasennus useammalla koneella
Kaikki edellä mitattu koskee yhtä konetta. Tämä luku kuvaa hajautetun muodon riittävän tarkasti rakentamista varten — ja koska ylläpitäjän todellinen kysymys ei ole miten vaan kannattaako, kuvaa ensin pisteen, jossa se tulee vaivan arvoiseksi.9.1 Milloin hajautettu muoto on perusteltu
Yksi kone on edullisempi ylläpitää kaikilla merkityksellisillä tavoilla: yksi vikaantumisalue, ei jaettua tilaa pidettäväksi johdonmukaisena, ei reititystä, joka voisi mennä pieleen. Datamme asettaa kolme kynnystä sille, milloin siitä kannattaa luopua.9.1.1 Alle 65 samanaikaista käännöstä: älä
Instanssikohtainen yläraja on ohjelmiston eikä laitteiston vakio (§6.1). Kunnes tarjottu kuorma lähestyy sitä, toinen kone tuo lisää vikaantumistapoja eikä hyödytä mitään. 64-ytiminen isäntäkone palveli 256 samanaikaista käännöstä täydellä onnistumisella vasta, kuncompileConcurrencyLimit oli nostettu; ylläpitäjä, joka ei ole vielä muuttanut tätä yhtä arvoa, ei ole laitteistorajoitteinen eikä hänen pitäisi ostaa laitteistoa.
9.1.2 Noin 65–500: skaalaa ensin vertikaalisesti
Vertikaalinen skaalaus pysyi lineaarisena koko alueellamme eikä koskaan siirtynyt taantumatilaan. Yksi suuri isäntäkone saavutti 1024 samanaikaista kylmää käännöstä 100 %:n onnistumisella (§4.3); viiveen taitekohta ilmeni 512:ssa, ei aiemmin. Tällä alueella suurempi kone on ehdottomasti yksinkertaisempi kuin useat pienemmät, ja luvun §4.4 mukaan nopeampi kone parantaa jokaisen käyttäjän kokemusta sen sijaan, että se vain päästäisi sisään useampia.9.1.3 Hajauta saatavuuden, ei suoritustehon vuoksi
Rehellinen syy ajaa useampaa kuin yhtä sovellusreplikaa ylärajan alapuolella on se, että yksi kone on yksi virtalähde, yksi ydin ja yksi päivitysikkuna. Se on oikeutettu syy, ja juuri sen me antaisimme; se ei vain ole kapasiteettiperuste, ja näiden kahden sekoittaminen saa ylläpitäjät ostamaan replikoita, kun he olisivat tarvinneet muistia.9.2 Tasot ja niiden mitoitus
Kuva 10 esittää topologian. Siinä on neljä tasoa, ja ne skaalautuvat eri suureiden mukaan — mikä on niiden erottamisen koko tarkoitus.9.2.1 Reuna
Yksi kuormantasaaja, tai kaksi saatavuuden vuoksi. Se päättää TLS-yhteydet eikä tee mitään raskasta; se skaalautuu yhteyksien eikä käännösten määrän mukaan, ja pieni instanssi riittää tässä tutkituille kuormille. Merkitystä on sen määrityksellä, ei sen koolla (§9.3).9.2.2 Sovellusreplikat
Nämä kantavat käännöskuorman ja ovat ainoa taso, joka skaalautuu samanaikaisuuden mukana. Mitoita jokainen luvun §8 sääntöjen mukaan — muisti ennen ytimiä, sitten kellotaajuus — ja aseta sitten replikoiden määrä kattamaan huippusamanaikaisuus jaettuna replikakohtaisella ylärajalla. Replikat eivät sisällä mitään pysyvää: niiden paikallisella levyllä on käännösten työtiedostot ja tulosvälimuisti, jotka molemmat voidaan rakentaa uudelleen. Tämän ansiosta niitä on turvallista lisätä ja poistaa vapaasti, ja tämä kannattaa varmistaa eikä olettaa, koska yksikin väärin määritettyfilestore-polku muuttaa tason huomaamatta tilalliseksi.
9.2.3 Tila
Redis, MongoDB ja S3-yhteensopiva objektitallennus erillisillä isäntäkoneilla. Redis on kantava osa ja vähiten ilmeinen: se sisältää istuntovaraston ja elävän asiakirjapuskurin, jonka ansiosta mihin tahansa replikaan ohjattu käännös näkee toiseen replikaan kirjoitetut näppäilyt. Ylläpitäjä, joka käsittelee Redisiä välimuistina ja mitoittaa sen poistoja varten, saa aikaan vanhentuneiden asiakirjojen käännöksiä, joita on äärimmäisen vaikea diagnosoida, koska mikään ei epäonnistu — tulos on vain väärä. MongoDB skaalautuu projektien määrän eikä käännöstahdin mukaan. Objektitallennus on valinnainen yhdellä replikalla ja pakollinen useammalla.9.2.4 Yksittäisinstanssi
git-bridge säilyttää tietovarastot paikallisella levyllä, ylläpitää paikallista indeksiä eikä sillä ole replikointimahdollisuutta. Sen on toimittava täsmälleen yhtenä instanssina kiinnitettynä yhden nimetyn replikan rinnalle, ja se on komponentti, joka tekee asennuksesta ei-aivan-tilattoman. Suunnittele sen isäntäkone sen mukaisesti: sen levy on se, joka on varmuuskopioitava.
Taulukko 4. Referenssitasot. Vain sovellustaso skaalautuu samanaikaisuuden mukana; sen mitoitus on luvun §8 aihe.
9.3 Reititys on se osa, joka menee helposti pieleen
Kolmen pyyntöluokan on päädyttävä kolmeen eri paikkaan, ja oletusarvoinen yhden säännön määritys täyttää niistä enintään kaksi. Polun/project/ alla oleva käännösliikenne tulisi jakaa projektitunnisteen johdonmukaisella hajautuksella, jotta projektin käännösvälimuisti pysyy yhdellä replikalla. Käytämme HAProxyn asetusta balance hash path,field(3,/) yhdessä asetusten hash-type consistent ja hash-balance-factor 150 kanssa. Valinnalla on merkitystä skaalattaessa: evästeaffiniteetilla olemassa olevat istunnot pysyvät kiinnitettyinä alkuperäiseen replikaansa loputtomasti, ja uusi replika saa vain uusia käyttäjiä, joten kone, josta ylläpitäjä juuri maksoi, ei ota vastaan lainkaan sitä kuormaa, joka motivoi sen ostamista. Johdonmukainen hajautus jakoi kokoonpanossamme skaalattaessa uudelleen 35 % projekteista, evästeillä 0 %.
Istuntoliikenne on erilaista. Kun WebSocket-päivitys epäonnistuu ja socket.io palaa XHR-kyselyyn, yhden istunnon peräkkäisten kyselyjen on päädyttävä yhteen replikaan, eikä polussa ole projektitunnistetta hajautettavaksi. Tämä liikenne tarvitsee erillisen taustapalvelun evästeaffiniteetilla. Suunnittelimme tämän jaon, mutta emme ottaneet sitä käyttöön; merkitsemme sen puutteeksi emmekä väitä toteuttaneemme sitä.
Lopuksi polun /git/ on päädyttävä replikaan, jonka rinnalla git-bridge toimii. Se reititetään tuohon replikaan eikä suoraan git-bridge-palveluun, koska silta todentaa takaisinkutsunsa sovelluksen OAuth-päätepisteitä vasten ja selvittää blob-URL-osoitteet sen kautta; replikan ohittaminen rikkoo todennuksen eikä paranna mitään.
9.4 Skaalaus alaspäin tarvitsee tyhjennyspuskurin
Replikan poistaminen ei ole symmetrinen sen lisäämisen kanssa: käynnissä oleva käännös menetetään, ja käyttäjä näkee virheen, jota hän ei aiheuttanut. Toimiva järjestys on pysäyttää ensin uusi liikenne, odottaa ja vasta sitten lopettaa. Toteutimme tämän pre-stop-koukkuna, joka pitää podia määritettävän ajan, kun kuormantasaaja merkitsee taustapalvelun tyhjeneväksi — riittävän lyhyen, jotta sen voi testata minuuteissa, ja tuotannossa riittävän pitkän istunnon luonnolliseen päättymiseen, tunteja eikä sekunteja. Aikaväli on säätönuppi, joka ratkaisee, onko joustavuus näkymätöntä vai raivostuttavaa. Yksi lisärajoitus löytyi mittaamalla eikä suunnittelemalla: suoritinkuormaan perustuva automaattinen skaalaus ei toimi tällä kuormalla. Sovelluspodin oma käyttöaste oli 22 m ydintä solmun kokonaismäärän ollessa 3997 m ydintä, koska käännöstyö tapahtuu sisarkonteissa, joita podi ei laske omikseen. Minkä tahansa tämän tason skaalaamiseen käytettävän signaalin on laskettava käynnissä olevia käännöskontteja, ei podin suoritinkäyttöä.10. Merkitys Overleafin ulkopuolella
Mikään luvuissa §4.2 tai §4.3 ei ole Overleafin koodille ominaista. Mitatut lait seuraavat kolmesta ominaisuudesta, jotka ovat yhteisiä kaikille isännöidyille LaTeX-palveluille: työyksikkö on yksisäikeinen prosessi, se on eristetty konttiin, ja sen työjoukko on suuri vain luku -puu, joka sivuvälimuistin on pidettävä muistissa. Kolme seurausta siirtyy suoraan kaikille, jotka rakentavat tällaista palvelua.10.1 Varaa ensin muistia, sitten ytimiä
Matriisin vahvin tulos on negatiivinen: alle 16 GiB:n muistilla ydinmäärällä ei ole juuri merkitystä, ja vasta 48 GiB:n muistilla 4, 8 ja 16 vCPU:n kokoonpanot ylipäätään erottuvat toisistaan (143, 268, 331). Ylläpitäjä, joka lukee tavanomaisen säännön muodossa “lisää yksi ydin viittä käyttäjää kohden”, ostaa väärää resurssia. Mekanismi on jakelupuun jaettu sivuvälimuisti, ja se on TeX Liven koon eikä minkään tietyn käyttöliittymän ominaisuus.10.2 Sisäänpääsytahti on resurssi, ja se yleensä unohdetaan
Arvolla palvelimellamme ei koskaan ollut yli 205 elävää hiekkalaatikkoa (kuva 7b), vaikka jokainen pyyntö saapui kerralla. Rajoittavana tekijänä oli konttien luominen eikä kääntäminen — mikä on linjassa mittaustutkimusten kanssa, jotka katsovat konttien käynnistyskustannuksen johtuvan ajonaikaisista yleiskustannuksista eikä kuvan koosta [19, 20]. Palvelu, joka mitoittaa vain suorittimen ja muistin, huomaa purskekäyttäytymisensä määräytyvän suureesta, jota se ei koskaan mitannut. Tämän käytännön muoto on luvun §8 suositus: rajoita sisäänpääsyä tietoisesti, koska itse valitsemasi jono on parempi kuin jono, jonka löydät.10.3 Käännöstään pidempään elävä hiekkalaatikko mitätöi mallin
Jokainen tämän artikkelin kapasiteettiluku olettaa, että kontti luodaan, se tekee yhden käännöksen ja päättyy — elinikä on kymmeniä sekunteja ja käyttösuhde lähellä yhtä vain sen ollessa käynnissä. Kaksi tuoretta suunnittelumallia rikkoo tämän oletuksen, ja ne rikkovat sen samalla tavalla. Ensimmäinen on käyttäjäkohtainen pysyvä hiekkalaatikko. Kiinteän yksityisen ympäristön varaaminen jokaiselle käyttäjälle muuttaa tilastollisesti multipleksoidun poolin joukoksi varauksia: palvelu, joka pystyisi aikajaon avulla palvelemaan 256 samanaikaista käännöstä 64 ytimellä, pystyy palvelemaan vain 16 käyttäjää, jos kullekin annetaan neljä omaa ydintä, eli suuruusluokkaa vähemmän samalla laitteistolla. Datamme kvantifioi tämän valinnan kustannuksen sen sijaan, että vastustaisi sitä — varaukset tuovat ennustettavuutta, ja vaihtokurssi on suositellussa toimintapisteessä noin . Toinen ja uudempi on tekoälyagentti, joka jakaa hiekkalaatikon kääntäjän kanssa. Agenttiavusteisilla kirjoitusalustoilla sama kontti, joka suorittaa XeLaTeXia, voi isännöidä myös pitkäkestoista koodausagenttia, joten se on varattuna jatkuvasti eikä purskeittain. Käytännön toimijat raportoivat juuri sitä oiretta, jonka malli ennustaa tällaisille asennuksille — jatkuvaa hitautta maltillisilla käyttäjämäärillä [15]. Vuorovaikutus kannattaa kuvata tarkasti, koska kyse ei ole yksinkertaisesti “suuremmasta kuormasta”. Kolme havaintoamme vahvistavat toisiaan. Varaus lakkaa olemasta purskeista, joten luvun §4.2 aikajakolaki koskee koko käyttäjäjoukkoa kerralla eikä vain parhaillaan kääntävää osaa. Sivuvälimuisti, joka tuo luvun §4.1 superlineaarisen muistihyödyn, jaetaan nyt agentin oman työjoukon kanssa eikä pysy lämpimänä TeXille. Ja luvun §6.2 puuttuva kontin muistiraja muuttuu paljon vaarallisemmaksi, koska kontti, joka ei koskaan päätä toimintaansa, ei koskaan palauta muistiaan. Emme mitanneet tällaista alustaa emmekä esitä väitteitä mistään tietystä tuotteesta. Voimme kuitenkin sanoa, mitä lukumme merkitsevät suunnittelulle: arkkitehtuuri, joka antaa jokaiselle käyttäjälle pitkäikäisen moniytimisen hiekkalaatikon, tulisi mitoittaa varausjärjestelmänä eikä tässä raportoitujen samanaikaisuuslukujen mukaan, ja sen odotettavissa oleva kapasiteetti on lähempänä sen ydinmäärää jaettuna käyttäjäkohtaisilla ytimillä kuin mitään taulukon 1 lukua.11. Validiteettia uhkaavat tekijät
11.1 Yksi asiakirja
Kaikissa mittauksissa käytetään yhtä 63-sivuista XeLaTeX-asiakirjaa. Absoluuttiset kapasiteetit poikkeavat muilla asiakirjoilla; skaalautumislakien, jotka ovat suhteita, ei pitäisi. Asiakirja, jonka muistijoukko on huomattavasti suurempi, siirtäisi muistirajaa muuttamatta sen superlineaarista luonnetta.11.2 Virtualisoitu isäntäkone
Vierasjärjestelmät toimivat KVM:n alla yhdellä fyysisellä koneella, joten absoluuttiset luvut sisältävät virtualisoinnin yleiskustannukset, ja vierasjärjestelmät jakavat isäntäkoneen sivuvälimuistin ja NVMe-laitteen. Lievensimme suurinta sekoittavaa tekijää sammuttamalla muut vierasjärjestelmät havaittuamme, että isäntäkoneen muistipaine kasvattaa vierasjärjestelmän kuormitusta yli samalla samanaikaisuudella.11.3 Yhtäaikainen saapuminen
Jokainen käännös lähetetään samalla hetkellä, mikä on pahin tapaus. Todelliset käyttäjät saapuvat stokastisena prosessina, joten lukujemme mukaan mitoitetulla asennuksella on marginaalia eikä vajetta — mutta palautusmääräajan lopun huippu on lähempänä malliamme kuin Poisson-mallia.11.4 Reunakokoonpanot
2 GiB:n muistilla järjestelmä on niin lähellä romahdusta, että saman kokoonpanon toistetut ajot voivat erota yhdellä käännöksellä. Raportoimme varovaisen arvon emmekä tee johtopäätöksiä :n eroista tällä alueella.12. Saatavuus
Testattu järjestelmä, käyttöönottotyökalut ja upstream-projekti, josta se on johdettu, ovat kaikki julkisia:- Ayakaleaf Pro — https://github.com/ayaka-notes/ayakaleaf-pro
- Käyttöönottotyökalupakki — https://github.com/ayaka-notes/toolkit
- Dokumentaatio — https://ayakaleaf-pro.ayaka.space
- Upstream Overleaf — https://github.com/overleaf/overleaf
- TeX Live -käännöskuvat —
ghcr.io/ayaka-notes/texlive-full:2025.1
9a519f0d3d, 5d472e9b38) löytyvät Overleafin historiasta.

