mercredi 14 juillet 2010

Lama tutorial blueprint: preambule

Computers are amazing machines. Thanks to Internet and to free software, it is quite easy to find software that fits our needs -- for free.

However, the more the task to do is particular, the harder it is to find a ready-made piece of software. Often, as a matter of fact the task is a combination of simpler ones, for which programs do exist. But how to combine them?

This problem, probably as old as computers, has different kinds of solutions. The first one consist in including some communication or cooperation means between applications. Those who promote the "Unix philosophy" are in favor of that; they believe that each program should only do one thing, and that we should build applications by linking them together with pipes, in which flows textual data. This approach is in use in Linux for moderately complex programs. Because in practice, the more the application is complex, the even more complex is the required "plumbing".

The second kind of solution is to create "big" but extensible software; most of the times by the mean of an embedded programming language. A popular exemple of this are web browsers like Firefox; one may also think of office suites. The drawback is that this extensibility is often limited to the domain of the application.

The last kind of solution consists in programming by ourselves what we need. We build our application by assembling software components with a scripting (or "glue") language.

Note that all three require some amount of programming.

I believe that the last approach is the best one, because it doesn't suffer the limitations or constrains of the others: using a true programming language allows to manipulate data in their original form rather than in a textual form, which makes things easiers. And by using software components, we are able to freely combine functions that belong to completely differents domains.

There are already plenty of languages for this, like Lua or Python. However, none of them gather the set of features that I think are required in order to allow those who feel able to, to program by themselves what they want.

These features are:

  • Early checks to flag the most obvious programming mistakes. The corner stone for this is static type checking. Most of the scripting languages check very few things; as a consequence a stupid typo can lead to a hard to find bug.
  • To accept that programming is a mean, not an end. Most languages are designed with the assumption that either you want to become a "true" programmer, or that you already are. Few assume that you program on the week-end just like others throw shelves together.
  • Correctness. Scripting languages are often designed with the idea that scripts are little, personnal throw-away programs, that don't need to be reliable or entirely correct. From my perspective, and in my experience, a program that deserved to be written is a program that might be reused and enhanced. To write a correct, reliable and robust program from the beginning is most of the time a benificial investment.
  • Efficiency. Scripting languages, by nature, are slower and more memory hungry than others; but some are abnormally. A greater efficiency allows to delay the moment when the programmer has to rethink its program because it is way too slow.

This is why I had to create Lama.

Although Lama is design to be approachable, I do not promise you that things will always be simple, smooth and easy. The picture of the typical Lama user I have in mind, is someone with some scientific education, or at least who has a logical mind. A prior programming experience is welcome, but not required.

Because programming requires that (this, and also some patience and self-control); those who promise you Easiness incarnated are always decieving you in a way or another.

This means that you will have to invest some efforts to read, experiment and understand, for instance, the difference between an entity and the reference to an entity; the concept of a type or of a closure, may also give you a hard time.


dimanche 11 juillet 2010

Better than GCC?

This one is of the sadly-funny kind.

Lama, my little programming language project, tries to spot the usual programming mistakes: using a variable before it has been initialized, returning an undefined value, etc. I am kind of proud of that, because it is quite reliable and to my surprise, already pointed to me such errors a couple of times.

The last time is precisely today. I was implementing for the first time an extension library, for accessing files. On the lama side, I wrote a quick and dirty test script that goes like this:


var testFile File
when openFile "todo.woim"
is File: set testFile, it
is BadFilename: print "bad filename"
is PermError: print "permission error"
is NoDevError: print "nodev"
is ResExhausted: print "sys error"
is Bug: print "bug"
end

when read testFile 100
is String: print it
is Nihil: print "EOF"
is FileClosedError: print "closed file"
is IOError: print "IO error"
end
Lama pointed to me that at line 'when read testFile 100', the variable 'testFile' is used before initialization, which is correct because it was not initialized in all the cases of the previous 'when' statement. 'when' statements are like 'switch' statements or pattern matching of FP languages, except that they deal with the members of a tagged union, which have distinct types (most of them are actually unit types, here).
Lama is unusually strict about that, given that it is a scripting language. This prevents precisely the "quick and dirty" temptation.

I put the latter 'when' in the first 'is' of the former one, but Lama was still crashing. When I looked back at the C side the function that was actually the first mistake I saw was.... that I was using an uninitialized variable!

