OpenAI

2 ნოემბერი, 2026

ინჟინერია

Git-ის მასშტაბირება OpenAI-ში

აგენტების მასშტაბზე გათვლილი კოდის ვერსიების კონტროლის სისტემის შექმნა და Git-ის ეკოსისტემის განვითარებაში წვლილის შეტანა.

ავტორები: აარონ ფრილი, ტეილორ ბლაუ და ტედ ნაიმანი — ტექნიკური გუნდის წევრები

იტვირთება…

გასული წლის განმავლობაში ჩვენი მონორეპოზიტორიუმის ზომა და მის მიმართ მოთხოვნები გასაოცარი ტემპით გაიზარდა. ცხადი იყო, რომ კოდის ვერსიების კონტროლის სისტემა უნდა განგვეახლებინა, რათა მას Codex-ით შესაძლებელი პარალელური მუშაობის მასშტაბისთვის გაეძლო.

შევქმენით Pando — Git რეპოზიტორიუმების ახალი სერვერული სისტემა, ისე, რომ არც საინჟინრო სამუშაო შეგვიწყვეტია და არც ჩვენი გუნდის მიერ Git-ის გამოყენების წესი შეგვიცვლია. ახლა OpenAI-ს მონორეპოზიტორიუმში მთელი პროგრამული შემუშავება Pando-ს ეყრდნობა. Pando ორი ამბიციური მიზნისთვის შეიქმნა: პირველი — ჰორიზონტალურად მასშტაბირებადი ჩაწერები, ოპტიმიზებული მრავალ შტოში ერთდროული გაგზავნისთვის. მეორე — წაკითხვის მაქსიმალური მწარმოებლურობა, რათა კლიენტებმა მონაცემები იმდენად სწრაფად ჩამოტვირთონ, რომ ხელმისაწვდომი ქსელური გამტარუნარიანობა სრულად გამოიყენონ.

ამ მიზნებს Git-ის პროტოკოლთან და კლიენტთან თავსებადობის შენარჩუნებით მივაღწიეთ, რაც ჩვენს ინჟინრებსა და აგენტებს საშუალებას აძლევს, Pando არსებულ სამუშაო პროცესებში შეუფერხებლად დანერგონ. საწარმოო გარემოში Pando-მ გაგზავნის მედიანური დაყოვნება თითქმის 5-ჯერ შეამცირა. ახლა ის ყოველდღიურად თითქმის ერთ პეტაბაიტ Git მონაცემებს აწვდის კლიენტებს.

აქ განვიხილავთ, რატომ შევქმენით კოდის ვერსიების კონტროლის ახალი სისტემა და რატომ გადავწყვიტეთ Git-თან თავსებადობის შენარჩუნება. ჩვენს სისტემას Git-ის მასშტაბირების გავრცელებულ მიდგომებს შევადარებთ და ავხსნით, რა უნიკალური შესაძლებლობებით აკმაყოფილებს Pando OpenAI-ს მასშტაბირების საჭიროებებს. ასევე განვიხილავთ შემდეგ ნაბიჯებს და იმას, როგორ გავაგრძელებთ Git-ის განვითარებაში წვლილის შეტანას აგენტების მუშაობის მასშტაბის მხარდასაჭერად.

რატომ დაგვჭირდა კოდის ვერსიების კონტროლის ახალი სისტემა

Codex-მა OpenAI-ში პროგრამული შემუშავების მასშტაბი და ტემპი შეცვალა: ინჟინრებს გაცილებით მეტი სამუშაოს პარალელურად შესრულების შესაძლებლობა მისცა. ეს ნიშნავს მეტ შტოსა და გაგზავნას, მეტ შერწყმას, ასევე მეტ წამოღებასა და კლონირებას შემუშავების გარემოებიდან, კვლევითი ამოცანებიდან და CI-დან.

ეს მოთხოვნები ერთმანეთს აძლიერებს. ახლა ერთ ინჟინერს ერთდროულად რამდენიმე ცვლილება აქვს CI-სთვის მზად, ხოლო თითოეულმა გაგზავნამ შეიძლება რამდენიმე ამოცანას ერთი და იმავე კომიტის წამოღება დააწყებინოს.

დაახლოებით გასული წლის ბოლოდან ჩვენი მონორეპოზიტორიუმის მხარდამჭერ სისტემებს დატვირთვასთან გამკლავება გაუჭირდა. წამოღება და გაგზავნა ნელდებოდა, შერწყმები ვერ სრულდებოდა, საიმედოობა კი ზოგჯერ 90%-ზე დაბლა ეცემოდა. თავად Git-ის შესაძლებლობების ზღვარს მივაღწიეთ თუ ჩვენი მონორეპოზიტორიუმის მომსახურების არქიტექტურისას? Git წარმოიშვა საზოგადოებაში, რომლის წევრებიც ბირთვის შესწორებებს ელფოსტით ცვლიდნენ. ორ ათწლეულზე მეტია, პროგრამული უზრუნველყოფის შექმნის მეთოდების ცვლილებასთან ერთად დეველოპერები თავიანთ Git-ზე დაფუძნებულ ხელსაწყოებსაც ადაპტირებენ. როდესაც საკუთარ მონორეპოზიტორიუმში სირთულეები შეგვექმნა, ჩვენთვის მნიშვნელოვანი იყო, ამ ნამუშევარზე დაყრდნობით გაგვეგრძელებინა განვითარება.

ვიპოვეთ გზა, შეგვენარჩუნებინა ნაცნობი სამუშაო პროცესი და სერვერული სისტემა ისე აგვეწყო თავიდან, რომ სხვადასხვა შტოში გაგზავნები პარალელურად დაემუშავებინა და ერთი და იგივე ისტორია ერთდროულად მრავალი წამკითხველისთვის მიეწოდებინა. კოდის ვერსიების კონტროლის სამუშაო პროცესის Git-ზე დაფუძნება იმას ნიშნავდა, რომ კლიენტის გაუმჯობესებები OpenAI-ს ფარგლებს გარეთაც სასარგებლო იქნებოდა. გვინდოდა, ეს გაუმჯობესებები Git-ის ჩვენი ასლიდან⁠(იხსნება ახალ ფანჯარაში) ძირითად პროექტში შეგვეტანა და ფართო საზოგადოებისთვის გაგვეზიარებინა.

Git-ის მასშტაბირებისთვის საჭირო ინჟინერია

კოდის ვერსიების კონტროლის სისტემის მასშტაბირებას ორი ძირითადი მიმართულება აქვს: მრავალი ჩამწერი სხვადასხვა შტოში აგზავნის მონაცემებს, ხოლო მრავალი წამკითხველი ერთსა და იმავე ისტორიას იღებს. Pando ორივესთვისაა ოპტიმიზებული.

პირველ რიგში, Pando თითოეული შტოს განახლებებს დამოუკიდებლად კოორდინირებს. დაუკავშირებელი შტოები შეიძლება პარალელურად განახლდეს, ხოლო შტოს წამკითხველი ამ რევიზიისთვის საჭირო ისტორიას იღებს. სანაცვლოდ, წამკითხველმა, რომელიც რამდენიმე შტოს ათვალიერებს, შეიძლება ისინი დროის სხვადასხვა მომენტის მდგომარეობაში დაინახოს.

