Basic personligt

Daniel Brahneborgs blogg

There and back again

Att låta ett program hoppa mellan olika programspråk var visst inte så enkelt. Från C kan man öppna filer med kompilerad C-kod och anropa funktioner där utan större problem. Funktionerna där kan använda externa bibliotek, liksom anropa funktioner i det ursprungliga programmet. Av någon konstig anledning verkar folk tyvärr inte gilla det språket, så vi ville erbjuda fler alternativ.

Jag hade kört en del Ruby, och tänkte att det kunde vara ett trevligt språk att erbjuda. Tyvärr fick jag aldrig minneshanteringen att bli rätt där, och när jag nu kollade några år senare så verkar det som om språket fortfarande är helt enkeltrådat, och inte ens fungerar som del av en multitrådad applikation.

Numera fanns även mruby, som klarade trådar. Tyvärr så använde den inte rubys normala “gem”-hantering, vilket gör den ointressant.

Det gick att anropa funktioner i Perl från C, så länge som man lät varje Perl-motor ligga i en egen tråd. Dokumentationen var ganska bra (även om det råder delade meningar om vad SvPOK() faktiskt testar), och minneshanteringen gick att få stabil. Anrop tillbaka till C var däremot en helt annan sak. Hela upplägget där bygger på att C-koden är en del av en Perl-modul, med sina egna byggregler och annat. Varianten att C-koden är en del av programmet som anropade Perl, hittar jag ingen dokumentation för. Antingen skriver man en mod_perl som anropar perl, eller så gör man en mysql-adapter. Inte båda.

Python kändes lockande, med bra api-er åt båda håll, ända tills jag såg listan med minnesläckor. Nej, tack.

För PHP hittar jag bara dokumentation för när PHP anropar C, inte tvärtom. Det lockar inte att sno källkoden till mod_php, även om den gör väldigt nära det vi vill ha. Dessutom framgår inte hur trådsäkert det är.

Det finns en reimplementation av PHP som heter PH7. Där är det enkelt att göra anrop åt båda håll, den är trådsäker, men den verkar inte ha något stöd för externa standardpaket. Allting måste därför finnas antingen i PHP-koden eller i applikationen som anropar den.

Javascript kändes också lockande, speciellt med Googles V8-motor. Den är trådsäker, man kan göra anrop åt båda håll, men så var det ju det där med externa moduler. De enda javascriptmoduler jag hittar är byggda ovanpå node.js. Att köra sådan kod skulle kräva en egen reimplementation av ungefär hela node, eller att vi skrev om hela vår app att också köras inuti node. Inget av det lockar överhuvudtaget.

Python, PH7 och V8 är onekligen en generation senare än de andra. Mycket renare API än Perl, och i V8-fallet dessutom med massor med coola features från de nyare varianterna av C++ (framför allt C++11) för att undvika minnesläckor. Det är irriterande att det verkar vara så svårt att kombinera det här med språkens övriga ekosystem, så som Perl lyckas med.

Är det något språk jag har missat, som faktiskt uppfyller alla krav? Java?

February 12th, 2016 Posted by Daniel Brahneborg | blogg | no comments

Testade Python

Ett klassiskt sätt att låta användarna göra egna tillägg till ett program är att stödja ett eller flera skriptspråk. Istället för att starta en ny process för interpretatorn som kör användarens kod, görs den till en del av huvudprogrammet. Det är så webbservrarna kör perl och php, t.ex. Jag tänkte göra detsamma nu, men för python.

För att vara säker på att mitt program inte har några minnesläckor eller klantar sig på andra sätt, testas varje ny version med Valgrind. Den hittar saker som att man läser värden innan de är skrivna, använder minne efter att det är återlämnat, och massa annat. Jag började nu med ett minimalt program som traditionsenligt bara skrev ut “Hello World”. Valgrind blev synnerligen irriterad, och skrev ut hundratals varningar. Ok, jag kanske hade missat någonting?

Jag testade med den riktiga interpretatorn, och körde samma sak där. Jo då, hundratals varningar även nu, både minne som glömts bort och som försöks återlämnas flera gånger. Det senare felet är allvarligt, för det kan göra att programmet kan krascha helt slumpmässigt. Om man råkar ha någon fil öppen så kan även innehållet där skrivas över. Det är verkligen en “all bets are off”-situation. I Unix-världen är det därför ganska vanligt att man struntar i att lämna tillbaka minne när programmet avslutas, eftersom allt ändå tas om hand av operativsystemet. Det är onödigt att flyttstäda i ett hus som ska rivas. Ändå störde det mig.

Man kan bygga python med en speciell flagga, som gör att den funkar bättre med just Valgrind. Sagt och gjort. Jo då, alla dubbla återlämningar försvann. Tyvärr fick jag då bara ännu fler varningar om bortglömt minne. Att få reda på om den läcker lika mycket oavsett vad man gör, eller om den läcker lite grand varje gång ens program körs, är inte helt lätt att få reda på. Det går säkert, men kräver större kunskap om python-källkoden än vad jag har tid och lust att skaffa mig. Att få överblick på en halv miljon rader C-kod är inte gjort i en handvändning.

Å andra sidan spelar det ingen roll. Att lämna tillbaka minne i rätt ordning är ibland väldigt svårt. Antingen glöms vissa bitar bort, eller så trampar man sig själv på tårna och lämnar tillbaka saker för tidigt. Jag har haft samma problem med min egen kod mer än en gång. Poängen är att anledningen till de problemen, är exakt alltid i samtliga fall att jag inte har haft kontroll på vad koden egentligen gör. Saker körs, men jag vet inte i vilken ordning. I ett sådant läge är det lätt att bara ge upp, eftersom man inte riktigt behöver bry sig. När programmet avslutas, kommer operativsystemet ju ändå städa upp. Om det alltid läcker lika mycket minne oavsett hur länge programmet har körts eller vad det har gjort, är det i praktiken inte ett problem.

Från mitt perspektiv är det ändå inte ok. Om problem med minneshantering kan bero på bristande kontroll, betyder det att mitt förtroende för koden minskar. Om programmerarna har problem här, har de förmodligen problem med andra saker också. Omvänt gäller också. Har man stenkoll på vad koden gör och vilken del av koden som äger vilket minne, är det en kakbit att se till att minnet återlämnas på rätt sätt och i rätt ordning.

Det hela blev ännu sämre av att flera filer måste vara skrivbara när man kompilerar python, eftersom de genereras på vägen. Ändå måste de finnas från början, annars går bygget sönder med en gång. Återigen, brist på kontroll på sakers livscykel.

Så nej, det blir ingen python just nu.

February 8th, 2016 Posted by Daniel Brahneborg | blogg | one comment

|