Programuotojų ir inžinierių folkloras (1 dalis)

Programuotojų ir inžinierių folkloras (1 dalis)

Tai istorijų iš interneto rinkinys apie tai, kaip klaidos kartais turi visiškai neįtikėtinų pasireiškimų. Galbūt ir jūs turite ką papasakoti.

Automobilių alergija vaniliniams ledams

Istorija inžinieriams, kurie supranta, kad atsakymas ne visada yra akivaizdus ir kad ir kokie toli atrodytų faktai, jie vis tiek yra faktai. „General Motors Corporation“ „Pontiac“ padalinys gavo skundą:

Rašau tau antrą kartą ir nekaltinu tavęs, kad neatsakai, nes skamba beprotiškai. Mūsų šeima turi tradiciją valgyti ledus kiekvieną vakarą po vakarienės. Ledų rūšys kaskart keičiasi, o po vakarienės visa šeima renkasi, kokius ledus pirkti, po kurių aš einu į parduotuvę. Neseniai nusipirkau naują Pontiac ir nuo tada mano kelionės nusipirkti ledų tapo problema. Matote, kiekvieną kartą, kai perku vanilinius ledus ir grįžtu iš parduotuvės, automobilis neužsiveda. Jei atnešu kokių kitų ledų, mašina užveda be jokių problemų. Noriu užduoti rimtą klausimą, kad ir kaip kvailai tai skambėtų: „Kas yra tas „Pontiac“, kad jis neužsiveda, kai atnešu vanilinius ledus, o lengvai įsijungia, kai atnešu kito skonio ledus?

Kaip galite įsivaizduoti, skyriaus pirmininkas skeptiškai žiūrėjo į laišką. Tačiau tik tuo atveju nusiunčiau inžinierių patikrinti. Jis nustebo, kad jį pasitiko turtingas, išsilavinęs vyras, gyvenantis gražioje vietovėje. Jie susitarė susitikti iškart po vakarienės, kad jiedu galėtų nueiti į parduotuvę ledų. Tą vakarą tai buvo vanilė, o kai jie grįžo į automobilį, jis neužsivedė.

Inžinierius atvyko dar tris vakarus. Pirmą kartą ledai buvo šokoladiniai. Automobilis užsivedė. Antrą kartą buvo braškiniai ledai. Automobilis užsivedė. Trečią vakarą jis paprašė paimti vanilės. Automobilis neužsivedė.

Racionaliai samprotavęs inžinierius atsisakė patikėti, kad automobilis alergiškas vaniliniams ledams. Todėl susitariau su automobilio savininku, kad jis tęs savo vizitus, kol ras problemos sprendimą. O pakeliui ėmė užsirašinėti: užsirašė visą informaciją, paros laiką, benzino rūšį, atvykimo ir grįžimo iš parduotuvės laiką ir t.t.

Netrukus inžinierius suprato, kad automobilio savininkas mažiau laiko sugaišo pirkdamas vanilinius ledus. Priežastis buvo prekių išdėstymas parduotuvėje. Vaniliniai ledai buvo populiariausi ir buvo laikomi atskirame šaldiklyje parduotuvės priekyje, kad būtų lengviau juos rasti. O visos kitos veislės buvo parduotuvės gale, o rasti tinkamą veislę ir sumokėti užtruko daug daugiau laiko.

Dabar klausimas buvo skirtas inžinieriui: kodėl automobilis neužsivedė, jei nuo variklio išjungimo momento praėjo mažiau laiko? Kadangi problema buvo laikas, o ne vaniliniai ledai, inžinierius greitai rado atsakymą: tai buvo dujinis užraktas. Tai pasitaikydavo kiekvieną vakarą, tačiau automobilio savininkui praleidus daugiau laiko ledų paieškai, variklis spėjo pakankamai atvėsti ir lengvai užsivedė. O kai vyras pirko vanilinius ledus, variklis dar buvo per karštas, o dujų spynelė nespėjo ištirpti.

Moralas: Net visiškai beprotiškos problemos kartais būna tikros.

Crash Bandicoot

Skaudu tai patirti. Kaip programuotojas, tu įpranti kaltinti savo kodą pirma, antra, trečia... o kažkur dešimtoje tūkstantinėje vietoje kaltini kompiliatorių. Ir toliau sąraše jūs jau kaltinate įrangą.

Štai mano istorija apie aparatinės įrangos klaidą.

Žaidimui Crash Bandicoot parašiau kodą įkelti ir išsaugoti atminties kortelėje. Tokiam pasipūtusiam žaidimų kūrėjui tai buvo kaip pasivaikščiojimas parke: maniau, kad darbas užtruks kelias dienas. Tačiau galiausiai šešias savaites derinau kodą. Pakeliui sprendžiau kitas problemas, bet kas kelias dienas kelioms valandoms grįždavau prie šio kodo. Tai buvo agonija.

Požymis atrodė taip: išsaugojus dabartinį žaidimo paleidimą ir prisijungus prie atminties kortelės, viskas beveik visada pavyksta... Tačiau kartais skaitymo ar rašymo operacijos laikas baigiasi be aiškios priežasties. Trumpas įrašymas dažnai sugadina atminties kortelę. Kai žaidėjas bando išsaugoti, jam ne tik nepavyksta išsaugoti, bet ir sunaikina žemėlapį. Kvailas.

Po kurio laiko mūsų gamintoja „Sony“ Connie Bus pradėjo panikuoti. Negalėjome išsiųsti žaidimo su šia klaida, o po šešių savaičių aš nesupratau, kas sukėlė problemą. Per Connie susisiekėme su kitais PS1 kūrėjais: ar kas nors susidūrė su kažkuo panašiu? Nr. Niekas neturėjo problemų su atminties kortele.

Kai neturite minčių derinti, belieka tik „skaldyti ir užkariauti“: pašalinti vis daugiau kodo iš sugedusios programos, kol liks santykinai mažas fragmentas, kuris vis dar sukelia problemą. Tai yra, jūs nupjaunate programą po gabalo, kol lieka dalis, kurioje yra klaida.

Tačiau iš vaizdo žaidimo labai sunku iškirpti gabalus. Kaip jį paleisti, jei pašalinote gravitaciją imituojantį kodą? Arba piešti personažus?

Todėl mes turime pakeisti ištisus modulius šaknimis, kurie apsimeta, kad daro kažką naudingo, bet iš tikrųjų daro kažką labai paprasto, kuriame negali būti klaidų. Turime parašyti tokius ramentus, kad žaidimas bent jau veiktų. Tai lėtas ir skausmingas procesas.

Trumpai tariant, aš tai padariau. Pašalinau vis daugiau kodo dalių, kol man liko pradinis kodas, kuris sukonfigūruoja sistemą, kad paleistų žaidimą, inicijuotų atvaizdavimo aparatūrą ir pan. Žinoma, šiame etape negalėjau sukurti išsaugojimo ir įkėlimo meniu, nes turėčiau sukurti viso grafinio kodo šaknį. Bet galėčiau apsimesti vartotoju, naudodamas (nematomą) išsaugojimo ir įkėlimo ekraną, paprašyti išsaugoti, o tada įrašyti į atminties kortelę.

Tai paliko nedidelę kodo dalį, kuri vis dar turėjo pirmiau nurodytą problemą, bet ji vis tiek nutiko atsitiktinai! Dažniausiai viskas veikė gerai, tačiau kartais pasitaikydavo nesklandumų. Pašalinau beveik visą žaidimo kodą, bet klaida vis dar gyva. Tai buvo mįslinga: likęs kodas iš tikrųjų nieko nedarė.

Kažkuriuo momentu, tikriausiai apie trečią valandą nakties, man šovė mintis. Skaitymo ir rašymo (įvesties/išvesties) operacijos apima tikslų vykdymo laiką. Kai dirbate su standžiuoju disku, atminties kortele arba „Bluetooth“ moduliu, už skaitymą ir rašymą atsakingas žemo lygio kodas tai daro pagal laikrodžio impulsus.

