Section courante

A propos

Section administrative du site

 Langage  Elément  Tutoriel  Aide 
ABAP/4
Ada
Assembleur
Assembly & bytecode
ASP (Active Server Pages)
Basic
C
C++
C# (C Sharp)
Cobol
ColdFusion
Fortran
HTML
Java
JavaScript
LISP
Logo
LotusScript
Oberon
Pascal
Perl
PHP
PL/1
Prolog
Python
Rebol
REXX
Ruby
Rust
SAS
NoSQL
SQL
Swift
X++ (Axapta)
GNAT
SMALLAda
VHDL
Assembleur 370
Assembleur 1802
Assembleur 4004
Assembleur 6502
Assembleur 6800
Assembleur 68000
Assembleur 8080 et 8085
Assembleur 8089
Assembleur 80x86
Assembleur AGC4
Assembleur ARM
Assembleur DPS 8000
Assembleur i860
Assembleur Itanium
Assembleur MIPS
Assembleur PDP-11
Assembleur PowerPC
Assembleur RISC-V
Assembleur SPARC
Assembleur SuperH
Assembleur UNIVAC I
Assembleur VAX
Assembleur Z80
Assembleur Z8000
Assembleur z/Architecture
ASSEMBLER/MONITOR 64
Micol Assembler
GFA Assembler
A86
MASM (Macro Assembler)
TASM (Turbo Assembler)
CIL
Jasmin
LLVM
MSIL
Parrot
P-Code (PCode)
SWEET16
G-Pascal
ASP 1.0
ASP 2.0
ASP 3.0
ASP.NET
ASP.NET Core
ABasiC (Amiga)
Adam SmartBASIC
Altair BASIC
AmigaBASIC (Amiga)
AMOS Basic (Amiga)
Atari Basic (Atari 400, 600 XL, 800, 800XL)
Basic Apple II (Integer BASIC/APPLESOFT)
Basic Commodore 64 (CBM-BASIC)
Basic Commodore 128 (BASIC 7.0)
Basic Commodore VIC-20 (CBM-BASIC 2.0)
Basic Coco 1 (Color Basic)
Basic Coco 2 (Extended Color Basic)
Basic Coco 3 (Extended Color Basic 2.0)
BASICA (PC DOS)
Basic Pro
BBC BASIC
Blitz BASIC (Amiga)
DarkBASIC
Dartmouth BASIC
GFA-Basic (Atari ST/Amiga)
GWBASIC (MS-DOS)
Liberty BASIC
Locomotive BASIC (Amstrad CPC)
MSX-Basic
Omikron Basic (Atari ST)
Oric Extended Basic
Power Basic
Quick Basic/QBasic (MS-DOS)
Sinclair BASIC (ZX80, ZX81, ZX Spectrum)
ST BASIC (Atari ST)
Turbo Basic
Vintage BASIC
VBScript
Visual Basic (VB)
Visual Basic .NET (VB .NET)
Visual Basic pour DOS
Yabasic
BeckerBASIC
SIMONS' BASIC
Basic09 d'OS-9
Disk Extended Color Basic
Basic09 d'OS-9
Disk Extended Color Basic
Access
Excel
Visual Basic pour Windows
Visual Basic .NET pour Windows
C Shell Unix (csh)
C pour Amiga
C pour Atari ST
C pour DOS
C pour Falcon030
C pour GEMDOS (Atari ST)
C pour Linux
C pour PowerTV OS
C pour OS/2
C pour Unix
C pour Windows
Aztec C
CoCo-C
GNU C
HiSoft C
IBM C/2
Introl-C
Lattice C
Microsoft C
MinGW C
MSX-C
Open Watcom C
OS-9 C Compiler
Pure C
Quick C
Turbo C
HiSoft C for Atari ST
HiSoft C for CP/M (Amstrad CPC)
C++ pour OS/2
C++ pour Windows
Borland C++
C++Builder
IBM VisualAge C++
Intel C++
MinGW C++
Open Watcom C++
Symantec C++
Turbo C++
Visual C++
Visual C++ .NET
Watcom C++
Zortech C++
C# (C Sharp) pour Windows
Apple III Cobol
Microsoft Cobol
BlueDragon
Lucee
OpenBD
Railo
Smith Project
Microsoft Fortran
WATFOR-77
CSS
FBML
Open Graph
SVG
XML
XSL/XSLT
LESS
SASS
GCJ (GNU)
JSP
Jython
Visual J++
Node.js
TypeScript
AutoLISP
ACSLogo
LotusScript pour Windows
Amiga Oberon
Oberon .NET
Apple Pascal
Delphi/Kylix/Lazarus
Free Pascal
GNU Pascal
HighSpeed Pascal
IBM Personal Computer Pascal
Lisa Pascal
Maxon Pascal
MPW Pascal
OS-9 Pascal
OSS Personal Pascal
Pascal-86
Pascal du Cray Research
Pascal/VS
Pascal-XT
PURE Pascal
QuickPascal
RemObjets Chrome
Sun Pascal
THINK Pascal
Tiny Pascal (TRS-80)
Turbo Pascal
UCSD Pascal
VAX Pascal
Virtual Pascal
Turbo Pascal for CP/M-80
Turbo Pascal for DOS
Turbo Pascal for Macintosh
Turbo Pascal for Windows
CodeIgniter (Cadre d'application)
Drupal (Projet)
Joomla! (Projet)
Phalanger (PHP .NET)
phpBB (Projet)
Smarty (balise)
Twig (balise)
Symfony (Cadre d'application)
WordPress (Projet)
Zend (Cadre d'application)
PL360
PL/M-80
PL/M-86
Turbo Prolog
CPython
IronPython
Jython
PyPy
AREXX
Regina REXX
JMP
Btrieve
Cassandra
Clipper
CouchDB
dBASE
Hbase
Hypertable
MongoDB
Redis
Access
BigQuery
DB2
H2
Interbase
MySQL
Oracle
PostgreSQL
SAP HANA
SQL Server
Sybase
U-SQL
Introduction
Configuration de l'environnement de développement
Fabriquer le LibSass
Profilage de LibSass
Utilisation de l'API
LibSass et Unicode
Composantes internes de SourceMap
Allocateur de mémoire personnalisé
Implémentation du pointeur intelligent LibSass
Les plugiciels
Compilation avec des fichiers makefiles
Compilation avec autotools
Compilation de LibSass avec MinGW (makefiles)
Compilation de LibSass avec Visual Studio
Compilation sur Mac OS X
Création d'une bibliothèque système partagée
Ebuilds pour Gentoo Linux
Contexte Sass
Valeur Sass
Fonction Sass
Importateur Sass
Exemple de code pour le contexte Sass
Contexte Sass interne
Exemple de code pour la valeur Sass
Valeur Sass interne
Exemple de code pour la fonction Sass
Fonction Sass interne
Exemple de code pour l'importateur Sass
Importateur Sass interne
Préface
Notes légales
Dictionnaire
Recherche

Allocateur de mémoire personnalisé

LibSass est livré avec un allocateur de mémoire personnalisé pour améliorer les performances. Initialement inclus dans LibSass 3.6, il est actuellement désactivé par défaut. Son activation est requise via la définition de SASS_CUSTOM_ALLOCATOR.

Présentation

L'allocateur est un allocateur de pool/arène surmonté d'une liste libre. Le modèle d'utilisation de la mémoire de LibSass est parfaitement adapté à cette implémentation. Chaque compilation tend à accumuler de la mémoire et à ne libérer que certains éléments de temps à autre, mais la consommation globale de mémoire augmente généralement jusqu'à la fin de la compilation. Cela nous permet de simplifier l'implémentation au maximum, car nous n'avons pas besoin de libérer beaucoup de mémoire au système et pouvons la réutiliser.

Arènes

Chaque arène est allouée selon une taille fixe (à la compilation). Chaque requête d'allocation est traitée depuis l'arène actuelle. Ils découpe l'arène en blocs de différentes tailles. Les arènes ne sont jamais restituées au système tant que la compilation n'est pas terminée.

Tranches

Une tranche de mémoire est une partie d'une arène. Lorsque le système demande un bloc de mémoire dimensionné, ils vérifient si l'arène actuelle dispose de suffisamment d'espace pour le contenir. Dans le cas contraire, une nouvelle arène est allouée. Nous renvoyons ensuite un pointeur vers cette arène et marquons l'espace comme utilisé. Chaque tranche possède également un en-tête invisible pour le demandeur, car il précède l'adresse du pointeur renvoyée. Cet entête est utilisé à des fins de comptabilité.

Listes libres (ou compartiments)

Une fois qu'une tranche de mémoire est renvoyée à l'allocateur, elle n'est pas libérée. Elle est placée sur la liste libre. Ils conservent un nombre fixe de listes libres, une pour chaque taille de bloc possible. Comme les tailles de bloc sont alignées sur la mémoire, nous pouvons obtenir l'index de la liste libre (ou compartiment) très rapidement (taille/alignement).

Tailles de bloc

Les arènes étant de taille fixe, ils doivent s'assurer que seuls des blocs suffisamment petits en sont servis. Cela simplifie également l'implémentation, car ils pouvent déclarer statiquement certaines structures pour la comptabilité. Les allocations trop importantes pour être suivies dans une liste libre seront directement affectées à malloc et free. C'est le cas lorsque l'index du compartiment est supérieur à SassAllocatorBuckets.

Sécurité des processus légers

Cette implémentation n'est pas thread-safe par conception. La rendre thread-safe serait certainement possible, mais cela aurait un impact (en termes de performances). De plus, cela n'est pas nécessaire compte tenu du modèle d'utilisation de la mémoire de LibSass. Il est donc préférable de s'assurer que les bassins de mémoire sont locaux pour chaque processus léger.

Obstacles à l'implémentation

L'allocation de mémoire étant un élément essentiel du C++, nous nous trouvons confrontés à plusieurs difficultés. Cela s'est particulièrement avéré pour l'initialisation et l'ordre de destruction des variables statiques. Par exemple, lorsqu'une chaîne statique possède un allocateur personnalisé, il se peut qu'elle soit initialisée avant le bassin de mémoire local du processus léger. D'un autre côté, il est également possible que le bassin de mémoire soit détruit avant qu'une autre chaîne statique ne veuille lui restituer sa mémoire. J'ai essayé de contourner ces problèmes, principalement en utilisant uniquement des objets POD (plain old data) locaux.

Gains de performances

Les tests indiquent que l'allocateur personnalisé améliore les performances d'environ 15 % pour les cas complexes (ils ont utilisé Bolt-Bench pour le mesurer). Une fois optimisé, l'allocateur personnalisé peut apporter jusqu'à 30 % d'amélioration. Cela représente une faible perte de quelques pourcents d'utilisation mémoire globale. Des ajustements sont possibles, mais le point idéal pour l'instant semble être :

  1. // Combien de compartiments devrait-ils avoir pour la liste libre ?
  2. // Détermine quand les allocations vont directement à malloc/free
  3. // Pour obtenir la taille maximale des éléments gérés, multipliez par l'alignement.
  4. #define SassAllocatorBuckets 512
  5.  
  6. // La taille des arènes du bassin de mémoire en octets.
  7. #define SassAllocatorArenaSize (1024 * 256)

Ces informations se trouvent dans settings.hpp.

Surcharge mémoire

Les paramètres SassAllocatorBuckets et SassAllocatorArenaSize doivent être définis l'un par rapport à l'autre. En supposant que l'alignement mémoire sur la plateforme soit de 8 octets, la taille maximale des blocs pouvant être gérés est de 4 Ko (512 x 8 octets). Si la taille de l'arène est trop proche de cette valeur, vous risquez de laisser beaucoup de RAM inutilisée. Lorsqu'une arène ne peut pas répondre à la requête en cours, elle est mise de côté et une nouvelle est allouée. Nous ne gardons pas trace de l'espace inutilisé des arènes précédentes, car cela surcharge le code et consomme un temps processeur précieux. En définissant les valeurs avec soin, nous pouvons éviter ce coût tout en conservant une surcharge mémoire raisonnable. Dans le pire des cas, la perte est d'environ 1,5 % par rapport aux paramètres par défaut (4 Ko sur 256 Ko).

Améliorations supplémentaires

Il serait intéressant de vérifier s'il est possible de réutiliser l'espace des anciennes arènes sans trop impacter les performances. Ils peuvent également vérifier les listes libres de blocs de plus grande taille pour répondre à une demande d'allocation. Cependant, ces deux éléments devraient être vérifiés pour évaluer l'impact sur les performances et leur gain réel.



PARTAGER CETTE PAGE SUR
Dernière mise à jour : Mardi, le 8 octobre 2024