dimanche 12 mai 2013

Une épingle à nourrice

Voici la modélisation et le rendu d'une épingle à nourrice. Finalement, ça a été plus simple que ce que je pensais. L'épingle a été modélisée en utilisant un chemin Nurbs, comme montré sur l'image en dessous, et un cercle Nurbs utilisé comme bevel object. J'ai utilisé une photo d'épingle en fond afin de me calquer dessus.

Gérer le ressort proprement a été un peu compliqué, puisqu'il a fallu remonter d'un côté et redescendre de l'autre pour ne pas que la boucle rentre en elle-même. Finalement, tout a été fait au pifomètre, et ça ne marche pas trop mal.

Pour la partie qui coince l'épingle, j'ai suivi la bonne vieille méthode de démarrer avec un cube, d'extruder vaguement pour couvrir la forme, et d'appliquer la modification sub-surface jusqu'à ce que ça ressemble à quelque chose.

Et pour finir, un rendu avec fond transparent dans un angle qui cache les parties moches, et basta!

mercredi 8 mai 2013

async_commit=off

J'expérimente ces temps-ci avec l'option "async_commit=off" de Postgresql. Cette option indique au serveur de rendre la main au client dès que le commit est effectué en mémoire, sans attendre que les données soient effectivement écrites sur le disque. L intérêt est donc de découpler la vitesse d'écriture sur le disque dur, et donc de diminuer la latence et d'augmenter le nombre de transactions par seconde.

En contrepartie, si le serveur venait à crasher, quelques secondes de données seraient perdues. Si cette contrainte est acceptable, par exemple parce que les données sont mises à jour régulièrement, ou parce que plusieurs bases tournent derrière un pgPool, c'est un sacré coup de boost.

Voici un petit benchmark qui fait tourner en boucle 1000 transactions, chaque transaction insérant un entier dans une table faite d'une simple colonne, sans contraintes. Le test tourne en local et en distant sur une machine avec lequel j'ai un ping de 200ms, avec synchronous_commit=off et synchronous_commit=on.

L'on voit que les performances augmentent d'environ 30% en local, ce qui est tout à fait appréciable. Mais l'autre chiffre intéressant est la grosse chute de performances en distant: le gain du commit asynchrone reste à peu près identique en relatif, mais la chute est rude. Le fait d'avoir à faire l'aller-retour pour chaque transaction est très coûteux.

La conclusion, c'est que s'il est possible de relâcher ses contraintes d'intégrité, synchronous_commit=off est une manière simple d'obtenir un impressionnant gain de performances. Mais c'est aussi que dans le cas de nombreuses petites transactions, le goulot d'étranglement se trouve sur le réseau, et non sur le disque ou le processeur. Dans ce cas, peut-on imaginer de faire tourner une base en local pour les performances, qui se répliquerait de manière asynchrone sur une base distante utilisée pour le basculement lors d'un crash?

mardi 23 avril 2013

Coder efficacement avec Emacs - Partie 7 - Tramp mode

Le mode "Tramp" d'Emacs permet d'éditer des fichiers distants, typiquement par ssh. En plus de l'édition, toute une série de modes fonctionnent également en distant, notamment la compilation et le debug.

Ma découverte du mode Tramp a commencé lorsqu'il a fallu que je développe depuis ma machine de bureau Windows sur des serveurs Linux situés un peu plus loin que d'habitude. Tout d'un coup, mon installation habituelle à base de Putty + Exceed ou XMing (des serveurs X pour Windows) était horriblement lente. C'est parce que le protocole X est fait pour des réseaux locaux à basse latence, et devient complètement inutilisable même avec 1ms de délai. Une solution est d'utiliser VNC, qui est bien plus efficace dans ces conditions. Une autre est de faire tourner Emacs sur sa machine locale et d'utiliser Tramp.

Son utilisation est simple: il suffit d'ouvrir un fichier via C-x C-f et d'utiliser la syntaxe /ssh:user@machine:~/chemin. L'auto-complétion fonctionne, et l'on peut aller chercher son fichier. Une fois ouvert, on l'édite normalement, et on le sauve sur le chemin distant de manière complètement transparente.