And GCC didn't warn me about that, despite of the -Wall -Wextra and whatnot.

Lama is a very simple language. and it's implementation uses brute force at will; it doesn't even built abstract syntax trees nor does SSA transforms, the kind of thing respectable compilers do.

And still, it does a better job than GCC at spotting obvious programming mistakes. It is funny to think that my little toy, home-made 4KLoc compiler does better than a multi- megabyte one implemented by experts.

Edit:
It appears that one gets more warnings when one switches from -g to -O2; how is that a debugging switch does mask potential bugs?


vendredi 19 mars 2010

When can code duplication be better?

Follow-up to a conversation on reddit:

C and C++ make it hard to read a register for its side effects (main article)

my comment:

"It seems to me that when one is concerned about these issues, and checks the compiler's output, one is also able to write the desired machine code.
So why not just use inline assembly in the first place?"

A redittor:

"It doesn't hurt to write portable code even in this context. You may have to run your code on a PPC instead of an ARM, but targeting the same peripheral."

It happens that I worked a lot this week on the Linux kernel; I tried to add support for a development board we bought, and it happens it is ARM-based.

The thing to know is that ARM is not just one processor, it is a large family of processors, perhaps as big as the m68k familly. As a result, there's a large collection of processor-specific source code files in the kernel.

There could be more, actually. It's kind of a tautology, but within a family the difference between two processors are minor with regard to what they have in common. Often it boils down to some extra built-in peripheral support.

As a consequence, and it looks like a good thing at first glance, the Linux maintainers choose to put the sharable code into common files, and use various tricks for the parts that differ.

Except that it is squared by the number of boards that may use a chip, because different boards are often "wired" differently.

In the particular, in the kernel part I was working in, they handled that not only with the usual #ifdef conditional compilation tricks, but also with include file search path order.

Conditional compilation is brittle, because a single typo can accidently select the wrong code; it is also harder to read. The include search path thing is even worth; one has to read an horribly long compilation command in order to get the actual inclusion order. When you see that some compilation options (including the -I ones, include search path specifications) are duplicated, probably because the makefile stuff is not totally under control, you start to think that something is wrong.

The bottom line is that, in order to avoid duplicate code, we end-up with a build recipe that can give one headaches very quickly. 

It seems to me that the total energy spent in the DRY effort overweights the cost of just duplicating the code. This rather particular and extreme case, but it shows that the DRY principle isn't always appropriate.


samedi 13 mars 2010

13 Mars

A peine croyable. La CIA aurait "épicé" le pain d'un petit village du sud de la france en 1951? (en anglais)

Internet ou Minitel 2.0? 

Plus:
http://faq.tuxfamily.org/InternetLibre_ou_Minitel_2.0/Fr

http://wiki.auto-hebergement.fr/

"Vector conflict Siege" - Jeu flash

Slayer - Raining Blood - version 8bits

Steambirds - jeu flash; mini-wargame tactique au tour par tour avec une pointe de temps réel.

Retroshoot360 - Jeu flash. Shoot them up style arène. Difficile, mais prenant.


dimanche 7 février 2010

Un navigateur Web est-il une bonne interface pour un produit embarqué?


