Скалирање Git-а у привредном друштву OpenAI
Изградња контроле изворног кода за обим рада који доносе агенти, уз улагање у Git екосистем.
Током протекле године, величина нашег монодепоа и захтеви које мора да испуни расли су запањујућом брзином. Било је јасно да морамо да обновимо систем за контролу изворног кода како би подржао обим истовременог рада који Codex омогућава.
Направили смо Pando, нови позадински систем за Git депое, без прекида инжењерског рада и без промене начина на који наш тим користи Git. Pando сада подржава целокупан развој у монодепоу привредног друштва OpenAI. Pando је пројектован да испуни два амбициозна циља: прво, хоризонтално скалабилан упис, оптимизован за истовремено слање на велики број грана. И друго, максималну пропусну моћ читања, како би клијенти могли да преузимају податке довољно брзо да у потпуности искористе расположив мрежни проток.
Ове циљеве смо остварили уз очувану компатибилност са Git протоколом и клијентом, омогућивши инжењерима и агентима да без тешкоћа укључе Pando у постојеће токове рада. У продукцији, Pando је смањио медијану латенције слања скоро пет пута. Сада испоручује скоро петабајт Git података дневно.
Овде ћемо представити разлоге за изградњу новог система за контролу изворног кода и објаснити зашто смо одлучили да задржимо компатибилност са Git-ом. Упоредићемо свој систем са уобичајеним приступима скалирању Git-а и објаснити зашто је Pando посебно погодан да испуни потребе привредног друштва OpenAI за могућношћу скалирања. Осврнућемо се и на наредне кораке и на то како ћемо наставити да доприносимо Git-у да би подржао рад на нивоу агента.
Codex је променио обим и темпо развоја у привредном друштву OpenAI, омогућивши инжењерима да обављају знатно више послова паралелно. То значи више грана и слања, више спајања, као и више преузимања и клонирања из развојних окружења, истраживачких задатака и система за континуирану интеграцију (CI).
Ти захтеви се међусобно појачавају. Један инжењер сада има више измена спремних за CI истовремено, а свако слање може да покрене више задатака који преузимају исти комит.
Отприлике крајем прошле године, системи који подржавају наш монодепо почели су да тешко прате тај темпо. Суочавали смо се са спорим преузимањем и слањем, као и неуспелим спајањима, а поузданост је повремено падала испод 90%. Да ли смо достигли ограничење самог Git-а или начина на који смо опслуживали свој монодепо? Git је настао у заједници која је закрпе за језгро размењивала е-поштом. Више од две деценије програмери прилагођавају своје алатке Git-у, пратећи промене у начину развоја софтвера. Када смо почели да наилазимо на тешкоће у сопственом монодепоу, било нам је важно да можемо да наставимо да се ослањамо на тај рад.
Видели смо начин да задржимо познат ток рада, а да истовремено обновимо позадински систем тако да паралелно обрађује слања на различите гране и истовремено испоручује исту историју великом броју клијената. Ослањање на Git као основу нашег тока рада са изворним кодом значило је да побољшања клијента могу бити корисна и ван привредног друштва OpenAI. Желели смо да та побољшања из наше копије Git-а(отвара се у новом прозору) вратимо у изворни пројекат и поделимо их са широм заједницом.
Скалирање система за контролу изворног кода има две кључне димензије: велики број клијената који шаљу податке на различите гране и велики број клијената који преузимају исту историју. Pando је оптимизован за обе.
Прво, Pando координише ажурирања сваке гране независно. Ажурирања неповезаних грана могу да се одвијају паралелно, а клијент који преузима грану добија историју потребну за ту ревизију. Компромис је у томе што клијент који посматра више грана може да види њихова стања из различитих тренутака.
Друго, Pando поново користи пакетне датотеке (Git формат за заједничку компресију више објеката) при различитим преузимањима, уместо да прави посебну пакетну датотеку за сваког клијента. Клијент можда преузме и неке објекте које већ има, али сервер може да испоручи исте бајтове великом броју клијената уз мало израчунавања.
Ови избори нам омогућавају да скалирамо упис на више грана и опслужујемо читања из кеша. Да бисмо видели како се ове одлуке уклапају, почнимо од тога како Git чува и преноси историју.
Git мора да одржава усклађеност два дела депоа: објеката и референци.
Git депо бележи снимке стања датотека и историју која их повезује као граф објеката. Објекат може бити блоб, стабло, комит или ознака. Блобови садрже садржај појединачних датотека, а стабла повезују називе са блобовима или другим стаблима и тако формирају структуру директоријума. Комити показују на коренско стабло и нула или више надређених комита, формирајући историју вашег депоа.
Објекти се идентификују хешом свог типа и садржаја. Објекти су и непроменљиви: бележење измењене датотеке ствара нови блоб, док неизмењене датотеке и директоријуми могу поново да користе постојеће објекте.
Гране и ознаке су референце, скраћено „рефови”, које показују на комите. Прављењем комита на грани настаје нови комит, а референца гране се ажурира тако да показује на њега.
Git објекти упућују једни на друге преко идентификатора: комити на стабла, а стабла на друга стабла и блобове. Грана refs/heads/main показује на комит C2, чија је надређена C1. C1 показује на коренско стабло T1, где parser.py упућује на блоб B1. C2 показује на коренско стабло T2, где parser.py упућује на блоб B2. У оба коренска стабла, docs/ упућује на исто стабло, T3. Његов унос README.md показује на блоб B3, а usage.md на блоб B4.
Git чува објекте у „распакованом” или „упакованом” облику. Распаковани објекти се чувају у засебним датотекама означеним идентификатором објекта. Упаковани објекти чувају се заједно у пакетној датотеци, што омогућава да се слични објекти чувају као делте један у односу на други.
Git може да чува блобове као засебне датотеке или да их пакује заједно, кодирајући један блоб као делту у односу на други.
У Git-у је објекат доступан из комита ако Git може да га пронађе пратећи везе од тог комита кроз његове надређене, стабла и блобове. При преузимању, клијент говори серверу које комите жели, а које већ има. Сервер проналази објекте доступне из жељених комита, изоставља оне за које зна да их клијент већ има и шаље преостале као пакетну датотеку у истом формату који Git користи на диску. Потпуно клонирање почиње без иједног објекта, па су му потребни сви објекти доступни из историје која се клонира.
Слање преноси објекте у супротном смеру и захтева од сервера да ажурира једну или више референци. Клијент користи скуп референци које сервер оглашава да не би слао објекте које сервер већ има. Зато пакет који се шаље може да зависи од постојећих објеката: сам пријем пакета није довољан за реконструкцију нове историје.
Репликација Git депоа подразумева одржавање доступности и објеката и референци на више сервера. Пре него што реплика може да испоручи нову вредност референце, мора да буде у стању да испоручи објекте доступне из те вредности. Сервис мора и да координише конкурентна ажурирања референци, односно слања која покушавају да помере исту грану са истог старог врха на различите нове комите. Системи који намећу јединствен редослед свих уписа у депо могу довести до тога да слања на неповезане гране чекају једно на друго.
При пројектовању система Pando проценили смо уобичајене приступе скалирању контроле изворног кода помоћу Git-а: један координише ажурирања референци међу репликама депоа трофазним комитом (3PC, протокол за координацију потврђивања на више чворова), а други одређује редослед ажурирања преко заједничког дневника унапред уписаних промена (WAL, запис промена пре њихове примене) у складишту блобова.
У решењу са трофазним комитом које смо моделирали, Git сервис чува потпуну копију депоа на неколико реплика. Када било који сервер прими слање, долазна пакетна датотека се копира и паралелно шаље свим репликама. Да би се послате измене објавиле, већина реплика мора да прихвати ажурирање референце. Сервер који тиме управља јесте координатор, а поступак захтева више кругова комуникације између координатора и сваке друге реплике.
Да би прихватила ажурирање референце, свака реплика закључава своју копију референце и проверава да ли она и даље показује на комит који клијент очекује. Координатор затим шаље поруку о припреми за потврђивање репликама које су прихватиле ажурирање. Када већина потврди пријем те поруке, координатор им налаже да изврше ажурирање. Свака ажурна реплика затим може да огласи нови врх гране из своје локалне копије депоа.
Одржавање потпуних реплика омогућава локално опслуживање читања и гарантује клијентима конзистентан приказ свих референци, без обзира на то коју реплику изаберу. Зато се референце ажурирају једна по једна, а свако слање захтева више циклуса размене порука ради координације ажурирања референце међу репликама.
Због чекања на кворум, трајање слања зависи од перформанси дискова реплика и латенције комуникације. Како обим уписа расте, реплике морају да прате и долазне пакете и саобраћај читања.
У решењу заснованом на WAL-у које смо моделирали, Git сервис користи заједнички манифест у складишту блобова да одреди редослед ажурирања у целом депоу. Када сервер прими слање, отпрема долазну пакетну датотеку у складиште блобова и припрема ажурирање референце у својој локалној копији депоа. Да би објавио послате измене, у заједнички манифест у складишту блобова додаје унос који бележи ажурирање референце и показује на пакетну датотеку. Git сервер затим ажурира манифест операцијом поређења и замене. Тиме се манифест атомски замењује или се, у супротном, промена одбија. Ако га је у међувремену ажурирао други уписивач, сервер чита нове уносе, проверава да ли је његово ажурирање референце и даље важеће и покушава поново, користећи пакетну датотеку коју је већ отпремио.
Уписивачи могу паралелно да отпремају своје пакетне датотеке, али чак и слања на неповезане гране захтевају ажурирање истог манифеста. Време повратног циклуса успешне операције поређења и замене ограничава колико често депо може да објави нови манифест. Складиште блобова са малом латенцијом убрзава овај корак. Груписање омогућава да један манифест истовремено ажурира више референци, али по цену стављања ажурирања у ред чекања и повећања латенције.
Складиште блобова може паралелно да прима пакетне датотеке, али ажурирања заједничког манифеста и даље се међусобно надмећу. Само повећање капацитета складишта блобова не отклања то уско грло. Свака реплика и даље мора да прочита и индексира пакете из складишта блобова пре него што може да их испоручује локално. Ако долазни уписи надмаше брзину тог рада, реплике заостају, а клијенти дуже чекају да преузму новопослате комите.
То нас доводи до система Pando. Pando је нова архитектура за опслуживање Git депоа, осмишљена да се скалира на велики број клијената који истовремено шаљу податке. Ево како функционише:
Пре него што смо развили Pando, слутили смо да можемо испунити своје захтеве без компромиса у погледу Git-а. Ипак, морали смо да одустанемо од неких ствари које већина Git система сматра обавезним:
Конзистентност целог депоа: За конзистентан снимак свих референци у одређеном тренутку потребна је координација у целом депоу. У систему који одређује јединствен редослед свих ажурирања референци, слања на неповезане гране надмећу се за исту тачку координације.
Посебне пакетне датотеке за сваког клијента: Ако два клијента са различитим локалним историјама преузимају исту грану, сервер ће можда морати да направи различит пакет за сваког како не би слао објекте које већ имају. Припрема ових одговора троши процесорске ресурсе и улазно-излазни капацитет диска, што отежава скалирање на велики број клијената који читају податке.
Уместо тога, Pando нуди блажи модел конзистентности (каузалну конзистентност) за скалирање уписа и поново користи пакетне датотеке за скалирање читања.
Када клијент шаље податке на грану, Pando чува долазну пакетну датотеку као непроменљив блоб у складишту блобова. Сваки пут када се грана помери, Pando у складишту метаподатака бележи верзију референце која садржи нови врх гране, пакет из ког потиче и све раније верзије референци од којих пакет зависи. И складиште блобова и складиште метаподатака могу се хоризонтално скалирати.
Преузимање комита или референце из система Pando захтева да се клијенту испоручи скуп верзија референци (пакетних датотека), чиме се реконструише стање клијента који је направио верзију референце која се преузима. Тиме се обезбеђује слабији облик конзистентности у целом депоу, али и могућност прављења серија ажурирања појединачних референци. До сукоба међу клијентима долази само када истовремено шаљу податке на исту референцу. Клијент који чита више грана не може да претпостави да та читања одражавају стање целог депоа у истом тренутку.
Слањем на главну грану додаје се инкрементални пакет који садржи један или више комита. Свако слање на споредну грану поново обухвата раније комите те тематске гране, па клијент који има оглашену верзију стабла може да преузме тематску грану у једном пакету.
То је облик каузалне конзистентности. Да би преузео референцу, клијент који чита податке види историју клијента који ју је уписао. При слању, Pando контролише коју историју клијент и сервер сматрају заједничком, чиме обезбеђује да клијенти праве пакетне датотеке које се лакше деле.
Зато Pando током Git операција не пружа стање свих референци у истом тренутку, нити јединствен редослед њихових ажурирања при клонирању или преузимању. На пример, претпоставимо да се гране foo и bar ажурирају током преговарања потпуног клонирања. Током преговарања, један клијент може да види foo у верзији 1 и bar у верзији 2, док други види foo у верзији 2 и bar у верзији 1. У пракси, корисници и агенти не зависе од глобалног редоследа ажурирања референци, већ од редоследа ажурирања појединачне референце.
У овој симулацији три модела конзистентности подешавамо 1000 клијената тако да сваки изабере засебну грану, а затим више пута шаље јединствене комите. Меримо укупно протекло време и латенција од слања до могућности преузимања. Ово кашњење је важна метрика за радна оптерећења, јер мери време повратног циклуса потребно корисницима и агентима за сарадњу или коришћење других система који се ослањају на контролу верзија. Симулација моделира хардвер различитих класа, од стандардних до врхунских виртуелних машина и система за складиштење блобова. У овој симулацији ублажили смо захтев за конзистентност целог депоа код трофазног потврђивања.
Simulating Git Server Implementations
Follow each writer through repeated pushes, and separately measure when an independent reader can check out each commit.
Покрените ову симулацију која пореди Pando са још два приступа. Изаберите инфраструктуру, од стандардног до врхунског хардвера, број клијената и друга подешавања да бисте видели разлике.
Моделирани систем трофазног комита показује знатно већу латенцију уписа под оптерећењем, када дискови достигну свој капацитет. Системи са дневником унапред уписаних промена из истог разлога показују знатно веће кашњење читања, јер сервери не успевају да довољно брзо читају дневник. И у стварним тестовима на нашем монодепоу и у овој симулацији, Pando подржава више хиљада клијената који могу истовремено да шаљу податке без нарушавања перформанси под оптерећењем.
При обради слања, Pando проверава долазну пакетну датотеку док је стримује у складиште блобова, без распакивања у локални депо. Када клијент започне преузимање, Pando бира сачуване пакете који су му потребни, а клијент их преузима. Ниједан сервер не мора да примењује пакетне датотеке на локални депо нити да обавља скупе операције распакивања и паковања. Пошто углавном обављају преговарање и избор пакетних датотека, Pando сервери могу да раде на стандардном хардверу.
То омогућава систему Pando да се скалира до ограничења клијената, мреже између клијената и система Pando и сервиса за складиштење блобова. Уз довољан капацитет, сваки клијент који ради на независној грани може да преноси пакете брзином коју дозвољава његова веза. Да бисмо том брзином опслужили више клијената, можемо да додајемо Pando сервере и упоредо повећавамо капацитет складишта метаподатака и блобова.
Pushing and Fetching a Branch in Pando
Pando stores the writer’s packfile in blob storage and records the ref version in metadata service. On fetch, Pando selects the packs the reader needs, and Express serves them.
Агент локално уређује датотеке и прави комит, а затим покреће git push, чиме се прави пакетна датотека тих измена ради ажурирања гране. Pando прима пакет и стримује га у складиште блобова. Након што декодирањем у једном пролазу провери долазно слање, Pando користи трансакцију над више кључева да забележи верзију референце у нашем складишту метаподатака и атомски ажурира показивач референце. То омогућава систему Pando да обезбеди конзистентност по принципу „читај оно што си уписао”. Цела ова операција уписа захтева читања и уписа метаподатака.
Када други клијент преузима грану, Pando бира скуп сачуваних пакета на основу историје коју клијент већ има. Ова операција захтева читања метаподатака, при чему је најкраће растојање, мерено верзијама референци, између онога што клијент има и онога што жели. Сервер враћа URI адресе пакетних датотека, а клијент их преузима преко сервиса Express, који чува пакетне датотеке у регионалним кешевима.
Ово решење се ослања на три кључна сервиса архитектуре система Pando: слање, преузимање и компакцију.
Када клијент шаље податке, уобичајени Git сервер понаша се као играч покера који показује све карте: открива клијенту сваку грану коју има. Клијент затим прикупља комите, стабла и блобове да би направио пакетну датотеку која изоставља објекте за које зна да их сервер већ има.
Оглашавање више референци може да смањи обим слања. Може и да отежа поновну употребу пакета, јер другом клијенту можда недостају објекти које је пошиљалац изоставио.
Pando примењује другачији приступ. Уместо да покаже све карте, клијенту оглашава само одабрани скуп грана. За то постоје два разлога:
Обезбеђивање конзистентног приказа свих референци је скупо. Са милионима грана, само оглашавање референци може да премаши 100 MiB. То захтева да сваки сервер или одржава ажурно мапирање, уз значајан трошак координације, или извршава упит над базом чији обим расте са бројем референци.
Када се клијенту достави само подскуп референци, он прави пакет који зависи само од онога што му сервер изричито дозвољава да изостави. Праћење зависности омогућава систему Pando да пакетну датотеку коју клијент направи при једном слању поново употреби као одговор на каснији захтев за преузимање.
Што више референци Git сервер оглашава, то клијенти који шаљу податке имају више извора на основу којих могу да изоставе објекте и тако направе мање пакете. Међутим, за поновну употребу тих пакетних датотека сервер мора да може да утврди да клијенти који их преузимају имају све зависности. У супротном, у пакетној датотеци могу да недостају објекти потребни клијенту.
С друге стране, ако Git сервер не огласи ниједну референцу, клијент би направио пакетну датотеку са целокупном историјом депоа. Ту пакетну датотеку може да користи било који други клијент, али уз значајну цену: преузимање било које гране практично постаје потпуно клонирање.
Оглашавање више референци доводи до мањих пакетних датотека. Већина смањења величине може се постићи оглашавањем само једне.
Подразумевано, када клијент шаље нову грану за развој функционалности, Pando као основу оглашава само одређено стабло. Тако величина огласа остаје иста док број грана у депоу расте, али то носи и одређене компромисе. Када инжењер више пута шаље податке на исту грану или надограђује једну развојну грану на другу, клијент мора поново да пошаље све што није на стаблу.
Зато су узастопна слања на грану већа, садрже потенцијално сувишне објекте и троше додатни мрежни проток клијента. У нашем монодепоу, медијана величине тако направљене пакетне датотеке била је испод 20 KiB, а 99. перцентил испод 3 MiB. За нас је то био разуман компромис, јер клијент који већ има оглашену историју стабла може да преузме грану помоћу те једне пакетне датотеке.
Након што изабере скуп референци које ће огласити клијенту, Pando прихвата слање и ажурира складиште метаподатака. Pando дели ажурирање метаподатака на синхрони и асинхрони део. Синхроно ажурирање метаподатака обезбеђује да клијенти одмах могу да преузму новоажурирани комит. Тиме се уписује нова верзија референце и њен показивач усмерава на ту верзију, уз чување новог врха гране, зависности коришћених при преговарању о пакетној датотеци и везе ка послатој пакетној датотеци.
Истовремено се у истој трансакцији бележе и асинхрони задаци, попут заказивања компакције. Код веома великих слања, синхроно се уписује само подскуп комита. Тако је потребан само константан број читања и уписа у складиште метаподатака, без обзира на величину слања.
Важно је да Pando сервери могу независно да прихватају слања на неповезане референце. Једини кључ око ког може доћи до надметања јесте показивач референце, који штитимо атомском операцијом налик поређењу и замени. Пропусну моћ уписа можемо да повећавамо додавањем Pando сервера, јединица за скалирање складишта метаподатака или складишта блобова.
При преузимању, клијент доставља серверу два скупа идентификатора комита, у протоколу позната као have и want. Уобичајени Git сервер израчунава разлику између скупова објеката доступних из постојећих и жељених комита, компримује потребне објекте и шаље резултат клијенту. Иако Git сервер отвореног кода има разне локалне индексе који убрзавају ову операцију, израда ових пакетних датотека може бити скупа, а оне се углавном тешко кеширају.
Уместо тога, Pando користи мапирања комита забележена при слању да пронађе клијентове комите have и want и повеже их са скупом верзија референци које их садрже. Свака од тих верзија референци повезана је са пакетном датотеком коју је Pando раније примио. Сервер на основу тога утврђује шта је клијенту потребно и бира пакетне датотеке које обухватају скуп потребних објеката.
Planning fetches in Pando
Pando compares what a client has with what it wants, then selects the stored packfiles needed—including any missing branch dependencies.
Fetch 27 trunk packs.
Select a branch to include its trunk dependencies.
Pando пресликава постојеће и жељене комите из Git протокола у низ верзија референци. Захтев за споредну грану подразумева и преузимање свега до њених зависности на стаблу.
Git протокол дозвољава слање само једне пакетне датотеке у HTTP одговору при клонирању или преузимању. Међутим, недовољно запажена могућност Git протокола, packfile-uri, омогућава серверу да врати везе за засебно преузимање додатних пакета. Pando користи искључиво ту могућност, а у самом одговору шаље празну пакетну датотеку. Да би подржао ову могућност, привредно друштво OpenAI је изворном пројекту допринело бројним побољшањима за packfile-uri.
Системи привредног друштва OpenAI раде у многим географским регионима, па у сваком одржавамо Pando кластере са локалним кешевима. Сервис за испоруку пакета Express кешира податке из складишта блобова, а засебан сервис кешира складиште метаподатака. Ови кешеви омогућавају систему Pando да захтеве за идентификатор комита или посебно читање референце у потпуности опслужи из кешираног стања тог кластера. За усмеравање захтева за пакетне датотеке ка Express серверима користимо конзистентно хеширање, уз стопу погодака у кешу већу од 99%.
Овај систем кешева пружа изузетно високу пропусну моћ, довољну да у потпуности искористи мрежни капацитет између клијената и система Pando. Уз ове URI адресе пакетних датотека и локалне кешеве, потврдили смо да операције клонирања и преузимања у потпуности користе мрежне везе од 10 Gbps, и то само на стандардним виртуелним машинама пружалаца услуга у облаку.
На већини Git сервера, препакивање и уклањање неискоришћених објеката неопходни су за одржавање перформанси депоа који расте. Оба корака ослобађају простор, али захтевају много израчунавања и улазно-излазних операција.
У депоу који се брзо мења, попут монодепоа привредног друштва OpenAI, није изводљиво слати засебну URI адресу пакетне датотеке за свако слање од последњег преузимања. Клијент би сваког дана морао да преузме десетине хиљада пакетних датотека да би ажурирао своје стабло.
Уместо тога, Pando у позадини спаја пакете како би смањио овај трошак, користећи решење налик компакцији у стаблима спајања заснованим на дневнику. Свако слање ствара оно што Pando назива пакетном датотеком „L0”, најмањом јединицом података коју Pando може да пренесе. Временом, позадински процеси прикупљају ове пакетне датотеке у покривне скупове који обухватају низ верзија референци и геометријски расту од нивоа L0. Наш монодепо данас користи покривне скупове пакетних датотека до нивоа L4.
Ови покривни скупови имају двоструку намену. Када се покривни скуп довољно попуни, процес за компакцију га преузима и прави једну пакетну датотеку. Тиме се побољшава степен компресије, јер се објекти у пакетној датотеци реорганизују. Уједно се убрзава преговарање при преузимању, јер покривни скупови служе као листа са прескакањем над верзијама референци. Истовременим прегледањем индекса на сваком нивоу, Pando може да изабере скуп пакета за слање клијенту у логаритамском времену. Ови покривни скупови пакетних датотека, било да су препаковани или не, омогућавају ефикасније планирање преузимања и смањују захтеве за пропусном моћи и латенцијом система Pando.
Compaction in Pando
Small packfiles are grouped into larger covers across levels, improving compression and speeding up fetches.
Компакција у позадини обједињује пакетне датотеке из многих верзија референци, што омогућава ефикасније преузимање уз мање датотека.
За разлику од многих Git сервера, пакетне датотеке се чувају на сваком нивоу и не одбацују се нити уклањају као неискоришћене. Пакети са свих нивоа непрекидно се користе за опслуживање клијената, на основу комита have и want које наводе у захтеву за преузимање. За клијенте који користе Pando као API, читање произвољног објекта из пакетне датотеке обично захтева мање прочитаних података са нивоа L0 него са L4, јер је мања вероватноћа да је објекат компримован.
Компакција у систему Pando знатно смањује укупан обим података који се шаљу клијентима и омогућава да сложеност планирања пакета расте спорије од линеарног раста заостатка клијента. То је нарочито важно за велике депое који се брзо мењају, а за које очекујемо да ће постати уобичајени у развоју софтвера.
Pando смо направили уз Codex, од покретања пројекта до продукције, за само 10 недеља. Језгро система Pando пројектовао је један инжењер, имплементирали су га тимови агената, а у рад га је пустило свега неколико инжењера. Pando је почео да опслужује продукциони саобраћај у априлу ове године и део је ширег система алатки за управљање изворним кодом које се користе у привредном друштву OpenAI.
При провери пројектног решења система Pando применили смо разноврсне приступе. Применили смо своје принципе за изградњу безбеднијих софтверских темеља. Пошто смо пројекат започињали од нуле, одлучили смо да Pando применимо у језику Rust, без наслеђених зависности. Написали смо скуп тестова усаглашености како би агенти могли да проверавају своје измене у односу на стандардно понашање Git-а. Развили смо и окружења за детерминистичко симулационо тестирање која нам омогућавају да проверавамо инваријанте и својства система. Тако смо могли да откријемо и ублажимо тешко уочљиве проблеме конкурентног приступа и регресије у преговарању и планирању пакета.
Многи модели су допринели овом систему; како су нови модели постајали доступни, користили смо их за побољшање перформанси и поузданости система Pando. Користећи GPT‑6 Astra, агенти су писали код у језицима Lean и TLA+ да формализују „теорију система Pando”, коју смо користили за проналажење и исправљање грешака у имплементацији и доказивање својстава система. Више сесија радило је непрекидно стотинама сати, проналазећи и исправљајући проблеме у граничним случајевима у систему Pando. Агенти такође раде даноноћно на безбедносном тестирању Git-а и система Pando из угла нападача, користећи моделе са могућностима програма Daybreak.
Pando смо првобитно увели као посреднички сервер који прослеђује читања и уписе нашем постојећем систему за контролу изворног кода. Тако смо могли да одржавамо Pando и претходни систем усклађеним и безбедно пребацимо саобраћај на Pando без прекида рада.
У оквиру свог механизма кеширања, Pando може и да уклони дупликате захтева и обједини их пре прослеђивања. То нам је омогућило да постојеће алатке наставе стабилно да раде док смо системе један по један пребацивали на Pando. Како смо пребацивали све више радних оптерећења на Pando, њихова слања су попуњавала Pando кеш и побољшавала поузданост претходног позадинског система.
Да бисмо оптимизовали перформансе при коришћењу система Pando, почели смо да испоручујемо своју јавну дистрибуцију Git-а на рачунаре програмера и у оквиру ChatGPT апликације за рачунар. За постепени прелазак клијената на Pando користили смо интерни омотач око Git интерфејса командне линије. Направили смо и многе друге алатке за обраду захтева за измене и преглед кода, као и API интерфејсе за аутоматизацију. Упоредо са Git саобраћајем, пребацили смо стотине интеграција које су зависиле од старих API интерфејса, веб-кука и преузимања депоа.
Сам Codex је помагао програмерима и тимовима да пређу на нови систем. Направили смо вештине за припрему постојећих радних копија и за усмеравање агената на коришћење новог система. Зато су програмери могли једноставно да затраже од услуге Codex да пребаци њихова развојна окружења и сервисе.
Прелазак на Pando побољшао је поузданост спајања и смањио медијану латенције слања за скоро 80%.
Pando може да испоручи петабајт Git података дневно са свега неколико процесорских језгара. Систем Pando је за сат времена испоручио више од 57 терабајта Git пакета, при чему је више од 99% тих бајтова стигло из локалног кеша на диску.
Поновна употреба пакета омогућава великом броју клијената да преузимају исту историју депоа уз мало израчунавања на чворовима који их опслужују. Овај пример приказује један депо, али Pando је пројектован да подржи много више њих. Како потражња расте, можемо независно да скалирамо испоруку података и Git преговарање.
Изградња система Pando на Git протоколу и клијенту помогла нам је да откријемо грешке и прилике за побољшање перформанси самог Git-а.
На пример, Pando директно испоручује клијентима пакете за поновну употребу, па су њихово преузимање и индексирање постали кључни за брзину и поузданост система. Тај рад је открио граничне случајеве при истовременим преузимањима, чишћењу после прекинутих преноса и настављању већ завршених преузимања. Исправили смо те делове кода, додали провере при прихватању постојећег пакета за преузимање и вратили те измене у изворни пројекат.
Морали смо и да видимо на шта одлазе време и мрежни проток, па смо додали праћење преузимања преко packfile-uri и бројање бајтова при генерисању пакета. Тако је лакше утврдити да ли споро преузимање троши време на генерисање пакета или на њихов пренос.
У верзији Git-а привредног друштва OpenAI(отвара се у новом прозору), клијент може паралелно да преузима и индексира независне пакете. Додали смо концепт „изричито наведених постојећих комита” како би сервер могао да огласи тренутни врх гране одвојено од историје коју клијент при слању сме да изостави из свог пакета. У систему Pando, то омогућава клијентима да помоћу --force-with-lease провере да се развојна грана није померила и направе њен пакет ослањајући се само на стабло. Свако ко има ту историју стабла затим може да преузме грану помоћу истог пакета.
Неколико ових побољшања већ је укључено у изворни Git, а многа друга налазе се у нашем јавном депоу. Настављамо да сарађујемо са Git заједницом како би ова побољшања била корисна и ван система Pando. Тај рад можете пратити у нашем јавном систему за праћење закрпа(отвара се у новом прозору).
Преиспитивањем устаљених приступа скалирању Git депоа, Pando нам омогућава да скалирамо свој монодепо без мењања Git токова рада које наши инжењери и агенти већ користе. У нашем монодепоу, Pando је омогућио већи степен паралелног рада, побољшао поузданост спајања и скратио време објављивања измена кода. Поред монодепоа, истражујемо и друге примене система Pando у привредном друштву OpenAI, укључујући радна оптерећења у којима велики број агената треба да сарађује на заједничком Git депоу.
Како инжењери и агенти буду стварали све више софтвера, све више тимова ван привредног друштва OpenAI наилазиће на ограничења контроле изворног кода са којима смо се ми сусрели. Тренутно истражујемо начине да технологију на којој се Pando заснива поделимо са својим корисницима.
Pando се ослања на две деценије искуства корисника и администратора Git депоа. Наставићемо да развијамо Pando и да сарађујемо са заједницом отвореног кода окупљеном око Git-а како бисмо делили побољшања корисна ширем кругу Git корисника.


