Folly : la bibliothèque C++ open-source de Facebook
Une initiative pour partager les outils utilisés en interne

Le , par Klaim

0PARTAGES

8  0 
Folly : la bibliothèque C++ open-source de Facebook
Une initiative pour partager les outils utilisés en interne

Herb Sutter, l'expert reconnu du langage C++, encense dans son dernier billet de blog l'initiative de Facebook qui vient tout juste de publier en open-source sa bibliothèque d'utilités : Folly.

Cette bibliothèque contient tout un tas d'algorithmes et de structures utilisés dans le code de Facebook. L'essentiel des fonctionnalités couvre les problèmes de performances ou d'absence d'implémentations trouvés dans les bibliothèques déjà existantes comme Boost ou la bibliothèque standard.

De plus en plus d'entreprises mettent leur code source à disposition de tous et permettent de compléter les fonctionnalités fournies par les bibliothèques C++ disponibles. Certaines ont pour but d'être intégrées dans la bibliothèque standard C++, dans le but de corriger ce qui semble être pour Herb Sutter le problème majeur du C++ : le manque d'outils disponibles de façon standard.

Dépôt GitHub de Folly : https://github.com/facebook/folly.

Et vous :
Que pensez-vous de cette initiative de Facebook ?
Pensez-vous pouvoir utiliser cette bibliothèque dans vos propres projets ?

Sources :

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de Arzar
Membre émérite https://www.developpez.com
Le 04/06/2012 à 1:12
Je viens de jeter en œil aux sources et il y a en effet beaucoup de choses intéressantes. Alors attention, il ne faut pas s'attendre à des bibliothèques de haut niveau genre XML, base de donnée ou réseau. Cela reste avant tout une collection de petits composants d'usage général. La majorité de ces composants sont en fait des structures de données orientées multithreading.