Cet article fait suite à mes commentaires sur un article de Gilles Blanc. J' y réagis à une affirmation que la tendance observée d'utiliser un navigateur Web comme interface graphique d'un produit embarqué est parfaitement appropriée, même quand le produit n'a nullement pour objectif ni nécessité de se connecter sur le Web, ou encore de fournir une interface déportée (paramétrage à distance d'une imprimante par navigateur Web, par exemple).

Je précise que Gilles Blanc est ingénieur chez Linagora, société de taille respectable spécialisée dans l'open source. Je suis pour ma part ingénieur spécialisé dans l'embarqué "haut de gamme" (c'est à dire capable de faire tourner un Linux; par opposition au "petit embarqué" basé sur un micro-contrôleur 8 bits où un OS serait impensable et de toutes façons, superflu).

Il se trouve que l'entreprise pour laquelle je travaille a adopté cette solution, après avoir évalué superficiellement une solution classique du style nano-X (GUI basé sur "frame buffer"). J'ai eu dès le départ des doutes sur la pertinence de celle-ci. J'en ai fait part quand on m' a demandé mon avis sur la question, puis on ne m' a plus demandé mon avis. Malheureusement, quasiment toutes mes craintes ce sont avérées justes, et après 6 mois/homme de travail (par mes collègues) le produit n'est que "presque" fini. Le pire est que certaines de mes doutes portaient également sur l'exploitation du produit fini.

Pourquoi ai-je vu dès le départ l'utilisation d'un navigateur Web comme interface graphique d'un mauvais oeil? Il suffit de considérer les choses d'un point de vue purement technique: pour faire tourner une interface graphique "Web" il faut:

  • Un navigateur Web. On sait que les "browsers" ne font pas partie des applications les plus légères et les plus simples. Ce qui se traduit par consommation élevée de ressources et une source de bugs potentielle.
  • Un serveur X11 ou équivalent. Encore des ressources consommées, encore une source potentielle de problèmes. Soit dit en passant, il existe au moins un portage de Webkit qui permet de se passer de X11, mais le portage de celui-ci sur notre premier prototype a été un échec pur et simple malgré l'aide (rémunérée) des auteurs.
  • Un serveur HTTP, car le navigateur, pour énorme qu'il soit ne sait rien faire tout seul. Il existe des serveurs HTTP vraiment très compacts, mais reste qu'on puise encore dans les ressources et qu'on installe encore une source de problèmes.

Par comparaison, pour une interface graphique construite avec les moyens classiques on a besoin:

  • D'une librairie GUI capable de fonctionner sur frame buffer.

J'insiste sur les "sources de problème potentielles", car c'est une dimension importante pour un produit commercial. Si l'un des composants de l'ensemble logiciel se comporte mal (fuite mémoire, crash - et soit dit en passant, si vous réutilisés du logiciel développé à l'origine sur PC il faut être conscient que sur PC, une fuite mémoire, un "freeze" ou un plantage ne semble pas aussi préoccupant que dans l'embarqué), vous avez le choix entre corriger vous même le logiciel, ou attendre que les auteurs ou la communauté le corrige. Dans les faits, le second terme de l'alternative n'est pas toujours envisageable. Quant au premier: déboguer un problème se produisant dans un empilement de quelques centaines de milliers de lignes de source est un problème redoutable

La comparaison parle d'elle-même, mais n'est pas tout à fait juste car quand même un navigateur Web ne consomme pas des méga-octets de RAM et flash sans raison. Cette raison est que tout ce qui apparaît dans un navigateur Web est "scripté": Javascript, CSS, HTML.

Cela offre il est vrai certaines facilités et une certaine souplesse. Mais observons que d'une manière générale dans l'embarqué, les logiciels sont beaucoup plus figés que dans le monde du PC, car les produits sont conçus pour répondre à un cahier des charges assez précis. Si toutefois on veut un peu de cette souplesse avec une solution classique, il existe une demi-douzaine de langages de script embarqués (Lua vient immédiatement à l'esprit).

Un argument qui revient souvent lorsque l'on parle de performances et d'efficacité des technologies est que "les cycles CPU comptent moins que les cycles développeur". Là encore, cet argument est beaucoup moins défendable dans le domaine de l'embarqué que sur PC. La raison est que les produits embarqués forment un ensemble matériel et logiciel commercialisés sur un marché concurrentiel. Comme je l'ai indiqué précédemment, la partie logicielle est relativement figée, donc le coût des développements l'est également, et est divisé par le nombre d'unités vendues. A contrario, le prix du matériel pèse sur chaque unité vendue. Donc, d'un point de vue purement financier, on a dans ce contexte beaucoup plus intérêt à réduire le coût matériel que celui des développements logiciels. Concrètement, j'estime (sur la base du fait que le processeur coûte de fois plus cher) que le prix de revient du matériel nécessaire pour faire tourner un navigateur est 50% plus élevé que celle nécessaire pour faire tourner la solution classique.

Le prix de revient matériel plus élevé est-il compensé par un coût de développement moins élevé? Pour être juste, cela dépend beaucoup du prix du matériel et du nombre d'unités produites.

Mais il y a plus problématique pour fonder une estimation: la productivité d'un développeur est difficilement mesurable. En particulier, rien ne permet de dire a priori s'il est plus rentable de développer une interface en C/C++ plutôt qu'en Ajax/HTML/CSS. Cela dépend grandement de l'expérience du développeur dans le domaine.

Quitte à choisir entre les deux, et au risque de donner l'impression de défendre mon territoire, mieux vaut choisir un développeur embarqué pour de l'embarqué; c'est une question de bon sens (et donc, votre homme connaitra de toutes façons C/C++ et saura traiter avec Qt ou autre). Le titre de développeur embarqué n'est tout même pas une médaille en chocolat. On doit faire preuve de rigueur et de parcimonie, car toutes les ressources (cycles CPU, flash, RAM) sont le plus souvent limitées et non extensibles; les mauvais fonctionnements, les crashs sont des plaisanteries assez peu goûtées (surtout si l'utilisateur est un client qui a déboursé une certaine somme; et a fortiori quand le système à une mission un tant soit peu critique); les moyens de déboguage et d'analyse post mortem sont souvent limitées. Du point de vue d'un développeur embarqué, les problèmes d'incontinence avec la mémoire, d'exceptions non interceptées, d'obésité injustifiables, de latences injustifiées, et cætera, de pas mal d'applications (y compris commerciales!) sont consternants.

Le choix d'utiliser un navigateur Web comme interface graphique plutôt que les technologies habituelles ne peut donc pas se faire sans discernement. Si on ne cède pas trop facilement au phénomène de mode ou à la séduction (j'ai envie de dire "coolitude"), et qu'on analyse d'une manière rationnelle les faits, force est de constater que cette solution n'est pas sans inconvénients notables. Il s'agit donc d'une solution adaptée à des applications précises plutôt que d'une solution généralisable à toute application.


vendredi 11 septembre 2009

Tracks

Un extrait de ma playlist YouTube:

Keep of Kalessin: Ascendant, Armada, etc.

Neuraxsis: The All and Nothing

Arsis: The Face Of My Innocence

Cattle Decapitation - Regret and the Grave

Arch Enemy - Nemesis

The Berzerker - All About You

Kronos - Phaeton

The Crown - I won't follow

Slayer !!!  - Psychopathy Red, Hate Worldwide


dimanche 26 juillet 2009

Réseaux sociaux

Tiens, un lien intéressant; partageons-le.

Alors, devrais-je le partager sur Twitter ou Facebook?

Ou peut-être Delicious, StumbleUpon?

Ou encore reddit? Ou le mettre en partage dans mon Google Reader?

Ou devrais-je utiliser FriendFeeds?

Ou devrais-je attendre Google Wave?


Le cas de FriendFeeds est révélateur: il se propose de centraliser tous les autres. Sa raison d'être est de résoudre l'éparpillement que génère l'usage de tous les autres. 

Le paradoxe est que d'une certaine manière, il ne fait que s'ajouter au problème. Maintenant que le lien est partagé sur Twitter ou sur reddit, il faut aller sur Twitter, reddit et FriendFeeds lire les commentaires.

Revenons au problème de base. Internet est un monde vaste. Le principal défi qu'il pose est d'extraire l'information qui nous intéresse dans tous ces tera-bits de données.

Les moteurs de recherche sont certes une aide précieuse, mais ont leurs limites. Google a beau employer des algorithmes sophistiqués pour indexer le Web, si les résultats de recherche ne sont pas probants sur la première ou deuxième page, ils sont peu nombreux les courageux qui creusent plus profond. Car on se retrouve vite noyé dans un océan de liens.

D'où l'intérêt de se créer un réseau de connaissances. Cela permet de mutualiser la recherche et le filtrage du Web selon nos centres d'intérêt.

On pourrait imaginer que chacun ait une page personnelle, dans laquelle il pourrait communiquer ces réflexions et observations du moment, ou mettre des liens qu'il juge intéressant. On pourrait imaginer pouvoir s'abonner à cette page, pour recevoir un message quand un nouvel article y apparaît. On pourrait imaginer aussi que les gens puissent commenter ces articles. Si on a plusieurs centres d'intérêts, on pourrait ranger les articles dans différentes catégories, ou y apposer différentes étiquettes. Et bien sûr, chacun pourrait indiquer quelles pages il suit, afin de constituer un réseau de connaissances. En cerise sur le gâteau, on pourrait imaginer un index général de ces pages, qui les répertorierait selon les catégories et étiquettes qu'on y trouve.

Ce serait une idée géniale, ne trouvez-vous pas?