მეორე — Pando წამოღების ოპერაციებში ხელახლა იყენებს პაკეტის ფაილებს (Git-ის ფორმატს რამდენიმე ობიექტის ერთად შესაკუმშად), ნაცვლად იმისა, რომ თითოეული კლიენტისთვის ცალკე ფაილი შექმნას. კლიენტმა შეიძლება უკვე არსებული ზოგიერთი ობიექტიც ჩამოტვირთოს, თუმცა სერვერს შეუძლია, მცირე გამოთვლითი დანახარჯით იგივე ბაიტები მრავალ კლიენტს მიაწოდოს.

ეს გადაწყვეტილებები საშუალებას გვაძლევს, ჩაწერები შტოებს შორის გავანაწილოთ და წაკითხვის მოთხოვნებს ქეშიდან მოვემსახუროთ. იმის გასაგებად, თუ როგორ მუშაობს ეს ყველაფერი ერთად, დავიწყოთ იმით, როგორ ინახავს და გადასცემს Git ისტორიას.

Git-ში ობიექტების შენახვის საფუძვლები

Git-ს უნდა შეეძლოს რეპოზიტორიუმის ორი ნაწილის სინქრონიზაცია: ობიექტებისა და მითითებების.

Git რეპოზიტორიუმი ფაილების მდგომარეობებსა და მათ დამაკავშირებელ ისტორიას ობიექტების გრაფის სახით ინახავს. ობიექტი შეიძლება იყოს ბლობი, ხე, კომიტი ან ტეგი. ბლობები ცალკეული ფაილის შიგთავსს ინახავს, ხოლო ხეები სახელებს ბლობებსა თუ სხვა ხეებს უკავშირებს და დირექტორიების სტრუქტურას ქმნის. კომიტები მიუთითებს ძირეულ ხეზე და ნულ ან მეტ მშობელ კომიტზე, რითაც თქვენი რეპოზიტორიუმის ისტორიას ქმნის.

ობიექტების იდენტიფიცირება მათი ტიპისა და შიგთავსის ჰეშით ხდება. ობიექტები უცვლელიცაა: შეცვლილი ფაილის ჩაწერა ახალ ბლობს ქმნის, უცვლელი ფაილებისა და დირექტორიებისთვის კი არსებული ობიექტების ხელახლა გამოყენება შეიძლება.

შტოები და ტეგები არის მითითებები, ანუ „refs“, რომლებიც კომიტებზე მიუთითებს. შტოში კომიტის შექმნისას ახალი კომიტი ემატება და შტოს მითითება მასზე გადასართავად ახლდება.

შტო refs/heads/main მიუთითებს კომიტ C2-ზე, რომლის მშობელია C1. C1 მიუთითებს ძირეულ ხე T1-ზე, სადაც parser.py ბლობ B1-ს უკავშირდება. C2 მიუთითებს ძირეულ ხე T2-ზე, სადაც parser.py ბლობ B2-ს უკავშირდება. ორივე ძირეულ ხეში docs/ ერთსა და იმავე ხეს, T3-ს, უკავშირდება. მისი ჩანაწერი README.md მიუთითებს ბლობ B3-ზე, ხოლო usage.md — ბლობ B4-ზე.

Git-ის ობიექტები ერთმანეთს ID-ით უკავშირდება: კომიტები — ხეებს, ხეები კი — სხვა ხეებსა და ბლობებს. შტო refs/heads/main მიუთითებს კომიტ C2-ზე, რომლის მშობელია C1. C1 მიუთითებს ძირეულ ხე T1-ზე, სადაც parser.py ბლობ B1-ს უკავშირდება. C2 მიუთითებს ძირეულ ხე T2-ზე, სადაც parser.py ბლობ B2-ს უკავშირდება. ორივე ძირეულ ხეში docs/ ერთსა და იმავე ხეს, T3-ს, უკავშირდება. მისი ჩანაწერი README.md მიუთითებს ბლობ B3-ზე, ხოლო usage.md — ბლობ B4-ზე.

Git ობიექტებს „ცალკეული“ ან „შეფუთული“ სახით ინახავს. ცალკეული ობიექტები ინახება ინდივიდუალურ ფაილებში, რომლებიც ობიექტის ID-ით იდენტიფიცირდება. შეფუთული ობიექტები ერთად ინახება პაკეტის ფაილში, რაც მსგავსი ობიექტების ერთმანეთის მიმართ სხვაობების სახით შენახვის საშუალებას იძლევა.

$GIT_DIR/objects-ში parser.py-ის ორი ვერსია ჩანს. ცალკეული ობიექტების სახით ბლობი A შეიცავს parse()-ს, ხოლო ბლობი B — parse()-საც და parse_file()-საც. პაკეტის ფაილი A-ს სრულად ინახავს, B-ს კი წარმოადგენს ინსტრუქციებად: დაკოპირდეს მთელი A და დაემატოს parse_file(). თანმხლები *.idx ფაილი ორივე ბლობის მდებარეობას პაკეტის ფაილში ობიექტის ID-ით განსაზღვრავს.

Git-ს შეუძლია ბლობები ცალკე ფაილებად შეინახოს ან ერთად შეფუთოს და ერთი ბლობი მეორის მიმართ სხვაობის სახით დააკოდიროს.

Git-ში ობიექტი კომიტიდან მიღწევადია, თუ Git-ს მისი პოვნა ამ კომიტიდან მშობლებზე, ხეებსა და ბლობებზე მიმავალი კავშირების გაყოლით შეუძლია. წამოღებისას კლიენტი სერვერს აცნობებს, რომელი კომიტები სურს და რომელი აქვს უკვე. სერვერი პოულობს მოთხოვნილი კომიტებიდან მიღწევად ობიექტებს, გამორიცხავს მათ, რომლებიც, მისი ინფორმაციით, კლიენტს უკვე აქვს, და დარჩენილებს აგზავნის პაკეტის ფაილად იმავე ფორმატით, რომელსაც Git დისკზე იყენებს. სრული კლონირება ობიექტების გარეშე იწყება, ამიტომ მას კლონირებადი ისტორიიდან მიღწევადი ყველა ობიექტი სჭირდება.

გაგზავნა ობიექტებს საპირისპირო მიმართულებით გადასცემს და სერვერს ერთი ან მეტი მითითების განახლებას სთხოვს. კლიენტი სერვერის მიერ გამოცხადებული მითითებების ნაკრებს იყენებს, რათა სერვერზე უკვე არსებული ობიექტები აღარ გაგზავნოს. ამიტომ გასაგზავნი პაკეტი შეიძლება არსებულ ობიექტებზე იყოს დამოკიდებული: მხოლოდ პაკეტის მიღება ახალი ისტორიის აღსადგენად საკმარისი არ არის.

