Des implémentations typiques de malloc
utilisent brk
/sbrk
comme moyen principal de réclamer la mémoire du système d'exploitation. Cependant, ils utilisent également mmap
pour obtenir des morceaux pour les grandes allocations. Y a-t-il un réel avantage à utiliser brk
au lieu de mmap
, ou est-ce juste la tradition? Cela ne fonctionnerait-il pas aussi bien pour tout faire avec mmap
?
(Remarque: j'utilise sbrk
et brk
interchangeable ici car ils sont interfaces avec le même appel système Linux, brk
.)
Pour référence, voici quelques documents décrivant le glibc malloc
:
Manuel de référence de la bibliothèque GNU C: le GNU Allocator
[.____] https://www.gnu.org/software/libc/manual/html_node/the-gnu-allocator.html
gLIBC WIKI: Vue d'ensemble de Malloc
[.____] https://sourceware.org/glibc/wiki/mallocinterns
Ce que ces documents décrivent est que sbrk
est utilisé pour réclamer une arène principale pour les petites allocations, mmap
est utilisé pour revendiquer des arènes secondaires et mmap
est également utilisé pour réclamer un espace pour gros objets ("beaucoup plus grand qu'une page").
L'utilisation du tas d'application (réclamée avec sbrk
) et mmap
introduit une complexité supplémentaire qui pourrait être inutile:
Arena allouée - L'arène principale utilise le tas de l'application. D'autres arènes utilisent
mmap
'd tas. Pour mapper un morceau sur un tas, vous devez savoir quel cas s'applique. Si ce bit est 0, le morceau provient de l'arène principale et du tas principal. Si ce bit est 1, le morceau provient de la mémoiremmap
D et que l'emplacement du tas peut être calculé à partir de l'adresse du chunk.
[Glibc Malloc est dérivé de ptmalloc
, qui a été dérivé de DLMALLOC , qui a été lancé en 1987.]
Le jemalloc Manpage ( http://jemalloc.net/jemalloc.3.html ) a cela à dire:
Traditionnellement, les allocateurs ont utilisé
sbrk(2)
pour obtenir la mémoire, qui est sous-optimale pour plusieurs raisons, y compris des conditions de race, une fragmentation accrue et des limitations artificielles sur la mémoire utilisable maximale. Sisbrk(2)
est pris en charge par le système d'exploitation, cet allocator utilise à la foismmap(2)
et SBRK (2), dans cet ordre de préférence; Sinon, seulemmap(2)
est utilisée.
Alors, ils disent même ici que sbrk
est sous-optimal, mais ils l'utilisent de toute façon, même s'ils sont déjà allés avoir la peine d'écrire leur code afin que cela fonctionne sans cela.
[L'écriture de Jemalloc a commencé en 2005.]
Mise à jour: en pensant à cela plus, ce bit sur "dans l'ordre de préférence" me donne une ligne sur enquête. Pourquoi l'ordre de préférence? Sont-ils simplement en utilisant sbrk
comme une baisse au cas où mmap
n'est pas pris en charge (ou manque de fonctionnalités nécessaires), ou est-il possible pour le processus d'entrer dans un état où il peut utiliser sbrk
mais pas mmap
? Je vais regarder leur code et voir si je peux comprendre ce que ça fait.
Je demande parce que je suis en train de mettre en œuvre un système de collecte des ordures en C, et je ne vois pas une raison d'utiliser quoi que ce soit d'autre que mmap
. Je me demande s'il y a quelque chose qui me manque cependant.
(Dans mon cas, j'ai une raison supplémentaire d'éviter brk
, qui est que je devrai utiliser malloc
à un moment donné.)
Je ne connais pas les détails sur Linux spécifiquement, mais sur FreeBSD depuis plusieurs années maintenant, MMAP est préférable et JemalLoc de FreeBSD's Libc a complètement handicapé. BRK ()/SBRK () ne sont pas implémentés dans le noyau sur les nouveaux ports vers Aarch64 et RISC-V.
Si je comprends bien l'histoire de Jemalloc correctement, il s'agissait à l'origine du nouvel allocator de Libc de Freebsd avant qu'il a été brisé et fait portable. Maintenant, FreeBSD est un consommateur en aval de Jemalloc. Il est très possible que sa préférence pour MMAP () sur SBAP () est originaire des caractéristiques du système FreeBSD VM Système construit autour de la mise en œuvre de l'interface MMAP.
Il convient de noter que In SUS et POSIX BRK/SBK/SBK/SBK/SBRK doit être considéré comme non portable à ce stade. Si vous travaillez sur un nouvel allocator que vous avez probablement Je ne veux pas en dépendre d'eux.