Laikrodžio pagalba įrenginys, kuris nėra tiesiogiai prijungtas prie procesoriaus, yra sinchronizuojamas su procesoriaus vykdomu kodu. Laikrodis nustato duomenų perdavimo spartą – duomenų perdavimo greitį. Jei kyla painiavos dėl laiko, taip pat painiojama arba aparatinė, arba programinė įranga, arba abi. Ir tai labai blogai, nes duomenys gali būti sugadinti.

Ką daryti, jei kažkas mūsų kode supainioja laiką? Viską, kas su tuo susiję, patikrinau testo programos kode ir pastebėjau, kad PS1 programuojamąjį laikmatį nustatėme iki 1 kHz (1000 žymėjimų per sekundę). Tai gana daug; pagal numatytuosius nustatymus, kai konsolė paleidžiama, ji veikia 100 Hz. Ir dauguma žaidimų naudoja šį dažnį.

Žaidimo kūrėjas Andy nustatė 1 kHz laikmatį, kad judesiai būtų skaičiuojami tiksliau. Andy linkęs persistengti, o jei mėgdžiojamės gravitacija, tai darome kuo tiksliau!

Bet ką daryti, jei laikmačio pagreitis kažkaip paveikė bendrą programos laiką, taigi ir laikrodį, kuris reguliuoja atminties kortelės perdavimo spartą?

Aš pakomentavau laikmačio kodą. Klaida nepasikartojo. Bet tai nereiškia, kad tai ištaisėme, nes gedimas įvyko atsitiktinai. O jei man tiesiog pasisekė?

Po kelių dienų vėl eksperimentavau su bandymo programa. Klaida nepasikartojo. Grįžau į visą žaidimo kodų bazę ir pakeičiau išsaugojimo ir įkėlimo kodą taip, kad programuojamas laikmatis būtų iš naujo nustatytas į pradinę reikšmę (100 Hz), prieš pasiekiant atminties kortelę, o tada iš naujo nustatys 1 kHz. Daugiau avarijų nebuvo.

Bet kodėl taip atsitiko?

Vėl grįžau į bandomąją programą. Bandžiau rasti tam tikrą klaidos atsiradimo modelį su 1 kHz laikmačiu. Galiausiai pastebėjau, kad klaida įvyksta, kai kas nors žaidžia su PS1 valdikliu. Kadangi pats tai daryčiau retai – kam man reikia valdiklio, kai bandau išsaugoti ir įkelti kodą? - Net nepastebėjau šios priklausomybės. Tačiau vieną dieną vienas mūsų menininkas laukė, kol baigsiu testuoti – tikriausiai tuo metu keikiausi – ir nervingai suko valdiklį rankose. Įvyko klaida. "Palauk, ką?!" Na, daryk tai dar kartą!

Kai supratau, kad šie du įvykiai yra tarpusavyje susiję, galėjau nesunkiai atkurti klaidą: pradėjau įrašyti į atminties kortelę, perkėliau valdiklį ir sugadinau atminties kortelę. Man tai atrodė kaip aparatinės įrangos klaida.

Atėjau pas Connie ir papasakojau jai apie savo atradimą. Ji perdavė informaciją vienam iš inžinierių, sukūrusių PS1. „Neįmanoma, – atsakė jis, – tai negali būti aparatinės įrangos problema. Paprašiau Connie suorganizuoti pokalbį su mumis.

Man paskambino inžinierius ir mes susiginčijome jo laužyta anglų kalba ir mano (labai) laužyta japonų kalba. Galiausiai pasakiau: „Leiskite man tiesiog išsiųsti savo 30 eilučių bandymo programą, kur valdiklio perkėlimas sukelia klaidą“. Jis sutiko. Sakė, kad tai buvo laiko švaistymas ir kad jis siaubingai užsiėmęs nauju projektu, bet pasiduos, nes esame labai svarbūs Sony kūrėjai. Išvaliau savo bandomąją programą ir nusiunčiau ją jam.

Kitą vakarą (mes buvome Los Andžele, o jis Tokijuje) jis man paskambino ir aviai atsiprašė. Tai buvo aparatinės įrangos problema.

Nežinau, kokia tiksliai buvo klaida, bet iš to, ką girdėjau „Sony“ būstinėje, jei nustatėte laikmatį į pakankamai didelę reikšmę, jis trukdė pagrindinės plokštės komponentams, esantiems netoli laikmačio kristalo. Vienas iš jų buvo atminties kortelės duomenų perdavimo spartos valdiklis, kuris taip pat nustatė valdiklių perdavimo spartą. Nesu inžinierius, todėl gal ką nors sujaučiau.

Tačiau esmė ta, kad tarp pagrindinės plokštės komponentų buvo trukdžių. O perduodant duomenis vienu metu per valdiklio prievadą ir atminties kortelės prievadą su 1 kHz dažniu veikiančiu laikmačiu, buvo prarasti bitai, prarasti duomenys, sugadinta kortelė.

Blogos karvės

Devintajame dešimtmetyje mano mentorius Sergejus parašė programinę įrangą SM-1980, sovietiniam PDP-1800 klonui. Šis mikrokompiuteris ką tik buvo sumontuotas geležinkelio stotyje netoli Sverdlovsko – svarbaus transporto mazgo SSRS. Naujoji sistema buvo skirta vagonams ir krovinių eismui nukreipti. Tačiau jame buvo erzinanti klaida, dėl kurios įvyko atsitiktinės avarijos ir gedimai. Kritimai visada įvykdavo, kai kas nors grįždavo namo vakare. Tačiau nepaisant kruopštaus tyrimo kitą dieną, kompiuteris veikė tinkamai atliekant visus rankinius ir automatinius testus. Paprastai tai rodo lenktynių būklę arba kitą konkurencinę klaidą, kuri atsiranda tam tikromis sąlygomis. Pavargęs nuo skambučių vėlų vakarą Sergejus nusprendė įsigilinti į esmę ir visų pirma suprasti, kokios sąlygos skirstymo aikštelėje lėmė kompiuterio gedimą.

Pirmiausia jis surinko visų nepaaiškintų kritimų statistiką ir sukūrė grafiką pagal datą ir laiką. Modelis buvo akivaizdus. Dar keletą dienų stebėjęs, Sergejus suprato, kad gali nesunkiai nuspėti būsimų sistemos gedimų laiką.

Netrukus jis sužinojo, kad trikdžiai įvyko tik tada, kai stotis rūšiavo traukinius galvijų iš Šiaurės Ukrainos ir Vakarų Rusijos, vežančių į netoliese esančią skerdyklą. Tai savaime buvo keista, nes skerdyklą aprūpino daug arčiau, Kazachstane, esančios fermos.

Černobylio atominė elektrinė sprogo 1986 m., o radioaktyvūs krituliai aplinkines teritorijas pavertė negyvenamomis. Buvo užterštos didžiulės teritorijos Šiaurės Ukrainoje, Baltarusijoje ir Vakarų Rusijoje. Įtaręs didelį radiacijos lygį atvykstančiose vagonuose, Sergejus sukūrė metodą, kaip patikrinti šią teoriją. Gyventojams buvo uždrausta turėti dozimetrus, todėl Sergejus geležinkelio stotyje užsiregistravo pas kelis kariškius. Kelis kartus išgėręs degtinės, jam pavyko įtikinti kareivį išmatuoti radiacijos lygį viename iš įtartinų vežimų. Paaiškėjo, kad lygis kelis kartus viršijo normalias vertes.

Galvijai ne tik skleidė daug radiacijos, jos lygis buvo toks aukštas, kad atsitiktinai dingo bitai SM-1800, kuris buvo šalia stoties esančiame pastate, atmintyje.