Git რეპოზიტორიუმის რეპლიკაცია ნიშნავს ობიექტებისა და მითითებების ხელმისაწვდომობის უზრუნველყოფას რამდენიმე სერვერზე. სანამ რეპლიკა მითითების ახალ მნიშვნელობას მიაწვდის, მას ამ მნიშვნელობიდან მიღწევადი ობიექტების მიწოდებაც უნდა შეეძლოს. სერვისმა ასევე უნდა მოახდინოს კონკურენტული მითითების განახლებების კოორდინაცია — ანუ გაგზავნებისა, რომლებიც ერთი შტოს ერთი და იმავე ძველი ბოლო კომიტიდან სხვადასხვა ახალ კომიტზე გადაყვანას ცდილობს. სისტემებში, რომლებიც რეპოზიტორიუმში ყველა ჩაწერას ერთ საერთო რიგს უწესებს, დაუკავშირებელ შტოებში გაგზავნებსაც შეიძლება ერთმანეთის ლოდინი მოუწიოს.

განაწილებული Git სერვისების არსებული მოდელები

Pando-ს დაპროექტებისას შევაფასეთ Git-ზე დაფუძნებული კოდის ვერსიების კონტროლის მასშტაბირების ტრადიციული მიდგომები: ერთი რეპოზიტორიუმის რეპლიკებს შორის მითითებების განახლებას სამფაზიანი ფიქსაციით კოორდინირებს (3PC — მრავალ კვანძზე ფიქსაციის კოორდინაციის პროტოკოლი); მეორე კი განახლებებს ბლობების საცავში საერთო წინასწარი ჩაწერის ჟურნალით ალაგებს (WAL — ცვლილებების ჩანაწერი, რომელიც მათ გამოყენებამდე იქმნება).

სამფაზიანი ფიქსაცია (3PC)

ჩვენ მიერ მოდელირებულ სამფაზიანი ფიქსაციის დიზაინში Git სერვისი რეპოზიტორიუმის სრულ ასლს რამდენიმე რეპლიკაზე ინახავს. როდესაც რომელიმე სერვერი გაგზავნილ მონაცემებს იღებს, შემომავალი პაკეტის ფაილი კოპირდება და ყველა რეპლიკას პარალელურად ეგზავნება. გაგზავნილი ცვლილებების გამოსაქვეყნებლად მითითების განახლება რეპლიკების უმრავლესობამ უნდა მიიღოს. ამ პროცესის მმართველი სერვერი კოორდინატორია; მასსა და თითოეულ სხვა რეპლიკას შორის კომუნიკაციის რამდენიმე რაუნდია საჭირო.

მითითების განახლების მისაღებად თითოეული რეპლიკა მითითების საკუთარ ასლს კეტავს და ამოწმებს, ისევ იმ კომიტზე მიუთითებს თუ არა, რომელსაც კლიენტი მოელის. შემდეგ კოორდინატორი თანხმობის გამომცხადებელ რეპლიკებს წინასწარი ფიქსაციის შეტყობინებას უგზავნის. როდესაც უმრავლესობა წინასწარი ფიქსაციის შეტყობინებას დაადასტურებს, კოორდინატორი მათ განახლების შესრულებას ავალებს. ამის შემდეგ ნებისმიერ განახლებულ რეპლიკას შეუძლია რეპოზიტორიუმის თავისი ლოკალური ასლიდან შტოს ახალი ბოლო კომიტი გამოაცხადოს.

სრული რეპლიკების შენახვა წაკითხვის ლოკალურად მომსახურებას შესაძლებელს ხდის და უზრუნველყოფს, რომ კლიენტებმა ყველა მითითების თანმიმდევრული სურათი მიიღონ, არჩეული რეპლიკის მიუხედავად. შედეგად, მითითებები სათითაოდ ახლდება და თითოეულ გაგზავნას რეპლიკებს შორის განახლების კოორდინაციისთვის მონაცემთა მიმოცვლის რამდენიმე სრული ციკლი სჭირდება.

კვორუმის ლოდინის გამო გაგზავნის ხანგრძლივობა რეპლიკების დისკის წარმადობასა და საკომუნიკაციო დაყოვნებაზეც ხდება დამოკიდებული. ჩაწერის მოცულობის ზრდასთან ერთად რეპლიკები შემომავალ პაკეტებსაც უნდა აუდიოდნენ და წაკითხვის ტრაფიკსაც.

წინასწარი ჩაწერის ჟურნალი (WAL)

ჩვენ მიერ მოდელირებულ WAL-ზე დაფუძნებულ დიზაინში Git სერვისი ბლობების საცავში საერთო აღწერის ფაილს იყენებს, რათა განახლებები მთელ რეპოზიტორიუმში დაალაგოს. როდესაც სერვერი გაგზავნილ მონაცემებს იღებს, შემომავალ პაკეტის ფაილს ბლობების საცავში ტვირთავს და რეპოზიტორიუმის ლოკალურ ასლში მითითების განახლებას ამზადებს. გაგზავნილი ცვლილებების გამოსაქვეყნებლად ის ბლობების საცავში შენახულ საერთო აღწერის ფაილს ამატებს ჩანაწერს, რომელიც მითითების განახლებას აღრიცხავს და პაკეტის ფაილზე მიუთითებს. შემდეგ Git სერვერი აღწერის ფაილს შედარება-ჩანაცვლების ოპერაციით აახლებს. ეს ოპერაცია აღწერის ფაილს ატომურად ანაცვლებს ან ცვლილებას უარყოფს. თუ ამასობაში ის სხვა ჩამწერმა განაახლა, სერვერი შუალედში დამატებულ ჩანაწერებს კითხულობს, ამოწმებს, კვლავ ვალიდურია თუ არა მისი მითითების განახლება, და უკვე ატვირთული პაკეტის ფაილით ხელახლა ცდის.

ჩამწერებს პაკეტის ფაილების პარალელურად ატვირთვა შეუძლიათ, მაგრამ დაუკავშირებელ შტოებში გაგზავნებიც კი ერთი და იმავე აღწერის ფაილის განახლებას მოითხოვს. შედარება-ჩანაცვლების წარმატებული ოპერაციის სრული ციკლის დრო ზღუდავს, რამდენად ხშირად შეუძლია რეპოზიტორიუმს ახალი აღწერის ფაილის გამოქვეყნება. დაბალი დაყოვნების მქონე ბლობების საცავი ამ ნაბიჯს აჩქარებს. ჯგუფურად დამუშავება ერთ აღწერის ფაილს რამდენიმე მითითების ერთდროულად განახლების საშუალებას აძლევს, თუმცა ამისთვის განახლებები რიგში უნდა ჩადგეს, რაც დაყოვნებას ზრდის.

ბლობების საცავს პაკეტის ფაილების პარალელურად მიღება შეუძლია, მაგრამ საერთო აღწერის ფაილის განახლებები კვლავ ერთმანეთს ეჯიბრება. მხოლოდ ბლობების საცავის სიმძლავრის გაზრდა ამ შემზღუდველ ფაქტორს ვერ აღმოფხვრის. თითოეულ რეპლიკას კვლავ სჭირდება ბლობების საცავიდან პაკეტების წაკითხვა და ინდექსირება, სანამ მათ ლოკალურად მიაწვდის. თუ შემომავალი ჩაწერების ტემპი ამ სამუშაოს აჭარბებს, რეპლიკები ჩამორჩება და კლიენტები ახლად გაგზავნილი კომიტების წამოღებას უფრო დიდხანს ელოდებიან.

Pando-ს არქიტექტურის შექმნა

ასე მივდივართ Pando-მდე. Pando არის Git რეპოზიტორიუმების მომსახურების ახალი არქიტექტურა, რომლის მიზანია მრავალი კლიენტის ერთდროული გაგზავნების მასშტაბზე მუშაობა. აი, როგორ მუშაობს ის:

