My Universe Logo

My Universe Blog » Entries Tagged as programming

Bleifreie Schwalbe macht Bruchlandung

Posted by Jesco Freund at Nov. 7, 2011 12:22 p.m.

In Go: First Contact hatte ich mir einen schnelleren und vor allem zu echtem Multithreading fähigen Python-Interpreter gewünscht. Damals wurde ich auf Unladen Swallow aufmerksam gemacht, ein Projekt, das zu jener Zeit auch die Unterstützung Googles genoss. Doch offenbar hat man sich dort entschieden, sich eher auf Go zu konzentrieren – das Unladen Swallow Projekt wurde zur verwesenden Projektleiche.

Nicht unerheblich zum Scheitern dürften auch die hohen technischen Hürden beigetragen haben. So gelang es nicht, durch Einsatz eines JIT und eines Garbage Collectors sowie Verzicht auf den GIL ein besseres Laufzeitverhalten zu erreichen – im Gegenteil, viele Module liefen auf den Entwicklungsversionen des Unladen Swallow Codes langsamer. So verwundert es auch nicht, dass letztlich auch PEP 3146 auf der Halde toter PEPs beerdigt wurde.

Doch was bedeutet das Ende von Unladen Swallow? Für viele Python-Programme erst mal gar nichts. Der Standard-Interpreter (CPython) bietet für die meisten Einsatzzwecke ausreichende Geschwindigkeit. Die Python Standardbibliothek ist nach wie vor eine reiche und gute Sammlung nützlicher Programmbausteine. Auch parallele Programmierung ist mit Python nach wie vor möglich, nur ist man eben auf die Nutzung des multiprocessing-Moduls festgelegt, wenn tatsächlich parallele Ausführung von Programmteilen benötigt wird.

Für die Zukunft von Python bedeutet das aber, dass die Sprache einen Makel weiter mit sich herumschleppt: Es wird auf absehbare Zeit nicht möglich sein, Threads tatsächlich parallel auszuführen. Durch die steigende Verbreitung von SMP-Systemen ist das aber auf Dauer nicht akzeptabel, da es die Eignung von Python zu sehr einschränkt. In einigen Bereichen lässt sich das kompensieren (z. B. durch Ausweichen auf multiprocessing), in anderen aber nicht. So wünschenswert es aus meiner Sicht wäre, aber solange hier keine Lösung gefunden wird, ist Python für mich keine Allzweck-Waffe für den Programmier-Alltag.

No comments | Defined tags for this entry: Go, google, programming, python

Pretty Hard to Protect

Posted by Jesco Freund at Dec. 14, 2010 10:52 p.m.

Unter diesem Titel hatte schon Captain Crunch anno 2006 einen recht bissigen, aber treffenden Artikel zu PHP geschrieben. Wirklich gebessert hat sich seither nichts – wenn pro Version (nach über einem halben Jahr) gefühlte 10 Vulnerabilities gefixt werden (siehe Release-Announcement für 5.3.4), zeugt das nicht von hohem Sicherheitsbewusstsein der PHP-Entwickler, sondern schlicht von miesem Qualitätsmanagement.

Die zahlreichen kritischen Bugs treten übrigens (fast) ausschließlich in den Extensions auf. Das legt für mich den Schluss nahe, dass der Ansatz, alle (Zusatz-) Funktionalität in (in C geschriebenen) Extensions zu organisieren, unter Qualitätsaspekten vielleicht nicht der beste ist. Andere Interpreter-Sprachen wie Perl oder Python konzentrieren sich bei der Programmierung mit C auf den Interpreter-Kern und lagern Zusatzfunktionalität in Module aus, die in der jeweiligen Interpretersprache selbst geschrieben sind.

So können diese auch von weniger erfahrenen Programmierern entwickelt und maintained werden – in Python oder Perl (oder auch PHP) selbst ist es einfach schwierig bis unmöglich, eine NULL pointer dereference oder einen Buffer Overflow zu provozieren. Dazu bedürfte es schon eines Bugs im Interpreter, dessen Code aber verhältnismäßig übersichtlich ist und daher einigermaßen gut auditiert werden kann.

Die ziemlich schlechte Qualität der PHP-Extensions ist meiner Meinung nach ein Stück weit dem Entwicklungsmodell geschuldet – Besserung ist daher erst zu erwarten, wenn hier ein Umdenken seitens der tonangebenden PHP-Entwickler stattfindet. Das ist allerdings derzeit nicht erkennbar…