SSRS ėmė trūkti maisto, o valdžia nusprendė maišyti Černobylio mėsą su mėsa iš kitų šalies regionų. Tai leido sumažinti bendrą radioaktyvumo lygį neprarandant vertingų išteklių. Sužinojęs apie tai, Sergejus nedelsdamas užpildė dokumentus dėl emigracijos. O kompiuterių gedimai sustojo savaime, kai laikui bėgant sumažėjo radiacijos lygis.

Per vamzdžius

Kažkada „Movietech Solutions“ sukūrė programinę įrangą kino teatrams, skirtą apskaitai, bilietų pardavimui ir bendram valdymui. Pavyzdinės programos DOS versija buvo gana populiari tarp mažų ir vidutinio dydžio kino teatrų tinklų Šiaurės Amerikoje. Tad nenuostabu, kad kai buvo paskelbta Windows 95 versija, integruota su naujausiais jutikliniais ekranais ir savitarnos kioskais bei aprūpinta įvairiausiais ataskaitų teikimo įrankiais, greitai išpopuliarėjo ir ji. Dažniausiai atnaujinimas vyko be problemų. Vietiniai IT darbuotojai įdiegė naują įrangą, perkėlė duomenis, o verslas tęsėsi. Išskyrus atvejus, kai tai netruko. Kai tai atsitiktų, bendrovė išsiųsdavo Jamesą, pravarde „Valytojas“.

Nors slapyvardis rodo niekšišką tipą, valytojas yra tik instruktoriaus, montuotojo ir universalaus meistro derinys. Jamesas praleisdavo kelias dienas kliento svetainėje, sujungdamas visus komponentus, o po to dar porą dienų mokydamas darbuotojus naudotis nauja sistema, spręsdamas visas iškilusias aparatinės įrangos problemas ir iš esmės padėdamas programinei įrangai jos atsiradimo pradžioje.

Todėl nenuostabu, kad šiais įtemptais laikais Jamesas į biurą atvyko ryte, o dar nespėjus pasiekti darbo stalo jį pasitiko vadybininkas, nepripildytas kofeino nei įprastai.

„Bijau, kad tau reikia kuo greičiau vykti į Anapolį, Nova Scotia“. Sugedo visa jų sistema ir po nakties darbo su jų inžinieriais negalime suprasti, kas atsitiko. Atrodo, kad serverio tinklas nepavyko. Bet tik po to, kai sistema veikė keletą minučių.

– Ar jie negrįžo prie senosios sistemos? - visiškai rimtai atsakė Jamesas, nors mintyse iš nuostabos išplėtė akis.

— Būtent: jų IT specialistas „pakeitė prioritetus“ ir nusprendė palikti seną serverį. James, jie įdiegė sistemą šešiose vietose ir ką tik sumokėjo už aukščiausios kokybės palaikymą, o jų verslas dabar vykdomas taip, kaip buvo šeštajame dešimtmetyje.

Džeimsas šiek tiek atsitiesė.

- Tai kitas reikalas. Gerai, pradėkime.

Kai jis atvyko į Anapolį, pirmiausia jis rado kliento pirmąjį teatrą, kuriame kilo problemų. Oro uoste paimtame žemėlapyje viskas atrodė neblogai, tačiau teritorija aplink norimą adresą atrodė įtartinai. Ne geto, o primena film noir. Kai Jamesas pastatė automobilį prie miesto centro kelkraščio, prie jo priėjo prostitutė. Atsižvelgiant į Anapolio dydį, greičiausiai jis buvo vienintelis visame mieste. Jos išvaizda iškart priminė garsųjį personažą, didžiajame ekrane siūliusį seksą už pinigus. Ne, ne apie Julia Roberts, o apie Joną Voightą [aliuzija į filmą „Vidurnakčio kaubojus“ – apytiksl. juosta].

Pasiuntęs prostitutę į kelią, Jamesas nuėjo į kiną. Apylinkės buvo pagerėjusios, bet vis tiek darė įspūdį, kad apleistas. Ne tai, kad Jamesas buvo per daug susirūpinęs. Jis anksčiau buvo apgailėtinose vietose. Ir tai buvo Kanada, kur net plėšikai yra pakankamai mandagūs ir sako „ačiū“, paėmę piniginę.

Šoninis įėjimas į kino teatrą buvo apniukusioje alėjoje. Džeimsas priėjo prie durų ir pasibeldė. Netrukus jis girgždėjo ir šiek tiek atsidarė.

-Tu valytoja? - iš vidaus pasigirdo užkimęs balsas.

- Taip, tai aš... Atėjau visko sutvarkyti.

Džeimsas įėjo į kino teatro vestibiulį. Matyt, neturėdami kitos išeities, darbuotojai pradėjo dalyti lankytojams popierinius bilietus. Tai apsunkino finansines ataskaitas, jau nekalbant apie įdomesnes detales. Tačiau darbuotojai su palengvėjimu sutiko Jamesą ir iškart nuvedė į serverio kambarį.

Iš pirmo žvilgsnio viskas buvo gerai. James prisijungė prie serverio ir patikrino įprastas įtartinas vietas. Jokiu problemu. Tačiau dėl didelio atsargumo Jamesas išjungė serverį, pakeitė tinklo plokštę ir atšaukė sistemą. Ji iškart pradėjo dirbti pilnai. Darbuotojai vėl pradėjo pardavinėti bilietus.

Jamesas paskambino Markui ir pranešė jam apie situaciją. Nesunku įsivaizduoti, kad Jamesas gali norėti likti šalia ir pažiūrėti, ar neatsitiks kas nors netikėto. Jis nusileido laiptais ir pradėjo klausinėti darbuotojų, kas atsitiko. Akivaizdu, kad sistema nustojo veikti. Jie jį išjungė ir įjungė, viskas veikė. Tačiau po 10 minučių sistema nukrito.

Kaip tik šią akimirką atsitiko kažkas panašaus. Staiga bilietų pardavimo sistema pradėjo mėtyti klaidas. Darbuotojai atsiduso ir čiupo popierinius bilietus, o Džeimsas nuskubėjo į serverio kambarį. Su serveriu viskas atrodė gerai.

Tada įėjo vienas iš darbuotojų.

– Sistema vėl veikia.

Jamesas buvo suglumęs, nes nieko nepadarė. Tiksliau, nieko, kas priverstų sistemą veikti. Jis atsijungė, paėmė telefoną ir paskambino į savo įmonės pagalbos liniją. Netrukus ta pati darbuotoja įėjo į serverio kambarį.

– Sistema neveikia.

Džeimsas žvilgtelėjo į serverį. Ekrane šoko įdomus ir pažįstamas įvairiaspalvių formų raštas – chaotiškai besiraitančios ir susipynusios dūdelės. Mes visi kažkada matėme šią ekrano užsklandą. Jis buvo gražiai perteiktas ir tiesiogine prasme hipnotizuojantis.


Džeimsas paspaudė mygtuką ir raštas dingo. Jis nuskubėjo į bilietų kasą ir pakeliui sutiko pas jį grįžtantį darbuotoją.

– Sistema vėl veikia.

Jei galite atlikti mentalinį veido delną, Jamesas padarė būtent tai. Ekrano užsklanda. Jis naudoja OpenGL. Ir todėl veikimo metu jis sunaudoja visus serverio procesoriaus išteklius. Dėl to kiekvienas skambutis į serverį baigiasi skirtuoju laiku.

Džeimsas grįžo į serverio kambarį, prisijungė ir pakeitė ekrano užsklandą gražiais vamzdeliais su tuščiu ekranu. Tai yra, vietoj ekrano užsklandos, kuri sunaudoja 100% procesoriaus resursų, įdiegiau kitą, kuri nevartoja resursų. Tada laukiau 10 minučių, kad patikrinčiau savo spėjimą.

Atvykęs į kitą kino teatrą Jamesas galvojo, kaip paaiškinti savo vadovui, kad ką tik nuskriejo 800 km, kad išjungtų ekrano užsklandą.

Avarija tam tikros mėnulio fazės metu