შეზღუდვების გადააზრება

Pando-ს შექმნამდე ვვარაუდობდით, რომ ჩვენს მოთხოვნებს Git-ზე უარის თქმის გარეშე დავაკმაყოფილებდით. თუმცა ზოგიერთი პირობის დათმობა დაგვჭირდა, რომელსაც Git-ის სისტემების უმეტესობა აუცილებელ მოთხოვნად მიიჩნევს:

  • თანმიმდევრულობა მთელ რეპოზიტორიუმში: ყველა მითითების თანმიმდევრული, დროის ერთი მომენტის ამსახველი მდგომარეობის მისაღებად საჭიროა კოორდინაცია მთელ რეპოზიტორიუმში. სისტემაში, რომელიც ყველა მითითების განახლებას საერთო რიგში აქცევს, ერთმანეთთან დაუკავშირებელ შტოებში გაგზავნები კოორდინაციის ერთ წერტილში ეჯიბრება ერთმანეთს.

  • უნიკალური პაკეტის ფაილები ყოველი კლიენტისთვის: თუ განსხვავებული ლოკალური ისტორიის მქონე ორი კლიენტი ერთსა და იმავე შტოს წამოიღებს, სერვერს შეიძლება თითოეულისთვის განსხვავებული პაკეტის შექმნა დასჭირდეს, რათა მათ უკვე არსებული ობიექტები აღარ გაუგზავნოს. ამ პასუხების შექმნა მოითხოვს პროცესორის რესურსსა და დისკზე შეტანა-გამოტანის ოპერაციებს, რაც წამკითხველების დიდი რაოდენობის მომსახურებას ართულებს.

ამის ნაცვლად, ჩაწერების მასშტაბირებისთვის Pando იყენებს ნაკლებად მკაცრ თანმიმდევრულობის მოდელს (მიზეზობრივ თანმიმდევრულობას), ხოლო წაკითხვების მასშტაბირებისთვის — პაკეტის ფაილების ხელახალ გამოყენებას.

მიზეზობრივი თანმიმდევრულობა (CC)

როდესაც კლიენტი შტოში მონაცემებს აგზავნის, Pando მიღებულ პაკეტის ფაილს ბლობის საცავში უცვლელ ბლობად ინახავს. შტოს ყოველი მოძრაობისას Pando მეტამონაცემების საცავში წერს მითითების ვერსიას, რომელიც შეიცავს ახალ ბოლო კომიტს, მის მომწოდებელ პაკეტსა და მითითებების ყველა წინა ვერსიას, რომლებზეც ეს პაკეტია დამოკიდებული. ბლობების საცავიც და მეტამონაცემების საცავიც ჰორიზონტალურად მასშტაბირდება.

Pando-დან კომიტის ან მითითების წამოსაღებად საჭიროა კლიენტისთვის მითითების ვერსიების ნაკრების (პაკეტის ფაილების) მიწოდება, რათა აღდგეს იმ კლიენტის მდგომარეობა, რომელმაც მოთხოვნილი მითითების ვერსია შექმნა. ეს მთელ რეპოზიტორიუმში თანმიმდევრულობის უფრო სუსტ ფორმას უზრუნველყოფს, თუმცა ცალკეული მითითებების განახლებები სერიალიზებადი რჩება. კლიენტებს შორის კონფლიქტი მხოლოდ მაშინ ხდება, როცა ისინი ერთსა და იმავე მითითებაში ერთდროულად აგზავნიან მონაცემებს. კლიენტი, რომელიც რამდენიმე შტოს კითხულობს, ვერ ჩათვლის, რომ ეს წაკითხვები მთელ რეპოზიტორიუმში დროის ერთსა და იმავე მომენტს ასახავს.

მარცხნივ ძირითადი შტოს სამი თანმიმდევრული პაკეტი შეიცავს კომიტებს: A, B და C; D და E; და F. მარჯვნივ ძირითადი და თემატური შტოები C-ზე იყოფა. ძირითადი შტო G-მდე მიდის, თემატური კი D-ს, E-სა და F-ს გაივლის. თემატური შტოს უახლესი პაკეტი შეიცავს D-ს, E-სა და F-ს. წყვეტილი კონტური მიუთითებს, რომ D და E თემატური შტოს წინა პაკეტშიც არის. ლურჯი ისარი აღნიშნავს ახალი პაკეტის დამოკიდებულებას ძირითადი შტოს G მდგომარეობაზე. Git-ში F-ის მშობელია E.

ძირითად შტოში გაგზავნა ამატებს ინკრემენტულ პაკეტს, რომელიც ერთ ან მეტ კომიტს შეიცავს. გვერდით შტოში ყოველი გაგზავნა თემატური შტოს წინა კომიტებსაც მოიცავს, ამიტომ კლიენტს, რომელსაც ძირითადი შტოს გამოცხადებული ვერსია აქვს, თემატური შტოს წამოღება ერთი პაკეტით შეუძლია.

ეს მიზეზობრივი თანმიმდევრულობის ფორმაა. მითითების წამოსაღებად წამკითხველი ხედავს იმ ჩამწერის ისტორიას, რომელმაც ეს მითითება შექმნა. გაგზავნისას Pando აკონტროლებს, რომელ საერთო ისტორიაზე თანხმდებიან კლიენტი და სერვერი, რათა კლიენტებმა უფრო მარტივად გასაზიარებელი პაკეტის ფაილები შექმნან.

შესაბამისად, Git-ის ოპერაციებისას Pando არ უზრუნველყოფს ყველა მითითების დროის ერთი მომენტის შესაბამის მდგომარეობას ან კლონირებისა თუ წამოღების ფარგლებში მითითებების განახლებების საერთო რიგს. მაგალითად, დავუშვათ, რომ სრული კლონირების შეთანხმების ეტაპზე ორივე შტო — foo და bar — განახლდა. შეთანხმებისას ერთმა კლიენტმა შეიძლება დაინახოს foo-ს ვერსია 1 და bar-ის ვერსია 2, მეორემ კი — foo-ს ვერსია 2 და bar-ის ვერსია 1. პრაქტიკაში მომხმარებლებისა და აგენტებისთვის მითითებების განახლებების გლობალური რიგი მნიშვნელოვანი არ არის; ისინი ცალკეული მითითების განახლებების რიგს ეყრდნობიან.

მიდგომების შედარება

თანმიმდევრულობის სამი მოდელის ამ სიმულაციაში 1 000 კლიენტიდან თითოეულს განსხვავებულ შტოს ვარჩევინებთ და შემდეგ უნიკალურ კომიტებს განმეორებით ვაგზავნინებთ. ვზომავთ მთლიან გასულ დროსა და გაგზავნიდან წამოღებამდე დაყოვნებას. ეს უკანასკნელი სამუშაო დატვირთვის მნიშვნელოვანი საზომია: ის ზომავს სრულ ციკლზე საჭირო დროს მომხმარებლებისა და აგენტების თანამშრომლობისთვის ან ვერსიების კონტროლზე დამოკიდებული სხვა სისტემების გამოსაყენებლად. სიმულაცია მოიცავს სხვადასხვა კლასის რესურსებს — სტანდარტულიდან პრემიუმ ვირტუალურ მანქანებამდე და ბლობების შენახვის სისტემებამდე. ამ სიმულაციაში სამფაზიანი ფიქსაციისთვის რეპოზიტორიუმის საერთო თანმიმდევრულობის მოთხოვნა შევარბილეთ.