No comments | Defined tags for this entry: Perl, PHP, programming, python, security

MVC ohne Java, Python, Ruby & Co

Posted by Jesco Freund at Sept. 15, 2010 10:23 p.m.

MVC kann man auch jenseits der klassischen objektorientierten Programmiersprachen umsetzen. Derzeit bastle ich an einer Implementierung in C – teils als Proof of Concept, teils für einen bestimmten Einsatzzweck – auf jeden Fall aber aus Spaß an der Freude.

Die Idee hinter Stormrose (so habe ich das Projekt getauft) ist relativ einfach: Ein kleiner, schlanker HTTPd nimmt Requests entgegen, ermittelt (ähnlich wie bei Django) anhand der URI den zuständigen Controller, übergibt diesem den Request und lässt vom Controller dann eine Antwort generieren, die zurück an den anfragenden Client übertragen wird.

Controller sind dabei einfache C-Funktionen, die einem bestimmten Schema entsprechen. Zu Demonstrationszwecken habe ich einen „Hello World“ Controller schon mal eingebaut, der – wie nicht anders zu erwarten – nur ein einfaches „Hello, World“ an den Client sendet. Ein Controller für statische Inhalte soll noch hinzukommen, so dass Stormrose theoretisch auch als „normaler“ Webserver einsetzbar wäre. Weitere Controller werden dann im Zuge der Entwicklung einer Stormrose-Applikation erstellt.

Auf Seiten der Views habe ich noch keine Aktiv-Posten zu verbuchen – hier muss ich mir noch etwas sinnvolles ausdenken. Einen (schwergewichtigen) XML-Parser möchte ich aber tunlichst vermeiden – sonst kann man ja gleich JSPs verwenden…

Für das Model gilt im Prinzip ähnliches – hier möchte ich allerdings dem Anwendungsentwickler wirklich komplett freie Hand lassen. Einen ORM-Mechanismus wird es nicht geben – Frameworks mit diesem Dreiklang (ORM, Templates, Glue) gibt es schon zu Hauf. Stormrose ist eher für Applikationen gedacht, die eben nicht hauptsächlich Datensätze aus einem RDBMS bearbeiten.

Damit wird es sicherlich eher ein Nieschendasein führen – wer es sich trotzdem mal ansehen möchte, kann sich den Code jederzeit per Subversion auschecken (https://svn.my-universe.com/stormrose/trunk). Derzeit ist der Code aber noch sehr unreif und befindet sich in ständiger Entwicklung. Momentan taugt er also bloß zum Experimentieren. Sobald die Controller-API stabil ist, werde ich dann auch ein kleines How-To zur Entwicklung einer kleinen Stormrose-Applikation veröffentlichen.

No comments | Defined tags for this entry: C, code, development, programming, Stormrose

Die Rückkehr der Primzahl

Posted by Jesco Freund at Sept. 2, 2010 9:16 p.m.

Vor über einem Jahr hatte ich mal über einen kleinen Wettstreit bezüglich eines Primzahl-Generators gebloggt. Damals hatte ich mich darauf beschränkt, das Problem durch geschickte Partitionierung des zu testenden Intervalls zu parallelisieren. Allerdings war meine Implementierung alles andere als perfekt und krankte vor allem an Pythons Global Interpreter Lock. Meine Freundin hatte mich mit ihrer Implementierung fast um Faktor 2 geschlagen :-(

Doch nun habe ich sie in Händen, die ultimative Waffe des Primalitätstesters: im Zen Python Blog ist die Implementierung des Miller-Rabin-Tests in Python wunderbar beschrieben und erklärt. Dieser Test ist probabilistisch; nach unseren Spielregeln muss also bei einem positiven Treffer auf jeden Fall ein deterministischer Test (Primfaktorzerlegung) durchgeführt werden. Allerdings liefert Miller-Rabin verhältnismäßig wenige False Positives, so dass sich mit Hilfe dieses Tests das Finden von Primzahlen noch deutlich beschleunigen lassen sollte.

No comments | Defined tags for this entry: algorithms, programming, Project Euler, python

Go: First Contact

Posted by Jesco Freund at May 8, 2010 12:38 a.m.

Und wieder ist die Welt um eine Programmiersprache reicher geworden – die Rede ist von Go, einer unter Schirmherrschaft von Google entwickelten Sprache, zu deren Vätern auch Vertreter der Unix-Prominenz (wie etwa Ken Thompson) gehören. Auch wenn einige „Fach“-Journalisten (mal wieder) die Sensation wittern und bereits die Totenglocken für C, C++ und Java läuten hören, habe ich mal (entgegen meiner Gewohnheit, bei journaille-generierten Hypes aktiv wegzusehen) ein bisschen mit Go herumgespielt, um mir ein eigenes Urteil erlauben zu können.

Auf den ersten Blick wirkt die Sprache ein bisschen wie „OK, wir nehmen C, fügen Objektorientierung hinzu, ohne die Komplexität von C++ ertragen zu müssen, und packen noch ein bisschen Nebenläufigkeit dazu“. Auf den zweiten Blick offenbart sich, dass die Sprache offenbar einer Hippie-Kommune entsprungen ist – jedenfalls lässt sich nicht mehr so genau sagen, wer die eigentlichen Eltern sind ;-). C und C++ haben auf jeden Fall Pate gestanden (bei Ken & Co. auch nicht anders zu erwarten), aber auch Elemente von Java, Python und sogar Pascal sind mit eingeflossen.

continue reading Go: First Contact

2 comments | Defined tags for this entry: C, Go, google, programming, python

Fröhliches aus dem Leben eines SAP-Entwicklers

Posted by André Mühlnikel at April 29, 2010 11:04 p.m.

Wer selbst im SAP-Coding unterwegs ist, kennt das: immer wieder stößt man auf allerlei Merkwürdigkeiten („Hey, warum nur einmal den Wert zuweisen? Doppelt hält besser!“). Doch was ein Kollege heute fand, ist mal echt was anderes. Und es zeigt, mit was für Leuten man in der SAP-Anwendungsentwicklung mitunter so zu tun hat … Hab jedenfalls gut gelacht :-)