Tikra istorija. Vieną dieną atsirado programinės įrangos klaida, kuri priklausė nuo mėnulio fazės. Apskaičiuojant tikrosios Mėnulio fazės aproksimaciją, įvairiose MIT programose paprastai buvo naudojama nedidelė rutina. GLS sukūrė šią tvarką į LISP programą, kuri rašant failą išvestų eilutę su beveik 80 simbolių laiko žyma. Labai retai pirmoji pranešimo eilutė buvo per ilga ir nukreipta į kitą eilutę. Ir kai programa vėliau perskaitė šį failą, ji keikėsi. Pirmosios eilutės ilgis priklausė nuo tikslios datos ir laiko, taip pat nuo fazės specifikacijos ilgio tuo metu, kai buvo spausdinama laiko žyma. Tai yra, klaida tiesiogine prasme priklausė nuo mėnulio fazės!

Pirmasis popierinis leidimas Žargono failas (Steele-1983) buvo tokios eilutės, kuri atvedė į aprašytą klaidą, pavyzdį, tačiau rinkėjas ją „ištaisė“. Nuo to laiko tai buvo apibūdinta kaip „mėnulio fazės klaida“.

Tačiau būkite atsargūs su prielaidomis. Prieš kelerius metus CERN (Europos branduolinių tyrimų centro) inžinieriai susidūrė su klaidomis eksperimentuose, atliktuose dideliame elektronų-pozitronų greitintuve. Kadangi kompiuteriai aktyviai apdoroja didžiulį šio įrenginio sugeneruotų duomenų kiekį prieš parodydami rezultatą mokslininkams, daugelis spėliojo, kad programinė įranga kažkaip jautri mėnulio fazei. Keli beviltiški inžinieriai suprato tiesos esmę. Klaida atsirado dėl nežymaus 27 km ilgio žiedo geometrijos pasikeitimo dėl Žemės deformacijos per Mėnulį! Ši istorija į fizikos folklorą pateko kaip „Niutono kerštas dalelių fizikai“ ir paprasčiausių bei seniausių fizikos dėsnių ir pažangiausių mokslo koncepcijų ryšio pavyzdys.

Nuleidus tualetą traukinys sustabdomas

Geriausia aparatinės įrangos klaida, apie kurią aš kada nors girdėjau, buvo greitajame traukinyje Prancūzijoje. Dėl klaidos traukinys buvo staigiai stabdomas, tačiau tik tuo atveju, jei jame buvo keleivių. Kiekvienu tokiu atveju traukinys buvo išimtas iš eksploatacijos, tikrinamas, bet nieko nerasta. Tada jis buvo išsiųstas atgal į liniją ir jis iškart sustojo.

Vieno patikrinimo metu traukiniu važiavęs inžinierius nuėjo į tualetą. Jis greitai nusiplovė, BOOM! Avarinis sustojimas.

Inžinierius susisiekė su vairuotoju ir paklausė:

– Ką veikei prieš pat stabdymą?

- Na, o nusileidime sulėtėjau...

Tai buvo keista, nes normaliai eksploatuojant traukinys nusileidęs dešimtis kartų sulėtėja. Traukinys pajudėjo toliau, o kitame nusileidime mašinistas perspėjo:

- Aš sulėtinsiu greitį.

Nieko neatsitiko.

– Ką veikėte per paskutinį stabdymą? – paklausė vairuotojas.

- Na... buvau tualete...

- Na, tada eik į tualetą ir daryk tai, ką padarei, kai vėl nusileisime!

Inžinierius nuėjo į tualetą, o kai vairuotojas perspėjo: „Aš lėtinu“, nuleido vandenį. Žinoma, traukinys iškart sustojo.

Dabar jie galėjo atkurti problemą ir reikėjo rasti priežastį.

Po dviejų minučių jie pastebėjo, kad nuo elektros spintos sienelės atjungtas variklio stabdžių nuotolinio valdymo laidas (traukinio gale buvo po vieną variklį) ir guli ant relės, kuri valdė unitazo kištuko solenoidą... Kai relė buvo įjungtas, tai sukėlė trikdžius stabdžių troselyje, o sistemos apsauga nuo gedimų tiesiog apėmė avarinį stabdymą.

Vartai, kurie nekentė FORTRANO

Prieš kelis mėnesius pastebėjome, kad tinklo jungtys žemyninėje dalyje [tai buvo Havajuose] darosi labai, labai lėtos. Tai gali trukti 10–15 minučių ir staiga vėl pasikartoti. Po kurio laiko kolega man pasiskundė, kad tinklo jungtys žemyninėje dalyje apskritai neveikia. Jis turėjo tam tikrą FORTRAN kodą, kurį reikėjo nukopijuoti į žemyninėje dalyje esantį įrenginį, bet nepavyko, nes „tinklas neužsilaikė pakankamai ilgai, kad FTP įkėlimas būtų baigtas“.

Taip, paaiškėjo, kad tinklo gedimai įvyko, kai kolega bandė perkelti failą su šaltinio kodu FORTRAN į kompiuterį žemyne. Mes bandėme archyvuoti failą: tada jis buvo sklandžiai nukopijuotas (tačiau tikslinė mašina neturėjo išpakavimo, todėl problema nebuvo išspręsta). Galiausiai FORTRAN kodą „suskirstėme“ į labai mažus gabalėlius ir išsiuntėme juos po vieną. Dauguma fragmentų buvo nukopijuoti be problemų, tačiau keli fragmentai nepraėjo arba praėjo po to daugybė bandymus.

Kai išnagrinėjome problemines ištraukas, išsiaiškinome, kad jos turi kažką bendro: juose buvo komentarų blokai, kurie prasidėjo ir baigiasi eilutėmis, sudarytomis iš didžiosios C (kaip kolega mieliau komentavo FORTRAN). Išsiuntėme el. laišką tinklo ekspertams žemyne ​​ir paprašėme pagalbos. Žinoma, jie norėjo pamatyti mūsų failų pavyzdžius, kurių nepavyko perkelti per FTP... bet mūsų laiškai jų nepasiekė. Galiausiai sugalvojome paprastą apibūdintikaip atrodo neperkeliami failai. Pavyko :) [Ar galiu čia pridėti vieno iš probleminių FORTRAN komentarų pavyzdį? Tikriausiai neverta!]

Galų gale mums pavyko tai išsiaiškinti. Neseniai tarp mūsų miestelio dalies ir žemyninio tinklo buvo įrengti nauji vartai. Ji turėjo DIDŽIŲ sunkumų perduodant paketus, kuriuose buvo pasikartojantys didžiųjų C raidžių bitai! Tik keli iš šių paketų gali užimti visus šliuzo išteklius ir neleisti patekti į daugelį kitų paketų. Mes pasiskundėme vartų gamintojui... ir jie atsakė: „O, taip, jūs susidūrėte su pasikartojančia C klaida! Mes jau žinome apie jį“. Galiausiai problemą išsprendėme įsigiję naujus vartus iš kito gamintojo (buvusio ginant, negalėjimas perkelti FORTRAN programų kai kuriems gali būti privalumas!).

Sunkūs laikai

Prieš kelerius metus, kurdamas ETL sistemą Perl, kad sumažinčiau 40 fazės klinikinių tyrimų išlaidas, man reikėjo apdoroti apie 000 1 datų. Du iš jų egzamino neišlaikė. Tai manęs per daug nejaudino, nes šios datos buvo paimtos iš klientų pateiktų duomenų, kurie dažnai, sakykime, nustebino. Bet kai patikrinau pirminius duomenis, paaiškėjo, kad šios datos buvo 2011 m. sausio 1 d. ir 2007 m. sausio 30 d. Maniau, kad klaida yra programoje, kurią ką tik parašiau, bet paaiškėjo, kad tai jau XNUMX metų. senas. Tai gali pasirodyti paslaptinga tiems, kurie nėra susipažinę su programinės įrangos ekosistema. Dėl kitos įmonės ilgalaikio sprendimo užsidirbti pinigų, mano klientas sumokėjo man, kad ištaisyčiau klaidą, kurią viena įmonė įvedė atsitiktinai, o kita tyčia. Kad suprastumėte, apie ką kalbu, turiu pakalbėti apie įmonę, kuri pridėjo funkciją, kuri galiausiai tapo klaida, taip pat keletą kitų įdomių įvykių, prisidėjusių prie paslaptingos klaidos, kurią ištaisiau.