Simulating Git Server Implementations

Follow each writer through repeated pushes, and separately measure when an independent reader can check out each commit.

Three-phase commit

Ready
Simulated time
0 s
Mean push to fetch
—
Writers done
0 / 1,000

Each square represents one writer. All selected architectures run the same workload. Squares lighten as pushes are acknowledged and turn blue when a writer finishes. The chart shows writers finished over simulated time; independent readers can continue fetching afterward. Use arrow keys to select a writer, Home or End to jump, and Escape to clear.

0 / 10,000 pushes acknowledged · 0 fetched

Select a square to inspect that writer.

Object-store WAL

Ready
Simulated time
0 s
Mean push to fetch
—
Writers done
0 / 1,000

Each square represents one writer. All selected architectures run the same workload. Squares lighten as pushes are acknowledged and turn blue when a writer finishes. The chart shows writers finished over simulated time; independent readers can continue fetching afterward. Use arrow keys to select a writer, Home or End to jump, and Escape to clear.

0 / 10,000 pushes acknowledged · 0 fetched

Select a square to inspect that writer.

Pando

Ready
Simulated time
0 s
Mean push to fetch
—
Writers done
0 / 1,000

Each square represents one writer. All selected architectures run the same workload. Squares lighten as pushes are acknowledged and turn blue when a writer finishes. The chart shows writers finished over simulated time; independent readers can continue fetching afterward. Use arrow keys to select a writer, Home or End to jump, and Escape to clear.

0 / 10,000 pushes acknowledged · 0 fetched

Select a square to inspect that writer.

Writer progress through verified fetches

  • Three-phase commit
  • Object-store WAL
  • Pando
05001,00000 s
  • Waiting
  • Pushing
  • All pushes acknowledged
0 sLater

Synthetic teaching models, not production benchmarks. Mean push to fetch covers topic pushes, from the first attempt through retries until an independent reader verifies that commit. It includes waiting for a reader slot and excludes builds and tests. With merges enabled, writer completion includes the required fetches and trunk merge.

Experiment settings

Preparing simulation…

Results

Play the comparison to see the recorded results.

Synthetic teaching models, not production benchmarks. Mean push to fetch covers topic pushes, from the first attempt through retries until an independent reader verifies that commit. It includes waiting for a reader slot and excludes builds and tests. With merges enabled, writer completion includes the required fetches and trunk merge.

გაუშვით ეს სიმულაცია, რათა 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.

Stream the push

  • Packfile bytes
  • Metadata
  • Request / acknowledgment
  • Packfile URIs

აგენტი ლოკალურად ასწორებს ფაილებს, ქმნის კომიტს და ასრულებს git push-ს, რომელიც ამ ცვლილებების პაკეტის ფაილს ქმნის შტოს გასაახლებლად. Pando იღებს პაკეტს და ნაკადად გადასცემს ბლობების საცავს. შემომავალი გაგზავნის ერთჯერადი დეკოდირებით შემოწმების შემდეგ Pando მრავალგასაღებიან ტრანზაქციას იყენებს, რათა მეტამონაცემების საცავში მითითების ვერსია ჩაწეროს და მითითების მაჩვენებელი ატომურად განაახლოს. ამით Pando უზრუნველყოფს თანმიმდევრულობას პრინციპით „წაიკითხე შენივე ჩაწერილი“. ჩაწერის მთელი ეს ოპერაცია მეტამონაცემების O(1)O(1) წაკითხვასა და ჩაწერას მოითხოვს.

როდესაც სხვა კლიენტი შტოს წამოიღებს, Pando შენახული პაკეტების ნაკრებს კლიენტთან უკვე არსებული ისტორიის საფუძველზე არჩევს. ამ ოპერაციას სჭირდება მეტამონაცემების O(log⁡Δ)O(\log \Delta) წაკითხვა, სადაც Δ\Delta არის უმოკლესი მანძილი, მითითების ვერსიებით გაზომილი, კლიენტთან არსებულსა და მისთვის სასურველ მდგომარეობას შორის. სერვერი აბრუნებს პაკეტის ფაილების URI-ებს, კლიენტი კი მათ ჩამოტვირთავს Express სერვისით, რომელიც პაკეტის ფაილებს რეგიონულ ქეშებში ინახავს.

ეს დიზაინი ეყრდნობა Pando-ს არქიტექტურის სამ ძირითად სერვისს: გაგზავნას, წამოღებასა და გაერთიანებას.

გაგზავნის მასშტაბირება

როდესაც კლიენტი მონაცემებს აგზავნის, ტრადიციული Git სერვერი პოკერის მოთამაშეს ჰგავს, რომელიც ყველა კარტს აჩვენებს — ის კლიენტს ყველა არსებულ შტოს აცნობს. შემდეგ კლიენტი აგროვებს კომიტებს, ხეებსა და ბლობებს და ქმნის პაკეტის ფაილს, რომელშიც არ შედის ობიექტები, რომლებიც, მისი ინფორმაციით, სერვერს უკვე აქვს.

მეტი მითითების გამოცხადებამ შეიძლება გასაგზავნი მონაცემების ზომა შეამციროს. თუმცა ამან პაკეტის ხელახალი გამოყენებაც შეიძლება გაართულოს, რადგან სხვა კლიენტს შესაძლოა არ ჰქონდეს ობიექტები, რომლებიც ჩამწერმა გამოტოვა.

Pando განსხვავებულ მიდგომას იყენებს. ყველა კარტის ჩვენების ნაცვლად, ის კლიენტს მხოლოდ შერჩეულ შტოებს უცხადებს. ამას ორი მიზეზი აქვს:

  1. ყველა მითითების თანმიმდევრული წარმოდგენის უზრუნველყოფა ძვირი ჯდება. მილიონობით შტოს შემთხვევაში მხოლოდ მითითებების გამოცხადების მოცულობამ შეიძლება 100 MiB-ს გადააჭარბოს. ამისთვის თითოეულმა სერვერმა ან აქტუალური შესაბამისობების სია უნდა შეინარჩუნოს, რაც კოორდინაციის დიდ დანახარჯს მოითხოვს, ან მონაცემთა ბაზას მიმართოს მოთხოვნით, რომლის მოცულობაც მითითებების რაოდენობასთან ერთად იზრდება.

  2. თუ კლიენტს მითითებების მხოლოდ ნაწილს მივაწვდით, ის შექმნის პაკეტს, რომელიც მხოლოდ იმ მონაცემებზე იქნება დამოკიდებული, რომელთა გამოტოვებაც სერვერმა მას პირდაპირ დაუშვა. დამოკიდებულებების აღრიცხვით Pando-ს შეუძლია, კლიენტის ერთი გაგზავნისას შექმნილი პაკეტის ფაილი ხელახლა გამოიყენოს და შემდგომი წამოღების მოთხოვნის პასუხად მიაწოდოს.