/assets/user/andre/img/jpg/SAP_Comment.jpg

No comments | Defined tags for this entry: ABAP, development, humor, programming, SAP, software, fun

Ich lebe noch!

Posted by Jesco Freund at March 21, 2010 12:09 a.m.

… auch wenn man anhand der langen Zeit seit dem letzten Blog-Eintrag etwas anderes vermuten könnte :-| Da mir momentan etwas die Energie fehlt, zu allen Themen, mit denen ich mich beschäftige, eigene Blog-Einträge zu verfassen, hier ein paar Updates in der Zusammenfassung:

  • Backtory ist nicht tot oder aufgegeben. Ich habe aber entschieden, erst mal ein brauchbares Archiv-Format zu entwerfen – das wird sicherlich noch seine Zeit brauchen. So lange muss es halt mit Duplicity irgendwie gehen, auch wenn ich persönlich inkrementelle Backups verabscheue. Das Leben hält auch so schon genügend Gelegenheiten für Genickbrüche bereit…
  • Den halbfertigen Relaunch meiner Website habe ich erst mal unterbrochen – erstens keine Zeit, und zweitens gefällt mir das, was ich bisher gebastelt habe, schon wieder überhaupt nicht. Ziel ist ein kompletter Rewrite der Site mit Django, und dann gibt's auch endlich ein weniger augenkrebsförderndes Design – versprochen. Hat aber (leider) im Moment nicht die allerhöchste Prio…
  • cdeploy geht gerade in die nächste Runde. Größte Neuerungen des 0.2er Zweigs: es läuft jetzt unter Linux und ist in der Lage zu erkennen, ob eine Datei überhaupt deployed werden muss.
  • Mit Eclipse CDT stehe ich weiterhin auf Kriegsfuß – einerseits gefällt mir das Entwickeln mit Eclipse sehr gut; andererseits ist für mich die Einrichtung eines Projekts jedes Mal ein ziemlicher Albtraum.
  • Zu meinem Mercurial-Server gibt es jetzt auch endlich wieder eine Projektverwaltung. Hier verrichtet Redmine seinen Dienst, das sich endlich in brauchbarer Manier über die FreeBSD Ports installieren lässt. Dem Maintainer sei Dank!

Auch in nächster Zeit wird es hier vermutlich eher ruhig bleiben. Die wenige Zeit, die mir mein Job derzeit zur Verfügung lässt, brauche ich in erster Linie für private Dinge.