Senais gerais laikais „Apple“ kompiuteriai kartais spontaniškai iš naujo nustatydavo savo datą į 1 m. sausio 1904 d. Priežastis buvo paprasta: ji naudojo bateriją maitinamą „sistemos laikrodį“, kad galėtų sekti datą ir laiką. Kas atsitiko, kai mirė baterija? Kompiuteriai pradėjo sekti datą sekundžių skaičiumi nuo epochos pradžios. Epocha turėjome omenyje pradinę atskaitos datą, o „Macintoshes“ tai buvo 1 m. sausio 1904 d. O pasibaigus akumuliatoriui, dabartinė data buvo nustatyta į nurodytą. Bet kodėl taip atsitiko?

Anksčiau „Apple“ naudojo 32 bitus, kad išsaugotų sekundžių skaičių nuo pradinės datos. Vienas bitas gali saugoti vieną iš dviejų reikšmių – 1 arba 0. Du bitai gali saugoti vieną iš keturių reikšmių: 00, 01, 10, 11. Trys bitai – viena reikšmė iš aštuonių: 000, 001, 010, 011, 100 , 101, 110, 111 ir kt. Ir 32 galėtų saugoti vieną iš 232 reikšmių, tai yra 4 294 967 296 sekundes. Kalbant apie „Apple“ datas, tai buvo maždaug 136 metai, todėl senesni „Mac“ kompiuteriai negali apdoroti datų po 2040 m. O jei sistemos akumuliatorius miršta, data iš naujo nustatoma į 0 sekundžių nuo epochos pradžios ir kiekvieną kartą įjungus kompiuterį (arba kol perkate naują bateriją) turite nustatyti datą rankiniu būdu.

Tačiau Apple sprendimas saugoti datas kaip sekundes nuo epochos reiškė, kad negalėjome tvarkyti datų prieš epochą, o tai turėjo toli siekiančių pasekmių, kaip pamatysime. „Apple“ pristatė funkciją, o ne klaidą. Be kita ko, tai reiškė, kad „Macintosh“ operacinė sistema buvo apsaugota nuo „tūkstantmečio klaidos“ (to negalima pasakyti apie daugelį „Mac“ programų, turinčių savo datos sistemas, skirtas apeiti apribojimus).

Pirmyn. Naudojome „Lotus 1-2-3“, IBM „žudikų programą“, kuri padėjo pradėti kompiuterių revoliuciją, nors „Apple“ kompiuteriuose buvo „VisiCalc“, todėl asmeninis kompiuteris buvo sėkmingas. Tiesą sakant, jei nebūtų atsiradę 1-2-3, kompiuteriai vargu ar būtų pakilę, o asmeninių kompiuterių istorija galėjo vystytis labai skirtingai. „Lotus 1-2-3“ 1900-uosius neteisingai traktavo kaip keliamuosius metus. Kai „Microsoft“ išleido savo pirmąją skaičiuoklę „Multiplan“, ji užėmė nedidelę rinkos dalį. Ir kai jie pradėjo Excel projektą, jie nusprendė ne tik nukopijuoti eilučių ir stulpelių pavadinimų schemą iš Lotus 1-2-3, bet ir užtikrinti suderinamumą su klaidomis sąmoningai laikant 1900 keliamuosius metus. Ši problema egzistuoja ir šiandien. Taigi 1-2-3 tai buvo klaida, bet Excel tai buvo sąmoningas sprendimas užtikrinti, kad visi 1-2-3 vartotojai galėtų importuoti lenteles į Excel nekeisdami duomenų, net jei jie neteisingi.

Bet buvo kita problema. Pirmiausia „Microsoft“ išleido „Excel“, skirtą „Macintosh“, kuri neatpažino datų iki 1 m. sausio 1904 d. O „Excel“ 1 m. sausio 1900 d. buvo laikoma eros pradžia. Todėl kūrėjai padarė pakeitimą, kad jų programa atpažintų eros tipą ir saugotų duomenis savyje pagal norimą erą. „Microsoft“ net parašė apie tai aiškinamąjį straipsnį. Ir šis sprendimas paskatino mano klaidą.

Mano ETL sistema gavo „Excel“ skaičiuokles iš klientų, kurios buvo sukurtos „Windows“, bet gali būti sukurtos ir „Mac“. Todėl epochos pradžia lentelėje galėtų būti arba 1 m. sausio 1900 d., arba 1 m. sausio 1904 d. Kaip sužinoti? „Excel“ failo formatas rodo reikiamą informaciją, tačiau mano naudojamas analizatorius jos neparodė (dabar rodo), ir manė, kad žinote konkrečios lentelės epochą. Tikriausiai galėjau praleisti daugiau laiko, kad suprastų „Excel“ dvejetainį formatą ir išsiųsčiau pataisą analizatoriaus autoriui, bet turėjau daug daugiau nuveikti dėl kliento, todėl greitai parašiau euristiką, kad nustatytų epochą. Ji buvo paprasta.

Programoje „Excel“ 5 m. liepos 1998 d. data gali būti pateikta formatu „07-05-98“ (nenaudinga amerikietiška sistema), „liepos 5 d. 98“, „5 m. liepos 1998 d.“, „5-liepos-98“ arba kitas formatas, kitas nenaudingas formatas (ironiška, bet vienas iš formatų, kurių nepasiūlė mano Excel versija, buvo ISO 8601). Tačiau lentelėje neformatuota data buvo išsaugota kaip „35981“ epochai-1900 arba „34519“ epochai-1904 (skaičiai rodo dienų skaičių nuo epochos). Aš paprasčiausiai naudojau paprastą analizatorių, kad ištraukčiau metus iš suformatuotos datos, o tada naudoju Excel analizatorių, kad ištraukčiau metus iš neformatuotos datos. Jei abi vertės skyrėsi 4 metais, tada žinojau, kad naudoju sistemą su epocha-1904.

Kodėl aš tiesiog nenaudojau suformatuotų datų? Kadangi 5 m. liepos 1998 d. galima suformatuoti kaip „liepos 98 d.“, praradus mėnesio dieną. Gavome lenteles iš tiek daug įmonių, kurios jas kūrė tiek įvairiais būdais, kad mums (šiuo atveju – man) teko išsiaiškinti datas. Be to, jei „Excel“ viskas bus gerai, tai turėtume ir mes!

Tuo pačiu metu susidūriau su 39082. Leiskite jums priminti, kad Lotus 1-2-3 1900 laikė keliamaisiais metais, ir tai buvo ištikimai pakartota programoje Excel. Ir kadangi tai pridėjo vieną dieną prie 1900 m., daugelis datos skaičiavimo funkcijų gali būti netinkamos tai pačiai dienai. Tai reiškia, kad 39082 galėjo būti 1 m. sausio 2011 d. („Mac“ kompiuteriuose) arba 31 m. gruodžio 2006 d. („Windows“). Jei mano „metų analizatorius“ iš suformatuotos reikšmės ištraukė 2011 metus, tada viskas gerai. Tačiau kadangi „Excel“ analizatorius nežino, kokia epocha naudojama, ji pagal numatytuosius nustatymus yra epocha-1900, grąžindama 2006 m. Mano paraiška pamatė, kad skirtumas buvo 5 metai, įvertino tai klaida, užregistravo ir grąžino neformatuotą reikšmę.

Norėdami tai apeiti, parašiau šį (pseudokodas):

diff = formatted_year - parsed_year
if 0 == diff
    assume 1900 date system
if 4 == diff
    assume 1904 date system
if 5 == diff and month is December and day is 31
    assume 1904 date system

Ir tada visos 40 000 datų buvo teisingai išanalintos.