Mais ce sont les modes de compilation et le mode gud qui rendent la fonctionnalité si utile. Une fois un fichier ouvert en distant, une commande de compilation, ou une ouverture du debuger se fera également en distant.

La réactivité d'une application locale, comme si on tournait là-bas!

mercredi 10 avril 2013

Meuh

Un bon mal de crâne avec le framework Android qui n'en fait qu'à sa tête, très mal au bras droit après avoir importé 280 pages dans Confluence parce que mes admins ne savent pas automatiser la chose, des tests unitaires qui foirent parce que l'on a perdu de gros fichiers de données qui seront très difficile à régénérer, la découverte que notre stratégie de gestion des fuseaux horaires est complètement foireuse, mon moral de programmeur n'est pas au beau fixe. Et pourtant, j'ai réussi à convertir mon équipe à IRC, j'ai gagné la bataille des bases de données en imposant Postgresql, et j'arrive à développer sur des machines situés sur des réseaux à haute latence sans avoir à utiliser VNC (simple snobisme), grâce au mode Tramp d'Emacs dont il faudra que je vous cause plus avant. Finalement, les choses vont plutôt bien!

lundi 18 mars 2013

Une goutte

Une goutte très stylisée rendue avec Blender.

Rien de bien méchant, si ce n'est le fond transparent. C'est tout bête, mais encore faut-il savoir comment faire. Tout se passe dans le panneau de rendu. D'abord, désactiver le rendu du "ciel", c'est à dire du fond, dans la section "Layers". Ensuite, rendre l'image avec une composante de transparence en choisissant RGBA. Bien entendu, il faut que le format d'image supporte la transparence, mais PNG, le choix par défaut, le permet.

Et voilà. Fort pratique pour les icônes et logos.

jeudi 14 mars 2013

Reparlons de move semantics

Et voyons si cela change fortement la manière de passer ses paramètres en C++11. Imaginez que vous deviez implémenter une queue d'objets, par exemple pour la rendre thread safe. En c++03, l'on penserait immédiatement à écrire le "push" en passant son paramètre par référence constante, comme montré dans push1. Comparons donc cela avec push2, qui semble au premier abord moins optimal (notez que l'objet A affiche simplement quels sont ses constructeurs appelés):

class Queue
{
public:
  void push1(const A & a)
  {
    _deque.push_back(a);
  }

  void push2(A a)
  {
    _deque.push_back(std::move(a));
  }
  
private:
  std::deque<A> _deque;
};

Voyons ce que cela donne dans le cas général:

Queue q;
A a;
q.push1(a);

affiche

A::A()
A::A(const A &)

Alors que

Queue q;
A a;
q.push2(a);

affiche

A::A()
A::A(const A &)
A::A(const A &&)

C'est à peine pire si l'on part du principe qu'un constructeur move n'est pas cher. Mais maintenant, regardons dans le cas où le paramètre peut être déplacé:

Queue q;
q.push1(A());

affiche

A::A()
A::A(const A &)

ce qui n'est pas pire, mais

Queue q;  
q.push2(A());

affiche

A::A()
A::A(const A &&)

et là, c'est nettement mieux! L'on évite complètement la copie, et l'on déplace simplement l'objet jusqu'à la queue. Notez que

Queue q;
A a;
q.push2(std::move(a));

affiche

A::A()
A::A(const A &&)
A::A(const A &&)

En effet, le standard autorise le compilo à transformer un passage par copie en un move.

Je suis un tout petit peu ennuyé par cette nouvelle approche. En effet, la règle jusqu'ici était, passe par référence si tu peux, et par autre chose si tu dois. Et maintenant, il va falloir choisir entre un passage par référence et un passage par copie en fonction de ce que la fonction va faire avec le paramètre, ce qui me donne l'impression de casser l'encapsulation. Mais économiser des copies est plaisant.

Les labels du blog sont cassés!

Ou plus exactement, le label C++. D'après les forums, tout le monde a le même problème: cliquer sur un label contenant le caractère '+' ne retourne aucun article. En revanche, le compte du nombre d'articles fonctionne...

Ça fait des mois que ça dure. Espérons que Google nous corrige ça bientôt.