No comments | Defined tags for this entry: backtory, blog, Django, programming, Redmine, snafu

The Optimal Archive Format for Backtory

Posted by Jesco Freund at Feb. 13, 2010 9:11 p.m.

During the last few days, I've been thinking about what archive format to use with Backtory. First, everything seemed clear: I intended to use tar (resp. USTar) – a wide-spread standard, meaning backup data would have been accessible with any standard-compliant tar implementation as present among any Unix system I know. However, looking closer at the specification of the tar file format, it shows some weaknesses which turns it to be a bad choice for a differential backup tool. The worst of them are:

  • Tar archives have no index or table of content. This means the whole file has to be scanned to find out about its content, and extracting only one particular file means the same.
  • Tar only reserves 100 bytes for file names. Working with longer path names is possible, yet painful
  • Tar header information is encoded in ASCII, making it difficult working with international character sets
  • Tar archives do not handle arbitrary meta data, meaning
    • it is not possible to encode files in any way (encryption, compression, …) before adding them to an archive
    • it is impossible to store extended information like ACLs for a file without resorting to ugly workarounds (like creating .meta files for each file)
  • When it comes to compression, tar files can only be post-processed with a compressor, meaning the entire archive has to be decompressed before it can be scanned

This rant may give you some more reasons why tar is really a bad choice, but to sum it up: I consider it too painful downloading a complete backup archive to the local harddisk, decompress it there and then scan through the whole file just to restore one single file. Wouldn't it be much smarter if Backtory just had to download the archive header and then check which part of the archive actually has to be downloaded and post-processed (e. g. decompressed)? Even with stupid old FTP this would be possible – just by aborting RETR after x received bytes and using REST plus ABOR again to fetch a specific part of a file.

So how would the optimal archive format for Backtory look like? I think this can be best described by a list of requirements:

  • The archive must be indexed. Minimum requirement for an index would be a table providing (relative) path names and offsets to meta data and data section of the file. The index table must be located at a predictable or easily determinable position within the archive file.
  • For each file, a bunch of standard meta data must be stored (virtually the information provided by lstat)
  • The archive format must allow arbitrary meta data for each file. Some of them could be standardized (e. g. encoding or compression method), others may vary from application to application (e. g. ACL data, MAC labels, encryption method, …)
  • It must be easy and cheap to extend an archive. To be more precise, I would consider it inacceptable if something had to be inserted at the beginning of an archive file, entrailing a shift of all successive bytes, meaning all offset data have to be reacalculated and nearly all data in the file reorganized on the file system. “Easy” and “cheap” would be perfectly achieved if an archive could be extended even via FTP (but I consider this very unlikely to become true without breaking the other requirements).
  • Recoverability in case of a damaged index: By doing a single pass scan over the meta data and content data blocks, it should be possible to regain all information necessary to rebuild the archive index.