Viduryje didelių spausdinimo darbų

Devintojo dešimtmečio pradžioje mano tėvas dirbo „Storage Technology“ – jau nebeegzistuojančiame padalinyje, kuris kūrė juostinius įrenginius ir pneumatines sistemas greitam juostos padavimui.

Jie perkūrė diskus, kad vienas centrinis „A“ diskas būtų prijungtas prie septynių „B“ diskų, o maža OS, valdanti „A“ diską, galėtų perduoti skaitymo ir rašymo operacijas visiems „B“ diskams.

Kiekvieną kartą paleidus diską „A“, į periferinį įrenginį, prijungtą prie „A“, reikėjo įdėti diskelį, kad būtų galima įkelti operacinę sistemą į jo atmintį. Jis buvo itin primityvus: skaičiavimo galią teikė 8 bitų mikrovaldiklis.

Tokios įrangos tikslinė auditorija buvo įmonės, turinčios labai didelius duomenų saugyklas – bankai, prekybos tinklai ir pan., kurioms reikėjo spausdinti daug adresų etikečių ar banko išrašų.

Vienas klientas turėjo problemų. Spausdinimo užduoties viduryje vienas konkretus diskas „A“ gali nustoti veikti, todėl visa užduotis gali sustoti. Norėdami atkurti disko veikimą, darbuotojai turėjo viską perkrauti. Ir jei tai atsitiko vidury šešių valandų užduoties, buvo prarastas didžiulis brangus kompiuterio laikas ir buvo sutrikdytas visos operacijos grafikas.

Technikai buvo išsiųsti iš Storage Technologies. Tačiau nepaisant visų pastangų, jie negalėjo atkurti klaidos bandymo sąlygomis: atrodė, kad ji įvyko atliekant didelius spausdinimo darbus. Problema buvo ne aparatinėje įrangoje, jie pakeitė viską, ką galėjo: RAM, mikrovaldiklį, diskelį, kiekvieną įmanomą juostos įrenginio dalį – problema išliko.

Tada technikai paskambino į būstinę ir iškvietė Ekspertą.

Ekspertas čiupo kėdę ir kavos puodelį, sėdėjo kompiuterių kabinete – tais laikais ten buvo kompiuteriams skirtos patalpos – ir stebėjo, kaip darbuotojai rikiuojasi į eilę didelio spausdinimo darbų. Ekspertas laukė, kol įvyks gedimas – taip ir įvyko. Visi žiūrėjo į Ekspertą, bet jis neįsivaizdavo, kodėl taip atsitiko. Taigi jis liepė vėl eiti į darbą, o visi darbuotojai ir technikai grįžo į darbą.

Ekspertas vėl atsisėdo į kėdę ir ėmė laukti nesėkmės. Praėjo maždaug šešios valandos ir įvyko gedimas. Ekspertas vėl neturėjo minčių, išskyrus tai, kad viskas vyko kambaryje, pripildytame žmonių. Jis įsakė vėl pradėti misiją, atsisėdo ir laukė.

Po trečios nesėkmės Ekspertas kažką pastebėjo. Gedimas įvyko, kai darbuotojai pakeitė juostas svetimame diske. Be to, gedimas įvyko vos vienam iš darbuotojų žengus pro tam tikrą plytelę ant grindų.

Paaukštintos grindys buvo pagamintos iš aliuminio plytelių, išklotų 6–8 colių aukštyje. Daugybė kompiuterių laidų driekėsi po paaukštintomis grindimis, kad kas nors netyčia neužliptų ant svarbaus laido. Plyteles klojo labai sandariai, kad po paaukštintomis grindimis nepatektų šiukšlių.

Ekspertas suprato, kad viena iš plytelių deformuota. Darbuotojui užlipus ant jo kampo, plytelės kraštai nutrynė į gretimas plyteles. Jomis trynė ir plyteles jungusios plastikinės detalės, kurios sukėlė statines mikroiškrovas, kurios kūrė radijo dažnius.

Šiandien RAM yra daug geriau apsaugota nuo radijo dažnių trukdžių. Tačiau tais metais taip nebuvo. Ekspertas suprato, kad šie trukdžiai sutrikdė atmintį, o kartu ir operacinės sistemos darbą. Jis paskambino į pagalbos tarnybą, užsisakė naujas plyteles, pats jas sumontavo ir problema išnyko.

Tai potvynis!

Istorija vyko serverių patalpoje, ketvirtame ar penktame biuro aukšte Portsmute (manau), dokų zonoje.

Vieną dieną Unix serveris su pagrindine duomenų baze sudužo. Jie jį paleido iš naujo, bet jis ir toliau laimingas krito vėl ir vėl. Nusprendėme paskambinti kam nors iš palaikymo tarnybos.

Palaikymo vaikinas... Manau, kad jo vardas buvo Markas, bet tai nesvarbu... Nemanau, kad aš jo pažįstu. Nesvarbu, tikrai. Pasilikime su Marku, gerai? Puiku.

Taigi, po kelių valandų atvyko Markas (žinote, nuo Lidso iki Portsmuto nėra ilgas kelias), įjungė serverį ir viskas veikė be problemų. Tipiškas prakeiktas palaikymas, klientas dėl to labai susierzina. Markas peržiūri žurnalo failus ir neranda nieko nemalonaus. Taigi Markas vėl įsėda į traukinį (ar bet kokiu transportu jis atvyko, tai galėjo būti luoša karvė, kiek žinau... vistiek nesvarbu, gerai?) ir pasišvaistęs grįžta į Lidsą. diena.

Tą patį vakarą serveris vėl sugenda. Istorija ta pati... serveris nekyla. Markas bando padėti nuotoliniu būdu, bet klientas negali paleisti serverio.

Dar traukinys, autobusas, citrininis meringue ar dar koks mėšlas, ir Markas grįžta į Portsmutą. Žiūrėkite, serveris įsijungia be jokių problemų! Stebuklas. Markas kelias valandas tikrina, ar viskas tvarkoje su operacine sistema ar programine įranga, ir išvyksta į Lidsą.

Maždaug dienos viduryje serveris sugenda (nerimkite!). Šį kartą atrodo protinga pakviesti aparatūros palaikymo žmones, kurie pakeistų serverį. Bet ne, po kokių 10 valandų irgi krenta.

Situacija kartojosi keletą dienų. Serveris veikia, užstringa maždaug po 10 valandų ir neįsijungia kitas 2 valandas. Patikrino aušinimą, atminties nutekėjimą, viską patikrino, bet nieko nerado. Tada avarijos sustojo.

Savaitė prabėgo nerūpestingai... visi buvo laimingi. Laimingas, kol viskas prasidės iš naujo. Paveikslas toks pat. 10 valandų darbo, 2-3 valandos prastovos...

Ir tada kažkas (manau, jie man pasakė, kad šis asmuo neturi nieko bendra su IT) pasakė:

— Tai potvynis!

Šūksnis buvo sutiktas tuščiais žvilgsniais, o kažkieno ranka tikriausiai dvejojo ​​paspaudus apsaugos iškvietimo mygtuką.

„Jis nustoja veikti su potvyniu“.

Tai atrodytų visiškai svetima sąvoka IT pagalbos darbuotojams, kurie vargu ar skaitys „Tide Yearbook“ sėdėdami išgerti kavos. Jie paaiškino, kad tai niekaip negali būti susiję su potvyniu, nes serveris jau savaitę dirbo be gedimų.

„Praėjusią savaitę potvynis buvo žemas, bet šią savaitę jis didelis.