რაც მეტ მითითებას აცხადებს Git სერვერი, მით მეტი წყარო აქვთ გამგზავნ კლიენტებს ობიექტების გამოსარიცხად და მით მცირე პაკეტების შექმნა შეუძლიათ. თუმცა ამ პაკეტის ფაილების ხელახლა გამოსაყენებლად სერვერს უნდა შეეძლოს დადასტურება, რომ წამომღებ კლიენტებს ყველა დამოკიდებულება აქვთ. სხვაგვარად, პაკეტის ფაილში შეიძლება კლიენტისთვის საჭირო ობიექტები არ იყოს.

მეორე მხრივ, თუ Git სერვერი არცერთ მითითებას არ გამოაცხადებს, კლიენტი შექმნის პაკეტის ფაილს, რომელიც რეპოზიტორიუმის სრულ ისტორიას შეიცავს. ამ ფაილის გამოყენება ნებისმიერ სხვა კლიენტს შეუძლია, თუმცა დიდი დანახარჯის ფასად: ნებისმიერი შტოს წამოღება ფაქტობრივად სრულ კლონირებად იქცევა.

მრუდი აჩვენებს, როგორ მოქმედებს გამოცხადებული მითითებები პაკეტის ფაილის ზომაზე: მითითებების გარეშე ფაილი სრულ ისტორიას მოიცავს, ძირითადი შტოს გამოცხადებით მცირდება, ხოლო ყველა მითითების გამოცხადებისას მხოლოდ ახალ ობიექტებს შეიცავს.

მეტი მითითების გამოცხადება პაკეტის ფაილების ზომას ამცირებს. ზომის შემცირების უდიდესი ნაწილი შეიძლება მხოლოდ ერთი მითითების გამოცხადებამ უზრუნველყოს.

ნაგულისხმევად, როდესაც კლიენტი ახალი ფუნქციის შტოს აგზავნის, Pando საფუძვლად მხოლოდ ერთ, წინასწარ განსაზღვრულ ძირითად შტოს აცხადებს. ამით გამოცხადების ზომა უცვლელი რჩება რეპოზიტორიუმში შტოების მატების მიუხედავად, თუმცა ამას თავისი კომპრომისები ახლავს. როდესაც ინჟინერი ერთ შტოში მრავალჯერ აგზავნის ცვლილებებს ან ერთი ფუნქციის შტოზე მეორეს ქმნის, კლიენტმა ხელახლა უნდა გაგზავნოს ყველაფერი, რაც ძირითად შტოში არ არის.

ამის გამო შტოში ყოველი მომდევნო გაგზავნის მოცულობა იზრდება, შესაძლოა ზედმეტ ობიექტებსაც შეიცავდეს და კლიენტის დამატებითი ქსელური რესურსი მოიხმაროს. ჩვენს მონორეპოზიტორიუმში ამ გზით შექმნილი პაკეტის ფაილის მედიანური ზომა 20 KiB-ზე ნაკლები იყო, ხოლო 99-ე პროცენტილი — 3 MiB-ზე ნაკლები. ჩვენთვის ეს გონივრული კომპრომისი იყო, რადგან წამკითხველს, რომელსაც გამოცხადებული ძირითადი შტოს ისტორია უკვე აქვს, შტოს წამოღება ამ ერთი პაკეტის ფაილით შეუძლია.

კლიენტისთვის გამოსაცხადებელი მითითებების შერჩევის შემდეგ Pando იღებს გაგზავნილ მონაცემებს და მეტამონაცემების საცავს აახლებს. Pando მეტამონაცემების განახლებას სინქრონულ და ასინქრონულ ნაწილებად ყოფს. მეტამონაცემების სინქრონული განახლება უზრუნველყოფს, რომ კლიენტებმა ახლად განახლებული კომიტი დაუყოვნებლივ წამოიღონ. ამ დროს იწერება მითითების ახალი ვერსია და მისი მაჩვენებელი ამ ვერსიაზე გადადის. ინახება ახალი ბოლო კომიტი, პაკეტის ფაილის შეთანხმებისას გამოყენებული დამოკიდებულებები და გაგზავნილი პაკეტის ფაილის ბმული.

ამავე ტრანზაქციაში აღირიცხება ასინქრონული სამუშაოც, მაგალითად, გაერთიანება დაგეგმვა. ძალიან დიდი გაგზავნებისას სინქრონულად კომიტების მხოლოდ ნაწილი იწერება. ამით მეტამონაცემების საცავში წაკითხვებისა და ჩაწერების მუდმივი რაოდენობა გვჭირდება, გაგზავნის მოცულობის მიუხედავად.

მნიშვნელოვანია, რომ Pando-ს სერვერებს ერთმანეთთან დაუკავშირებელ მითითებებში გაგზავნების მიღება დამოუკიდებლად შეუძლია. ერთადერთი გასაღები, რომლისთვისაც კონკურენცია ხდება, მითითების მაჩვენებელია. მას ატომური შედარება-ჩანაცვლების მსგავსი ოპერაციით ვიცავთ. ჩაწერის მწარმოებლურობა შეგვიძლია გავზარდოთ Pando-ს სერვერების, მეტამონაცემების საცავის მასშტაბირების ერთეულების ან ბლობების საცავების დამატებით.

წამოღება და კლონირება ქსელის მაქსიმალური სიჩქარით

წამოღებისას კლიენტი სერვერს კომიტების ID-ების ორ ნაკრებს აწვდის, რომლებიც პროტოკოლში ცნობილია როგორც 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.

Already heldFetchMissing branch dependency

Fetch 27 trunk packs.

Select a branch to include its trunk dependencies.

Pando Git-ის პროტოკოლით განსაზღვრულ არსებულ და მოთხოვნილ კომიტებს მითითების ვერსიების მიმდევრობას უსადაგებს. გვერდითი შტოს მოთხოვნა გულისხმობს ძირითადი შტოს ისტორიის მოთხოვნასაც, იმ წერტილამდე, რომელზეც გვერდითი შტოა დამოკიდებული.

Git-ის პროტოკოლი კლონირებისა თუ წამოღებისას HTTP პასუხში მხოლოდ ერთი პაკეტის ფაილის გაგზავნას უშვებს. თუმცა Git-ის პროტოკოლის ნაკლებად დაფასებული შესაძლებლობა, packfile-uri, სერვერს დამატებითი პაკეტების ცალ-ცალკე ჩამოსატვირთი ბმულების დაბრუნების საშუალებას აძლევს. Pando მხოლოდ ამ გზას იყენებს, უშუალოდ პასუხში კი ცარიელ პაკეტის ფაილს გადასცემს. ამ შესაძლებლობის მხარდასაჭერად OpenAI-მ Git-ის ძირითად პროექტში packfile-uri-ის არაერთი გაუმჯობესება შეიტანა.

OpenAI-ს სისტემები მრავალ გეოგრაფიულ რეგიონში მუშაობს, ამიტომ თითოეულში Pando-ს კლასტერები და ლოკალური ქეშები გვაქვს. პაკეტების მიწოდების სერვისი Express ჩვენი ბლობების საცავის ქეშირებას ახდენს, ცალკე სერვისი კი — მეტამონაცემების საცავისას. ამ ქეშების მეშვეობით Pando კომიტის ID-ის მოთხოვნებსა თუ მითითების სპეციალური წაკითხვის მოთხოვნებს მთლიანად იმავე კლასტერის ქეშირებული მდგომარეობიდან პასუხობს. პაკეტის ფაილის მოთხოვნების Express სერვერებზე გადასანაწილებლად თანმიმდევრულ ჰეშირებას ვიყენებთ; ქეშში მოხვედრის მაჩვენებელი 99%-ს აღემატება.