Well, that's it. However, I have not found any yet-existing archive format that covers these requirements (at least none which is patent-free and has at least one open source implementation). And before anyone starts rhapsodizing about xar, I'd like to state why I see xar to be unfit for Backtory:

  • The meta data block is in XML, which means you need a fat parser to process it.
  • The heap (all file content data) is useless without the meta data ⇒ recovery of a damaged toc is anything else than easy (I doubt it's possible at all).
  • The toc (XML meta data) is located at the beginning of a xar container. When extending a xar archive, all data inside must be relocated since its toc has to be extended.

I guess I have to design my own container format for Backtory. However, if I really should do so, I would implement it as a library independent of backtory and give it its own CLI tool. I already got some idea how the archive container could look like, but there are still some details I have to work out. Stay tuned, I'll keep you informed about what I'll do and how I will implement it…

No comments | Defined tags for this entry: backtory, code, programming

Portable Shell-Skripte mit absoluten Pfaden

Posted by Jesco Freund at Oct. 3, 2009 2:23 p.m.

Gute Shell-Skripte sprechen Binaries mit dem absoluten Pfad an. Dadurch wird das Skript unabhängig von der Umgebungsvariablen $PATH und funktioniert auch manierlich, wenn es beispielsweise üder die Crontab oder unter einem andere User aufgerufen wird. Soweit die Theorie, doch in der Praxis gibt es einen gemeinen Fallstrick, der den Wanderer zwischen den Unix-Welten das Leben bzw. Skripten schwer macht. Betrachten wir einmal das folgende Beispiel:

#!/bin/sh

b_uname="/bin/uname"
b_awk="/bin/awk"

name=`$b_uname -n | $b_awk -F. '{print $1}'`

echo "Das System heisst ${name}."
exit 0

Dieses kleine Skript ist ein (zugegebenermaßen etwas umständlicher) Ersatz für den Befehl hostname -s – das tut aber eigentlich nichts zur Sache. Viel spannender ist die Frage, wie portabel dieses Skript arbeitet. Unter CentOS 5.3 kann ich es fehlerfrei ausführen. Anders sieht es aus, wenn dieses Skript auf einer Maschine mit FreeBSD oder Solaris aufgerufen wird: Unter FreeBSD erhält man Fehlermeldungen („Command not found“), da uname und awk nicht wie bei CentOS und Solaris in /bin liegen, sondern in /usr/bin (bei Solaris kommt es ebenfalls zu Problemen, die aber darin begründet sind, dass die Solaris-Implementierungen von uname und awk von den GNU-Implementierungen abweichen – doch dazu später).

Unter den verschiedenen Unix-Derivaten und sogar Linux-Distributionen liegen Binaries also nicht immer am selben Ort. Müssen portable Skripte also darauf verzichten, absolute Pfade zu verwenden und sich auf $PATH verlassen? Natürlich nicht. Allerdings funktioniert der Schnellschuss „dann definiere ich Binaries eben systemabhängig“ auch nicht so ohne weiteres – man sieht ja, dass das häufig dazu herangezogene uname schon nicht sehr portabel gelagert ist. Es gibt jedoch einen eleganteren Weg, der sich nur auf Shell-interne Funktionen stützt und daher tatsächlich komplett portabel ist:

#!/bin/sh

detect_binary() {
    local BINDIRS="/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /opt/csw/bin /opt/sfw/bin /usr/openwin/bin"

    for i in $BINDIRS; do
        if [ -x "${i}/${1}" ]; then
            echo "${i}/${1}"
            break
        fi
    done
}

b_uname=$(detect_binary "uname")
b_awk=$(detect_binary "awk")

Die Funktion detect_binary probiert alle angegebenen Pfade durch, bis sie in einem auf eine ausführbare Datei mit dem gesuchten Namen stößt. Anschließend gibt sie den absoluten Pfad des gefundenen Binaries zurück. Auf diese Weise wird zum einen sichergestellt, dass nur Binaries aus den vorgegebenen Pfaden verwendet werden, und zum anderen, dass die Binaries weiterhin unabhängig von der Umgebungsvariable $PATH gefunden werden können.

Eines löst dieser Code-Schnipsel jedoch nicht: Das unterschiedliche Verhalten von gleichnamigen Binaries unter verschiedenen Unix-Derivaten. Auf vielen Nicht-Linux Systemen stehen Binaries der GNU-Implementierung zur Verfügung, oder zumindest Binaries, die das Verhalten der GNU-Implementierungen nachahmen. Unter FreeBSD beispielsweise findet man in gsed und gawk die GNU-Implementierungen, während sich hinter sed und awk die traditionellen BSD-Implementierungen verbergen. Die <programm>-Binaries findet man im übrigen auch unter Linux. Benötig man also in einem Skript explizit das GNU-Verhalten (beispielsweise beim Einsatz von sed -i, so sollte man auch die GNU-Binary-Namen verwenden.

Happy Scripting!

4 comments | Defined tags for this entry: code, FreeBSD, Linux, programming, scripting, shell, Solaris

Altes Eisen

Posted by Jesco Freund at July 31, 2009 9:54 p.m.

/assets/user/jfreund/img/png/sprachen.png

Laut Statistik von GitHub ist Ruby die derzeit am meisten verwendete Programmiersprache. „Meine“ Sprachen, also C, und Python („Shell“ ist doch keine Programmiersprache… *scnr* 8-)) kommen noch nicht mal zusammengenommen auf den „Marktanteil“ von Ruby. Scheint so, als wären Webanwendungen schwer angesagt – vielleicht nutzen aber auch die meisten konventionellen Projekte einfach nur andere Hosting-Plattformen… Trotzdem fühlt es sich komisch an, bei C gerade mal schlappe 6% zu lesen.

1 comment | Defined tags for this entry: C, code, programming

Page 1 of 3 next page »