Šiek tiek terminų tiems, kurie neturi jachtos licencijos. Potvyniai priklauso nuo mėnulio ciklo. O kai Žemė sukasi, kas 12,5 valandos Saulės ir Mėnulio gravitacinė trauka sukuria potvynio bangą. 12,5 valandos ciklo pradžioje – atoslūgis, ciklo viduryje – atoslūgis, o pabaigoje – vėl atoslūgis. Tačiau keičiantis mėnulio orbitai, keičiasi ir skirtumas tarp atoslūgių ir atoslūgių. Kai Mėnulis yra tarp Saulės ir Žemės arba priešingoje Žemės pusėje (pilnatis arba be mėnulio), gauname Syzygyn potvynius – didžiausius potvynius ir žemiausius atoslūgius. Pusė mėnulio gauname kvadratinius potvynius – žemiausius potvynius. Skirtumas tarp dviejų kraštutinumų labai sumažėja. Mėnulio ciklas trunka 28 dienas: syzygian - kvadratūra - syzygian - kvadratūra.

Kai technikams buvo paaiškinta potvynio jėgų esmė, jie iškart pagalvojo, kad reikia kviesti policiją. Ir visai logiška. Bet pasirodė, kad vaikinas buvo teisus. Prieš dvi savaites netoli biuro prisišvartavo naikintojas. Kiekvieną kartą, kai potvynis jį pakeldavo iki tam tikro aukščio, laivo radaro postas atsidurdavo serverio patalpos grindų lygyje. O radaras (ar elektroninės kovos įranga, ar koks kitas karinis žaislas) kompiuteriuose sukėlė chaosą.

Raketos skrydžio misija

Man buvo pavesta perkelti didelę (apie 400 tūkst. eilučių) raketų paleidimo valdymo ir stebėjimo sistemą į naujas operacinės sistemos, kompiliatoriaus ir kalbos versijas. Tiksliau, nuo Solaris 2.5.1 iki Solaris 7 ir nuo Verdix Ada Development System (VADS), parašytos Ada 83, iki Rational Apex Ada sistemos, parašytos Ada 95. VADS įsigijo Rational, o jos produktas buvo pasenusi, nors Rational bandė įdiegti suderinamas VADS specifinių paketų versijas, kad palengvintų perėjimą prie Apex kompiliatoriaus.

Trys žmonės man padėjo tiesiog teisingai sukompiliuoti kodą. Tai užtruko dvi savaites. Ir tada aš pats dirbau, kad sistema veiktų. Trumpai tariant, tai buvo pati prasčiausia programinės įrangos architektūra ir įgyvendinimas, su kuriuo teko susidurti, todėl prireikė dar dviejų mėnesių, kad užbaigčiau prievadą. Tada sistema buvo pateikta testavimui, kuris užtruko dar kelis mėnesius. Iškart ištaisiau klaidas, kurios buvo rastos testavimo metu, tačiau jų greitai sumažėjo (pirminio kodo buvo gamybinė sistema, todėl jos funkcionalumas veikė gana patikimai, tereikia pašalinti klaidas, kurios atsirado adaptuojantis naujam kompiliatoriui). Galiausiai, kai viskas veikė kaip priklauso, buvau perkeltas į kitą projektą.

O penktadienį prieš Padėkos dieną suskambo telefonas.

Raketos paleidimas turėjo būti išbandytas maždaug po trijų savaičių, o atliekant laboratorinius atgalinės atskaitos bandymus, komandų seka buvo užblokuota. Realiame gyvenime tai nutrauktų bandymą, o jei užsikimšimas įvyktų per kelias sekundes nuo variklio užvedimo, pagalbinėse sistemose įvyktų keli negrįžtami veiksmai, kuriems prireiktų ilgos – ir brangios – raketos parengties. Tai nebūtų prasidėję, bet daug žmonių būtų labai nusiminę dėl prarasto laiko ir daug, daug pinigų. Neleisk, kad kas nors sakytų, kad Gynybos departamentas pinigus leidžia beatodairiškai – aš niekada nesutikau sutarčių vadovo, kuris neskirtų biudžeto pirmoje ar antroje vietoje, o po to grafiko.

Ankstesniais mėnesiais šis atvirkštinio skaičiavimo iššūkis buvo atliktas šimtus kartų įvairiais variantais, tik su keliais nedideliais žagsėjimais. Taigi tikimybė, kad tai įvyks, buvo labai maža, tačiau jos pasekmės buvo labai reikšmingos. Padauginkite abu šiuos veiksnius ir suprasite, kad naujienos man ir dešimčiai inžinierių bei vadovų pranašavo sugadintą atostogų savaitę.

Ir buvo atkreiptas dėmesys į mane kaip į asmenį, kuris perkėlė sistemą.

Kaip ir daugumoje saugumui svarbių sistemų, buvo užregistruota daug parametrų, todėl buvo gana lengva nustatyti kelias kodo eilutes, kurios buvo įvykdytos prieš sistemos gedimą. Ir, žinoma, juose nebuvo absoliučiai nieko neįprasto; tie patys posakiai buvo sėkmingai atlikti tūkstančius kartų per tą patį bėgimą.

Mes pakvietėme žmones iš Apex į Rational, nes jie sukūrė kompiliatorių, o kai kurios jų sukurtos rutinos buvo vadinamos įtartinu kodu. Jiems (ir visiems kitiems) padarė įspūdį, kad reikia ieškoti nacionalinės svarbos problemos šaknų.

Kadangi žurnaluose nieko įdomaus nebuvo, nusprendėme pabandyti atkurti problemą vietinėje laboratorijoje. Tai nebuvo lengva užduotis, nes įvykis įvyko maždaug kartą per 1000 važiavimų. Viena iš įtariamų priežasčių buvo ta, kad iškvietimas į pardavėjo sukurtą mutex funkciją (VADS perkėlimo paketo dalis) Unlock neprivedė prie atrakinimo. Apdorojimo gija, kuri iškvietė funkciją, apdorojo širdies plakimo pranešimus, kurie nominaliai gaunami kas sekundę. Pakėlėme dažnį iki 10 Hz, tai yra 10 kartų per sekundę, ir pradėjome bėgti. Maždaug po valandos sistema užsirakino. Žurnale matėme, kad įrašytų pranešimų seka buvo tokia pati kaip ir nepavykusio testo metu. Darėme kelis važiavimus, sistema buvo nuolat blokuojama praėjus 45-90 minučių nuo starto ir kiekvieną kartą žurnale buvo tas pats maršrutas. Nors techniškai naudojome skirtingą kodą – pranešimų dažnis buvo skirtingas – sistemos elgsena buvo tokia pati, todėl buvome tikri, kad dėl šio įkėlimo scenarijaus kyla ta pati problema.

Dabar mums reikėjo išsiaiškinti, kur tiksliai blokavimas įvyko išraiškų sekoje.

Šis sistemos diegimas naudojo Ada užduočių sistemą ir naudojo ją neįtikėtinai prastai. Užduotys yra aukšto lygio vienu metu vykdoma Ada konstrukcija, panaši į vykdymo gijas, įtaisyta tik pačioje kalboje. Kai reikia bendrauti dviem užduotimis, jos „nustato susitikimą“, pasikeičia reikiamais duomenimis, o tada sustabdo susitikimą ir grįžta prie savarankiškų vykdymų. Tačiau sistema buvo įgyvendinta kitaip. Pasibaigus tikslinei užduočiai, ta tikslinė užduotis buvo susieta su kita užduotimi, kuri vėliau buvo susieta su trečiąja užduotimi ir taip toliau, kol buvo baigtas apdorojimas. Po to visi šie susitikimai buvo baigti ir kiekviena užduotis turėjo grįžti prie jos vykdymo. Tai reiškia, kad turėjome reikalų su brangiausia funkcijų iškvietimo sistema pasaulyje, kuri sustabdė visą „multitasking“ procesą, kol apdorojo dalį įvesties duomenų. Ir anksčiau tai nesukeldavo problemų tik todėl, kad pralaidumas buvo labai mažas.