ქეშების ეს სისტემა უკიდურესად მაღალ მწარმოებლურობას უზრუნველყოფს და კლიენტებსა და Pando-ს შორის ქსელის გამტარუნარიანობის სრულად ათვისება შეუძლია. პაკეტის ფაილების ამ URI-ებისა და ლოკალური ქეშების გამოყენებით დავადასტურეთ, რომ მხოლოდ ღრუბლოვანი პროვაიდერების სტანდარტულ ვირტუალურ მანქანებზეც კლონირებისა და წამოღების ოპერაციები 10 გბიტ/წმ ქსელურ კავშირებს სრულად ტვირთავს.

გაერთიანება და პირველ ბაიტამდე დრო

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.

Compaction in progressPublished cover

გაერთიანება ფონურად აერთიანებს მითითების მრავალი ვერსიის პაკეტის ფაილებს, რაც ნაკლები ფაილით უფრო ეფექტიან წამოღებას უზრუნველყოფს.

ბევრი Git სერვერისგან განსხვავებით, პაკეტის ფაილები ყველა დონეზე რჩება და არც იშლება, არც გამოუყენებელ მონაცემებად იწმინდება. კლიენტების უწყვეტი მომსახურებისთვის ყველა დონის პაკეტები გამოიყენება, წამოღების მოთხოვნაში მითითებული have და want ნაკრებების მიხედვით. იმ კლიენტებისთვის კი, რომლებიც Pando-ს API-დ იყენებენ, პაკეტის ფაილიდან ნებისმიერი ობიექტის წაკითხვა, ჩვეულებრივ, L0-დან უფრო ნაკლები მონაცემის წაკითხვას მოითხოვს, ვიდრე L4-დან, რადგან ნაკლებად სავარაუდოა, რომ ობიექტი შეკუმშული იყოს.

Pando-ში გაერთიანება მნიშვნელოვნად ამცირებს კლიენტებისთვის გადაცემულ მთლიან მოცულობას და პაკეტების დაგეგმვის დანახარჯს საშუალებას აძლევს, კლიენტის ჩამორჩენასთან შედარებით სუბწრფივად გაიზარდოს. ეს განსაკუთრებით მნიშვნელოვანია დიდი და სწრაფად ცვალებადი რეპოზიტორიუმებისთვის, რომლებიც, ჩვენი მოლოდინით, პროგრამული უზრუნველყოფის შემუშავებაში ახალ ნორმად იქცევა.

Pando-ს შექმნა

Pando Codex-ით შევქმენით და პროექტის დაწყებიდან საწარმოო გარემოში გაშვებამდე მხოლოდ 10 კვირა დაგვჭირდა. Pando-ს ბირთვი ერთმა ინჟინერმა დააპროექტა, აგენტების გუნდებმა განახორციელეს და რამდენიმე ინჟინერმა დანერგა. Pando-მ საწარმოო ტრაფიკის მომსახურება მიმდინარე წლის აპრილში დაიწყო და OpenAI-ში გამოყენებული კოდის ვერსიების მართვის ხელსაწყოების უფრო ფართო სისტემის ნაწილია.

Pando-ს დიზაინის შესამოწმებლად მრავალფეროვანი მიდგომები გამოვიყენეთ. გამოვიყენეთ ჩვენი პრინციპები უფრო უსაფრთხო პროგრამული საფუძვლების შესაქმნელად⁠. რადგან პროექტს ნულიდან ვიწყებდით, Pando-ს Rust-ში და მოძველებული დამოკიდებულებების გარეშე განხორციელება გადავწყვიტეთ. დავწერეთ შესაბამისობის ტესტების ნაკრები, რათა აგენტებს თავიანთი ცვლილებები Git-ის სტანდარტულ ქცევასთან შეედარებინათ. ასევე შევქმენით დეტერმინისტული სიმულაციური ტესტირების გარემოები სისტემის ინვარიანტებისა და თვისებების შესამოწმებლად. მათი მეშვეობით ვიპოვეთ და შევამცირეთ რთულად შესამჩნევი რბოლის მდგომარეობები და რეგრესიები შეთანხმებისა და პაკეტების დაგეგმვის პროცესებში.

ამ სისტემის შექმნაში მრავალმა მოდელმა შეიტანა წვლილი; ახალი მოდელების გამოჩენისთანავე მათ Pando-ს წარმადობისა და საიმედოობის გასაუმჯობესებლად ვიყენებდით. GPT‑6 Astra-ს გამოყენებით აგენტებმა Lean-სა და TLA+-ში დაწერეს „Pando-ს თეორიის“ ფორმალური აღწერა, რომელიც განხორციელებაში შეცდომების საპოვნელად და გამოსასწორებლად, ასევე სისტემის თვისებების დასამტკიცებლად გამოვიყენეთ. რამდენიმე უწყვეტი სესია ასობით საათს მუშაობდა Pando-ში ზღვრული შემთხვევების მოსაძებნად და გამოსასწორებლად. ასევე დღე-ღამის განმავლობაში ვამუშავებთ აგენტებს Daybreak-ის შესაძლებლობების მქონე მოდელებით, რათა Git-სა და Pando-ზე მოწინააღმდეგის როლში უსაფრთხოების ტესტირება ჩაატარონ.

Pando-ს დანერგვა

თავდაპირველად Pando დავნერგეთ პროქსიდ, რომელიც წაკითხვებსა და ჩაწერებს ჩვენს არსებულ კოდის ვერსიების კონტროლის სისტემაში ატარებდა. ეს საშუალებას გვაძლევდა, Pando და წინა სისტემა სინქრონულად შეგვენარჩუნებინა და ტრაფიკი Pando-ზე უსაფრთხოდ, მუშაობის შეწყვეტის გარეშე გადაგვეტანა.

ქეშირების დიზაინის ფარგლებში Pando-ს ასევე შეუძლია მოთხოვნების დუბლიკატების მოცილება და მოთხოვნების გაერთიანება პროქსირებამდე. ამის წყალობით არსებული ხელსაწყოები გამართულად მუშაობდა, სანამ სისტემები Pando-ზე სათითაოდ გადაგვქონდა. რაც მეტი სამუშაო დატვირთვა გადაგვქონდა Pando-ზე, მით მეტად ივსებოდა მისი ქეში გაგზავნილი მონაცემებით და უმჯობესდებოდა ჩვენი წინა სერვერული სისტემის საიმედოობა.

Pando-ს გამოყენებისას წარმადობის ოპტიმიზაციისთვის დეველოპერების კომპიუტერებსა და ChatGPT‑ის დესკტოპაპში Git-ის ჩვენი საჯარო დისტრიბუციის მიწოდება დავიწყეთ. კლიენტების Pando-ზე ეტაპობრივად გადასაყვანად Git-ის CLI-ის გარშემო შექმნილი შიდა გარსი გამოვიყენეთ. შევქმენით მრავალი სხვა ხელსაწყო ცვლილების მოთხოვნების სამართავად და კოდის მიმოხილვისთვის, ასევე ავტომატიზაციის API-ები. Git-ის ტრაფიკთან ერთად გადავიტანეთ ასობით ინტეგრაცია, რომლებიც ძველ API-ებზე, ვებჰუკებსა და რეპოზიტორიუმების ჩამოტვირთვებზე იყო დამოკიდებული.