Extrait du readme de Folly :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#### `Arena.h`, `ThreadCachedArena.h`
Simple arena for memory allocation: multiple allocations get freed all
at once. With threaded version.
#### [`AtomicHashMap.h`, `AtomicHashArray.h`](AtomicHashMap.md)
High-performance atomic hash map with almost lock-free operation.
#### [`Benchmark.h`](Benchmark.md)
A small framework for benchmarking code. Client code registers
benchmarks, optionally with an argument that dictates the scale of the
benchmark (iterations, working set size etc). The framework runs
benchmarks (subject to a command-line flag) and produces formatted
output with timing information.
#### `Bits.h`
Various bit manipulation utilities optimized for speed.
#### `Bits.h`
Bit-twiddling functions that wrap the
[ffsl(l)](http://linux.die.net/man/3/ffsll) primitives in a uniform
interface.
#### `ConcurrentSkipList.h`
An implementation of the structure described in [A Provably Correct
Scalable Concurrent Skip
List](http://www.cs.tau.ac.il/~shanir/nir-...DIS2006-BA.pdf)
by Herlihy et al.
#### [`Conv.h`](Conv.md)
A variety of data conversion routines (notably to and from string),
optimized for speed and safety.
#### `DiscriminatedPtr.h`
Similar to `boost::variant`, but restricted to pointers only. Uses the
highest-order unused 16 bits in a pointer as discriminator. So
`sizeof(DiscriminatedPtr<int, string, Widget>) == sizeof(void*)`.
#### [`dynamic.h`](Dynamic.md)
Dynamically-typed object, created with JSON objects in mind.
#### `Endian.h`
Endian conversion primitives.
####`Escape.h`
Escapes a string in C style.
####`eventfd.h`
Wrapper around the
[`eventfd`](http://www.kernel.org/doc/man-pages/...eventfd.2.html)
system call.
####[`FBString.h`](FBString.md)
A drop-in implementation of `std::string` with a variety of optimizations.
####[`FBVector.h`](FBVector.md)
A mostly drop-in implementation of `std::vector` with a variety of
optimizations.
####`Foreach.h`
Pseudo-statements (implemented as macros) for iteration.
####[`Format.h`](Format.md)
Python-style formatting utilities.
####[`GroupVarint.h`](GroupVarint.md)
[Group Varint
encoding](http://www.ir.uwaterloo.ca/book/adde...mpression.html)
for 32-bit values.
####`Hash.h`
Various popular hash function implementations.
####[`Histogram.h`](Histogram.md)
A simple class for collecting histogram data.
####`IntrusiveList.h`
Convenience type definitions for using `boost::intrusive_list`.
####`json.h`
JSON serializer and deserializer. Uses `dynamic.h`.
####`Likely.h`
Wrappers around [`__builtin_expect`](http://gcc.gnu.org/onlinedocs/gcc/Ot...-Builtins.html).
####`Malloc.h`
Memory allocation helpers, particularly when using jemalloc.
####`MapUtil.h`
Helpers for finding items in associative containers (such as
`std::map` and `std::unordered_map`).
####[`PackedSyncPtr.h`](PackedSyncPtr.md)
A highly specialized data structure consisting of a pointer, a 1-bit
spin lock, and a 15-bit integral, all inside one 64-bit word.
####`Preprocessor.h`
Necessarily evil stuff.
####`PrettyPrint.h`
Pretty-printer for numbers that appends suffixes of unit used: bytes
(kb, MB, ...), metric suffixes (k, M, G, ...), and time (s, ms, us,
ns, ...).
####[`ProducerConsumerQueue.h`](ProducerConsumerQueue.md)
Lock free single-reader, single-writer queue.
####`Random.h`
Defines only one function---`randomNumberSeed()`.
####`Range.h`
Boost-style range facility and the `StringPiece` specialization.
####`RWSpinLock.h`
Fast and compact reader-writer spin lock.
####`ScopeGuard.h`
C++11 incarnation of the old [ScopeGuard](http://drdobbs.com/184403758) idiom.
####[`SmallLocks.h`](SmallLocks.md)
Very small spin locks (1 byte and 1 bit).
####`small_vector.h`
Vector with the small buffer optimization and an ptional embedded
`PicoSpinLock`.
####`sorted_vector_types.h`
Collections similar to `std::map` but implemented as sorted vectors.
####`StlAllocator.h`
STL allocator wrapping a simple allocate/deallocate interface.
####`String.h`
String utilities that connect `folly::fbstring` with `std::string`.
####[`Synchronized.h`](Synchronized.md)
High-level synchronization library.
####`System.h`
Demangling and errno utilities.
####[`ThreadCachedInt.h`](ThreadCachedInt.md)
High-performance atomic increment using thread caching.
####[`ThreadLocal.h`](ThreadLocal.md)
Improved thread local storage for non-trivial types.
####`TimeoutQueue.h`
Queue with per-item timeout.
####`Traits.h`
Type traits that complement those defined in the standard C++11 header
`<traits>`.
####`Unicode.h`
Defines the `codePointToUtf8` function.
Petite remarque, à la lecture du code j'ai été très étonné de voir que Folly propose du C++ résolument moderne.

Par comparaison, tous les autres gros projets open source (de ma connaissance) en C++ et suffisamment massifs pour avoir eux aussi ce genre de brique de base bien fournies (par exemple llvm/clang ou chromium) ont des contraintes fortes forçant une approche assez conservative, du genre :
- Pas d'exception
- C++03 uniquement, souvent en bannissant certains aspects du langage pour être accepté par le plus grand nombre de compilateurs.
- Pas de bibliothèque tierce.

Du coup c'est assez fascinant de voir que Folly, qui si je comprends bien est la brique de base sur laquelle s’appuie tout le reste du code C++ chez Facebook, au contraire :
- Utilise les exceptions.
- Utilise extensivement le C++11. Il faut d'ailleurs au minimum gcc 4.6 pour compiler le code, vu l'utilisation régulière de feature comme les variadic template ou rvalue reference.
- Utilise extensivement boost.
5  0 
Avatar de JolyLoic
Rédacteur/Modérateur https://www.developpez.com
Le 04/06/2012 à 18:46
Posté sur la mailing list de boost :
https://www.facebook.com/notes/faceb...50864656793920

I'm Tudor, one of the folly developers. I'll try to answer your questions
or poke the appropriate people

Re: "NO EXCEPTIONS" in the README -- the README file was intended for
internal Facebook contributors (hence stray references to internal paths),
and "NO EXCEPTIONS" referred to "no exceptions to the rules above", NOT "no
C++ exceptions". Will fix / clarify / remove soon.

-Tudor.
Donc les exceptions C++ sont autorisées !

Remarque @Klaim : Dans http://programmers.stackexchange.com.../113481#113481 je ne suis pas d'accord avec toute une série d'arguments qui vont tous dans le sens : De toute façon, une exception, c'est juste des infos de crash plus jolies, mais nous, on n'a pas le droit de crasher (et on a des environnements qui nous permettent de ne pas le faire). C'est typiquement l'argument contre une fonctionnalité de quelqu'un qui ne l'a pas utilisée pour de vrai. Une exception n'est pas un crash. C'est un mécanisme de remontées d'erreurs comme un autre, qui comme un autre peut conduire au traitement silencieux de celles-ci, ou à la fin du programme, ou à un tas d'intermédiaires, mais uniquement selon le code de gestion des erreurs, qui lui est indépendant de la technique de remontée utilisée.

Je ne nie pas l’argument performances (ni ne l'admets, je n'ai juste pas assez d'infos là dessus). Mais j'accepterais que les jeux n'ont aucun intérêt à utiliser un mécanisme d'exception le jour où on me justifiera que les jeux n'ont pas non plus de mécanisme de code de retour de fonction indiquant si la fonction s'est finie avec succès ou pas.
4  0 
Avatar de Freem
Membre émérite https://www.developpez.com
Le 06/06/2012 à 12:48
La consommation en ressources du traitement des exceptions varie selon le compilateur, donc il est difficile d'affirmer de façon catégorique que ça pèse vraiment lourd.
Et, naturellement, j'ai ici parlé de ressources de façon générale.
Selon mes lectures en survol à ce sujet, il y a grosso modo deux stratégies pour les gérer:
_ augmenter la taille du code
_ augmenter les traitements processeur

Avec GCC, selon la doc, une exception n'a un coût que si elle est lancée, mais le binaire augmente un peu.
Honnêtement... J'aime beaucoup l'optimisation, mais je préfère un programme qui ne crash pas, et qui ne contiens pas de memory leak.
Donc, j'aime bien les contrôles d'erreur.
Si on veut me dire que les exceptions consomment, je veux voir un comparatif, entre un source C et un C++, ou chaque fonction du C retourne un code erreur, et ou celui-ci est systématiquement vérifié.
Ca inclut printf/scanf, naturellement...

Si il s'avère que le binaire C résultant d'un tel code est plus rapide, plus petit en RAM, plus petit sur le disque, et plus lisible, alors je serai conquis. (En fait, même juste la moitié de ces arguments commencerait à me faire réfléchir... mais bon, je doute qu'un code sans exception vérifie toutes les conditions d'erreurs. Déjà qu'avec les exceptions ce n'est pas toujours le cas...)

Sauf que:
_ coller des if partout dans le code augmente la taille du binaire, même si ce ne sont que 3 octets par occurrence pour un short jump (selon mes souvenirs d'asm)
_ coller des if partout dans le code implique des vérifications. Et chaque vérification consomme du temps processeur. J'imagine une fonction récursive qui à été appelée 50 fois... et j'ai un sérieux doute quand à la légèreté des vérifs de retour d'erreur classique.
_ "accessoirement" mélanger le code de traitement d'erreur avec le code d'exécution normal, ça rend le code illisible.

Bon, après, c'est vrai aussi, il semble qu'il est possible de bricoler un système pas trop mal en C avec signal.h et les longjump, mais je n'en ai pas encore vu, moi.
Je pense que les exceptions, c'est un peu comme l'orienté objet: quelque chose dont tout le monde parle mais qui est moins répandu qu'on ne voudrait le croire.
En tout cas, je n'en ai pas vu à mon taf actuel, ni sur les 2-3 projets open source que j'ai osé vouloir lire. (Ni l'un ni l'autre d'ailleurs: ni exceptions, ni conception orientée objet, alors que les langages le permettent...)
4  0 
Avatar de Luc Hermitte
Expert éminent sénior https://www.developpez.com
Le 06/06/2012 à 16:50
Ouais enfin. Il y a erreur alors.
Si le code peut utiliser des assert plutôt que des if dans tous les sens, cela signifie que les éventuelles erreurs trouvées sont des erreurs de programmation et non de problèmes dans le contexte de l'exécution (comme une connexion réseau à internet perdue).

Les exceptions n'ont pas leur place. Pas plus que les if. C'est des assertions qu'il faut, et le débat exception ou pas n'a pas lieu d'être pour ces "erreurs là".
4  0 
Avatar de Luc Hermitte
Expert éminent sénior https://www.developpez.com
Le 07/06/2012 à 19:43
Citation Envoyé par Klaim Voir le message
Oui mais la encore il y a subtilité.

Quel est l'effet d'une assertion? Log + crash souvent.

Mais pour un jeu ça peut etre problématique. Une série d'assertions peuvent donner plus d'indices sur l'ampleur d'un probleme qu'une seule assertion qui fait tout crasher.

Du coup beaucoup d'assertions sont implémentées pour logger et etre evaluable optionellement, pour quand meme generer du code dans le cas ou l'assertion ne passe pas OU pour crasher OU pour lancer une exception.
En plus les assertions sont rarement gardées dans le code d'un jeu, ils sont utilisés seulement dans des versions "debug" ou "release debug" du jeu, pour des soucis de performances.

[...]

Enfin bref, ce que je veux dire c'est que comprendre l'ampleur et du sujet mais aussi comprendre que les termes employés ont tendance à englober trop de choses qui ne sont pas forcément sous entendues par toutes les parties de la discussion, fait que les discussions tournent rapidement steriles sur le sujet...
Il y a un truc qui me perturbe dans ta réaction à mon intervention.
Et je crois que j'ai enfin trouvé : une assertion en phase de dév va non seulement crasher, mais aussi et surtout provoquer un core dump (man ulimit pour ceux sous *nix qui n'ont pas de core générés).
Et un fichier core, c'est juste royal car la pile d'appel (sur tous les threads) est stockée au moment du crash.
Nul besoin d'avoir une série de logs quand on dispose d'un état complet du programme au moment du plantage (et donc l'état de toutes les variables qui étaient encore en train de vivre).

Il n'y a de fait pour moi aucune subtilité.
- erreur de prog -> assertions => core dump => état complet (au détail des optims faites à notre insu et de certaines résolutions de meta-prog template) au moment du plantage.
- erreur dans le contexte (très bien explicité par Freem) -> 110000 ifs, ou des exceptions. Et ça, ce n'est pas désactivable dans le produit final.
Et ici même la question initiale se pose : "if ou exception?" ; "Quel est le mécanisme qui coute le moins cher -- quand non buggué -- sur la plateforme ciblée ?"
(et effectivement, deux des articles traduits (/en cours de) couvrent ce sujet)

Maintenant si les consoles ne peuvent pas générer de fichiers core (ou équivalent), je comprends que la situation soit pourrie et que vous deviez pervertir le fonctionnement des assertions pour tracer des choses comme la pile d'appel. Car je suis d'accord, un crash sans fichier core, cela n'apporte rien.

(oui on peut forker la discussion)

Reste le sujet connexe de la programmation défensive qui n'a pas encore été proprement abordé.
2  0 
Avatar de Ekleog
Membre éclairé https://www.developpez.com
Le 06/06/2012 à 11:39
Sauf que, comme le fait remarquer un des articles qui est en traduction (je crois), les exceptions sont souvent moins gourmandes en ressources que l'utilisation d'un code de retour. En tout cas, tant qu'elles restent exceptionnelles, bien sûr. Mais, si il y a autant d'erreurs que de retours normaux, est-ce toujours une erreur ?
1  0 
Avatar de Klaim
Membre expert https://www.developpez.com
Le 06/06/2012 à 14:49
Ce que beaucoup oublient avec l'argument des ifs a la place des exceptions, c'est que le choix de ne pas utiliser d'exceptions n'implique pas que l'on va checker les erreurs. C'est ce qui se passe dans beaucoup de jeux vidéos: on met beaucoup beaucoup d'assertions pour crasher le plus vite possible pendant le développement ou au moins logger et puis continuer, mais une fois que le jeu est suffisamment prêt on vire tout et il n'y a aucune vérification d'erreur. Une des raisons qui rends cela possible est tout simplement qu'un jeu console n'a que des inputs fixes et prévisibles, du coup il est possible de se retrouver, après beaucoup de travail, avec un jeu qui
tourne "parfaitement" sans aucune vérification du tout.

Cela étant dis, hors du contexte d'un jeu console, pour une console des anciennes générations du moins, cet argument ne tiens plus.

Pour le point sur l'activation des exceptions: en théorie on est censé ne pas payer si il n'y a aucun throw de fait. Dans la pratique on paye mémé dans ce cas. Par contre, aujourd’hui sur la plupart des plateformes (mais pas sur console ou sur la plupart des systèmes embarques, pas les smartphones) le cout est très faible donc ça va encore. Sur certaines consoles comme la DS le simple fait qu'il n'y ai que 4mo de mémoire virtuelle "normale" a laquelle on doit imputer la taille de l’exécutable fais que le coût du mécanisme d'exception en terme de taille d’exécutable n'est pas du tout acceptable. Je ne sais pas pour la 3ds qui a sacrement beaucoup plus de mémoire, mais j’imagine qu'il y a des contraintes similaires parce que c'est pas non plus un pc ou même un smartphone.
1  0 
Avatar de Freem
Membre émérite https://www.developpez.com
Le 07/06/2012 à 11:30
Citation Envoyé par Ekleog Voir le message

=> ?
Là, je ne comprense pas.
C'est de l'humour, peut-être ?
Non, je me suis juste mal exprimé... je pensais aux contrôle d'erreur au sens large du terme, c'est à dire que je pense que mettre un saut classique vaut toujours mieux que rien, même si je préfère les exceptions au sauts classiques.

Citation Envoyé par Klaim Voir le message

Cela étant dis, hors du contexte d'un jeu console, pour une console des anciennes générations du moins, cet argument ne tiens plus.
Reste à définir le terme ancienne génération, alors, je suppose.
Effectivement, dans le cas d'un environnement maîtrisé à 100%, les exceptions n'ont pas lieu d'être. Mais maîtrisé à 100% implique 0 connectivité au monde extérieur.
Je n'ai jamais été un "consoleux" mais il me semble que la DS permet le multi-joueur en connectant plusieurs consoles, non?
De ce fait, il y a un réseau qui se crée...
Sinon, il y a aussi l'option ou le dev ne fait pas d'allocation dynamique, et que du coup, il n'y a pas de risque de buffer overflow. Sinon, risque d'explosion, encore une fois.
Cela dis, pour tempérer mes propos, j'ajouterai qu'en plus de ne jamais jouer sur console que chez quelques potes, je n'ai jamais non plus développé de jeux pour console (et de façon générale, un part un casse-brique en basic sur ma TI82 au lycées, pas vraiment fait de jeux... et clairement l'environnement était contrôlé à 95% sur TI - restait le dépassement de capacité a éviter lors des copies de matrices qui représentaient les niveaux/sauvegardes mais je n'avais de toute façon aucune façon de les gérer - )


Pour le point sur l'activation des exceptions: en théorie on est censé ne pas payer si il n'y a aucun throw de fait. Dans la pratique on paye mémé dans ce cas.
Ma mémé a plus de sous que moi, c'est p'tet pour ça
Blague à part (c'était juste pour me dérider en ce jeudi au temps pourri) il y a ce thread sur SO:
http://stackoverflow.com/questions/6...n-handling-add

Et les 2 premiers posts, avec leurs scores semblent montrer que globalement, le surcoût des exception est négligeable, tant au niveau de la taille du binaire que de l'exécution.

Citation Envoyé par Klaim Voir le message
Oui mais la encore il y a subtilité.
Quel est l'effet d'une assertion? Log + crash souvent.
C'est aussi ainsi que les profs que j'ai eus me décrivaient le rôle d'une exception. Le but du jeu n'était pas que le programme survive, selon leurs explications, juste que le dev ait un rapport de bug plus complet limite... En même temps, on ne les as que survolées (et il n'a jamais été précisé que printf/scranf ont des valeurs de retours)...
La ou j'ai commencé à comprendre leur rôle, c'est le jour ou je suis tombé sur un document traitant de l' "exception safety" de Boost.

Citation Envoyé par Klaim Voir le message
Enfin bref, ce que je veux dire c'est que comprendre l'ampleur et du sujet mais aussi comprendre que les termes employés ont tendance à englober trop de choses qui ne sont pas forcément sous entendues par toutes les parties de la discussion, fait que les discussions tournent rapidement steriles sur le sujet...
C'est sûr.
Personnellement, quand je pense aux assertions, je pense à "assert()".
Du coup, c'est automatiquement supprimé quand je passe en mode release.
Depuis C++11, je devrais aussi penser à "static_assert()" (ou un truc du genre) qui permet juste une vérification par le compilo, et n'a donc aucune influence dans le binaire.
Donc, du code censé contrôler les problème de code, les bugs introduits par le dev.

Ah, c'est vrai, on pourrait aussi penser aux exceptions "std::logic_error" mais je ne sais pas quels sont leurs rôles et cas d'utilisations, donc j'ai tendance à ne pas y penser.
Surtout qu'en général, en cas d'erreur de logique, ça me mène au crash peu après
Donc je vois plus les exceptions, et contrôles d'erreurs en if, comme un moyen de prévenir et traiter les évènements sur lesquels on a aucune prise lors de la programmation:
_ mémoire insuffisante pour traiter une opération
_ rupture de réseau
_ fichier d'entrée corrompu
_ saisie utilisateur foireuse (genre il entre un texte dans un champ où on lui demande de mettre un nombre, et la conversion foire en lançant une exception)

Citation Envoyé par Klaim Voir le message

(je sens qu'on a completement change de sujet au passage).
En effet

PS: ta démo pourrait devenir un jeu d'arcade relativement fun
1  0 
Avatar de Errata
Membre régulier https://www.developpez.com
Le 04/06/2012 à 11:41
Du coup c'est assez fascinant de voir que Folly, qui si je comprends bien est la brique de base sur laquelle s’appuie tout le reste du code C++ chez Facebook
Le code a la marque d'Andrei Alexandrescu, qui est le guru C++ chez facebook.
Un code de qualité, dont certain bout de code mériterais d’être envisager pour s’intégrer dans la lib standard (je pense au JSON serializer/deserializer, et aux container thread-safe, fonction de hash).
0  0 
Avatar de David_g
Membre éclairé https://www.developpez.com
Le 04/06/2012 à 11:53
Je me demande si HipHop peut utiliser aussi cette bibliothèque.
0  0 
Contacter le responsable de la rubrique Accueil

Partenaire : Hébergement Web