Aprašiau šį užduočių mechanizmą, nes kai buvo prašoma arba tikimasi, kad susitikimas bus baigtas, gali įvykti „užduočių perjungimas“. Tai reiškia, kad procesorius gali pradėti apdoroti kitą užduotį, kuri yra paruošta vykdyti. Pasirodo, kai viena užduotis yra pasirengusi susitikti su kita užduotimi, gali būti pradėta vykdyti visiškai kita užduotis ir galiausiai kontrolė grįžta į pirmąjį pasimatymą. Be to, gali įvykti kiti įvykiai, dėl kurių užduotis pasikeičia; vienas iš tokių įvykių yra sistemos funkcijos iškvietimas, pvz., spausdinimas arba nutildymo vykdymas.

Kad suprasčiau, kuri kodo eilutė sukėlė problemą, turėjau rasti būdą, kaip įrašyti eigą per teiginių seką, neaktyvinant užduočių jungiklio, kad būtų išvengta gedimo. Taigi aš negalėjau pasinaudoti Put_Line()kad būtų išvengta I/O operacijų. Galėčiau nustatyti skaitiklio kintamąjį ar kažką panašaus, bet kaip pamatyti jo reikšmę, jei negaliu jo parodyti ekrane?

Taip pat nagrinėjant žurnalą paaiškėjo, kad nepaisant širdies plakimo pranešimų apdorojimo užstrigimo, kuris blokavo visas proceso I/O operacijas ir neleido atlikti kitokio apdorojimo, kitos nepriklausomos užduotys buvo vykdomos toliau. Tai yra, darbas nebuvo visiškai užblokuotas, tik (kritinė) užduočių grandinė.

Tai buvo raktas, reikalingas norint įvertinti blokavimo išraišką.

Sukūriau Ada paketą, kuriame buvo užduotis, išvardintas tipas ir visuotinis to tipo kintamasis. Daugybė pažodinių žodžių buvo susieti su konkrečiomis probleminės sekos išraiškomis (pvz., Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), tada įterpė į jį priskyrimo išraiškas, kurios priskyrė atitinkamą sąrašą visuotiniam kintamajam. Kadangi viso to objekto kodas atmintyje tiesiog saugojo konstantą, užduočių perjungimas dėl jos vykdymo buvo labai mažai tikėtinas. Mums pirmiausia kilo įtarimų dėl posakių, galinčių pakeisti užduotį, nes užblokavimas įvyko vykdant, o ne grįžo perjungiant užduotį atgal (dėl kelių priežasčių).

Stebėjimo užduotis tiesiog buvo vykdoma ciklais ir periodiškai tikrinama, ar nepasikeitė pasaulinio kintamojo reikšmė. Su kiekvienu pakeitimu vertė buvo įrašyta į failą. Tada trumpas laukimas ir naujas patikrinimas. Įrašiau kintamąjį į failą, nes užduotis buvo vykdoma tik tada, kai sistema ją pasirinko vykdyti perjungdama užduotį probleminėje srityje. Kad ir kas nutiktų atliekant šią užduotį, neturės įtakos kitoms nesusijusioms užblokuotoms užduotims.

Buvo tikimasi, kad kai sistema pasieks probleminio kodo vykdymo tašką, pasaulinis kintamasis bus iš naujo nustatytas pereinant prie kiekvienos kitos išraiškos. Tada atsitiks kažkas, dėl ko užduotis persijungs, o kadangi jos vykdymo dažnis (10 Hz) yra mažesnis nei stebėjimo užduoties, monitorius gali užfiksuoti visuotinio kintamojo reikšmę ir ją įrašyti. Įprastoje situacijoje galėčiau gauti pasikartojančią sąrašų poaibio seką: paskutinės kintamojo reikšmės užduoties perjungimo metu. Kai pakabinamas, pasaulinis kintamasis nebeturi keistis, o paskutinė parašyta reikšmė parodys, kuri išraiška neužbaigta.

Paleidau kodą su stebėjimu. Jis sustingo. O stebėjimas veikė kaip laikrodis.

Žurnale buvo numatyta seka, kurią nutraukė reikšmė, rodanti, kad buvo iškviestas mutex Unlock, o užduotis nebaigta – kaip ir su tūkstančiais ankstesnių skambučių.

„Apex“ inžinieriai tuo metu karštligiškai analizavo savo kodą ir rado vietą mutexe, kur teoriškai gali atsirasti užraktas. Tačiau jo tikimybė buvo labai maža, nes tik tam tikra įvykių seka, įvykusi tam tikru metu, galėjo sukelti blokavimą. Merfio dėsnis, vaikinai, tai Merfio dėsnis.

Siekdamas apsaugoti reikalingą kodo dalį, pakeičiau mutex funkcijos iškvietimus (sukurtus ant OS mutex funkcijos) mažu vietiniu Ada mutex paketu, kad valdyčiau mutex prieigą prie tos dalies.

Įdėjau jį į kodą ir atlikau testą. Po septynių valandų kodas vis dar veikė.

Mano kodas buvo pateiktas „Rational“, kur jie jį sukompiliavo, išardė ir patikrino, ar jame nebuvo naudojamas tas pats metodas, kuris buvo naudojamas probleminėse mutex funkcijose.

Tai buvo gausiausia mano karjeros kodo peržiūra 🙂 Su manimi kambaryje buvo apie dešimt inžinierių ir vadybininkų, dar dešimt žmonių dalyvavo konferenciniame pokalbyje – ir jie visi ištyrė apie 20 kodo eilučių.

Kodas buvo peržiūrėtas, surinkti nauji vykdomieji failai ir pateikti formaliam regresijos testavimui. Po poros savaičių atgalinės atskaitos bandymas buvo sėkmingas ir raketa pakilo.

Gerai, viskas gerai, bet kokia istorijos prasmė?

Tai buvo visiškai bjauri problema. Šimtai tūkstančių kodo eilučių, lygiagretus vykdymas, daugiau nei tuzinas sąveikaujančių procesų, prasta architektūra ir prastas įgyvendinimas, sąsajos įterptoms sistemoms ir išleisti milijonai dolerių. Jokio spaudimo, tiesa.

Ne aš vienintelis sprendžiau šią problemą, nors perkėlimą buvau dėmesio centre. Bet nors aš tai padariau, tai nereiškia, kad supratau visus šimtus tūkstančių kodo eilučių ar net perskaičiau jas. Kodą ir žurnalus išanalizavo visos šalies inžinieriai, bet kai man pasakė savo hipotezes apie gedimo priežastis, užtrukau tik pusę minutės, kol jas paneigiau. O kai manęs paprašydavo paanalizuoti teorijas, tai perduodavau kam nors kitam, nes man buvo akivaizdu, kad tie inžinieriai eina ne tuo keliu. Skamba įžūliai? Taip, tai tiesa, bet hipotezes ir prašymus atmečiau dėl kitos priežasties.

Supratau problemos esmę. Tiksliai nežinojau, kur tai vyksta ir kodėl, bet žinojau, kas vyksta.

Per tiek metų sukaupiau daug žinių ir patirties. Buvau vienas iš Ada naudojimo pradininkų ir supratau jos privalumus ir trūkumus. Žinau, kaip Ada vykdymo bibliotekos tvarko užduotis ir lygiagretų vykdymą. O žemo lygio programavimą suprantu atminties, registrų ir asemblerio lygiu. Kitaip tariant, turiu gilių savo srities žinių. Ir aš juos naudojau, kad surasčiau problemos priežastį. Aš ne tik apsprendžiau klaidą, bet ir supratau, kaip ją rasti labai jautrioje vykdymo aplinkoje.

Tokios kovos su kodu istorijos nėra labai įdomios tiems, kurie nėra susipažinę su tokios kovos ypatumais ir sąlygomis. Tačiau šios istorijos padeda suprasti, ko reikia norint išspręsti tikrai sudėtingas problemas.

Norėdami išspręsti tikrai sunkias problemas, turite būti ne tik programuotoju. Turite suprasti kodo „likimą“, kaip jis sąveikauja su aplinka ir kaip veikia pati aplinka.

Ir tada jūs turėsite savo sugadintą atostogų savaitę.

Bus tęsiama.

Šaltinis: www.habr.com

Добавить комментарий