გადასვლაში დეველოპერებსა და გუნდებს თავად Codex ეხმარებოდა. შევქმენით უნარები არსებული სამუშაო ასლების მოსამზადებლად და აგენტებისთვის ახალი სისტემის გამოყენებაში გზის გასაკვლევად. შედეგად, დეველოპერებს შეეძლოთ, უბრალოდ Codex-ისთვის ეთხოვათ თავიანთი შემუშავების გარემოებისა და სერვისების გადატანა.

Pando-ზე გადასვლამ შერწყმის საიმედოობა გააუმჯობესა და გაგზავნის მედიანური დაყოვნება თითქმის 80%-ით შეამცირა.

Pando-ს დღეში ერთი პეტაბაიტი Git მონაცემის მიწოდება პროცესორის სულ რამდენიმე ბირთვით შეუძლია. Pando-ს ერთ საათში 57 ტერაბაიტზე მეტი Git პაკეტი მიუწოდებია, ამ ბაიტების 99%-ზე მეტი კი დისკის ლოკალური ქეშიდან იყო.

პაკეტების ხელახალი გამოყენება მრავალ კლიენტს ერთი და იმავე რეპოზიტორიუმის ისტორიის ჩამოტვირთვის საშუალებას აძლევს, მომსახურე კვანძებზე მცირე გამოთვლითი დანახარჯით. ამ მაგალითში ერთი რეპოზიტორიუმია ნაჩვენები, თუმცა Pando გაცილებით მეტის მხარდასაჭერადაა შექმნილი. მოთხოვნის ზრდასთან ერთად მონაცემების მიწოდებისა და Git-ის შეთანხმების პროცესების დამოუკიდებლად მასშტაბირება შეგვიძლია.

Git-ის პროექტში წვლილის შეტანა

Pando-ს Git-ის პროტოკოლსა და კლიენტზე დაფუძნებამ თავად Git-ში შეცდომებისა და წარმადობის გაუმჯობესების შესაძლებლობების აღმოჩენაში დაგვეხმარა.

მაგალითად, Pando ხელახლა გამოყენებად პაკეტებს პირდაპირ კლიენტებს აწვდის, ამიტომ მათი ჩამოტვირთვა და ინდექსირება სწრაფი და საიმედო სისტემის შექმნის საკვანძო ნაწილად იქცა. ამ სამუშაომ გამოავლინა ზღვრული შემთხვევები პარალელურ ჩამოტვირთვებში, შეწყვეტილი გადაცემების შემდეგ გასუფთავებასა და უკვე დასრულებული ჩამოტვირთვების განახლებაში. გამოვასწორეთ ეს სცენარები, დავამატეთ შემოწმებები წამოღებისთვის არსებული პაკეტის მიღებისას და ეს ნამუშევარი ძირითად პროექტში შევიტანეთ.

ასევე გვჭირდებოდა დაგვენახა, რაში იხარჯებოდა დრო და ქსელური რესურსი, ამიტომ დავამატეთ packfile-uri-ით ჩამოტვირთვების ტრასირება და პაკეტების შექმნისას ბაიტების დათვლა. ამით გაადვილდა გარკვევა, ნელი წამოღებისას დრო პაკეტების შექმნაზე იხარჯებოდა თუ მათ გადაცემაზე.

OpenAI-ს Git-ის ვერსიაში⁠(იხსნება ახალ ფანჯარაში) კლიენტს დამოუკიდებელი პაკეტების პარალელურად ჩამოტვირთვა და ინდექსირება შეუძლია. დავამატეთ „აშკარად მითითებული არსებული კომიტების“ ცნება, რათა სერვერმა შტოს მიმდინარე ბოლო კომიტი გამოაცხადოს იმ ისტორიისგან განცალკევებით, რომლის გამოტოვებაც გამგზავნ კლიენტს თავისი პაკეტიდან შეუძლია. Pando-ში ეს კლიენტებს საშუალებას აძლევს, --force-with-lease-ით შეამოწმონ, რომ ფუნქციის შტო არ შეცვლილა, პაკეტი კი მხოლოდ ძირითად შტოზე დაყრდნობით ააგონ. ამის შემდეგ ყველას, ვისაც ძირითადი შტოს ეს ისტორია აქვს, შტოს წამოღება იმავე პაკეტით შეუძლია.

ამ გაუმჯობესებებიდან რამდენიმე უკვე Git-ის ძირითად პროექტშია, მრავალი სხვა კი — ჩვენს საჯარო რეპოზიტორიუმში. ვაგრძელებთ Git-ის საზოგადოებასთან მუშაობას, რათა ეს გაუმჯობესებები Pando-ს ფარგლებს გარეთაც სასარგებლო იყოს. ამ სამუშაოს შეგიძლიათ თვალი ადევნოთ ჩვენს შესწორებების საჯარო ტრეკერში⁠(იხსნება ახალ ფანჯარაში).

შემდეგი ნაბიჯები

Git-ის რეპოზიტორიუმების მასშტაბირების დამკვიდრებული მიდგომების გადააზრებით Pando საშუალებას გვაძლევს, გავზარდოთ ჩვენი მონორეპოზიტორიუმი ისე, რომ ინჟინრებისა და აგენტების არსებული Git სამუშაო პროცესები არ შევცვალოთ. ჩვენს მონორეპოზიტორიუმში Pando-მ გაზარდა პარალელურად მუშაობის შესაძლებლობა, გააუმჯობესა შერწყმის საიმედოობა და შეამცირა კოდის ცვლილებების გამოქვეყნებისთვის საჭირო დრო. მონორეპოზიტორიუმის გარდა, OpenAI-ში Pando-ს გამოყენების სხვა გზებსაც ვიკვლევთ, მათ შორის ისეთ ამოცანებს, სადაც უამრავ აგენტს საერთო Git რეპოზიტორიუმში თანამშრომლობა სჭირდება.

რაც უფრო მეტ პროგრამულ უზრუნველყოფას შექმნიან ინჟინრები და აგენტები, მით მეტი გუნდი OpenAI-ს ფარგლებს გარეთ წააწყდება კოდის ვერსიების კონტროლის იმ შეზღუდვებს, რომლებსაც ჩვენ მივადექით. ამჟამად ვიკვლევთ, როგორ გავუზიაროთ მომხმარებლებს ტექნოლოგია, რომელსაც Pando ეფუძნება.

Pando ეყრდნობა Git რეპოზიტორიუმების მომხმარებლებისა და ოპერატორების ორ ათწლეულში დაგროვილ გამოცდილებას. გავაგრძელებთ Pando-ს განვითარებას და Git-ის ღია კოდის საზოგადოებასთან თანამშრომლობას, რათა გავაზიაროთ ყველა გაუმჯობესება, რომელიც Git-ის მომხმარებელთა ფართო წრეს გამოადგება.

ავტორი

OpenAI