La version stable de Rust 1.28 est désormais disponible !
Allocateur(s) et optimisation de la mémoire
Rust est un langage de programmation système axé sur la sécurité, la rapidité et la concurrence.
Pour mettre à jour votre version stable, il suffit d’exécuter la commande habituelle.
$ rustup update stable
Si vous ne disposez pas de rustup, vous pouvez en obtenir une copie sur la page de téléchargement du site officiel. N’hésitez pas également à consulter la release note de la 1.28 sur GitHub !
Quoi de neuf ?
Les événements passés, d’une contre-attaque ( :evil: !) matée, laissent désormais place à une nouvelle version majeure de Rust s’axant principalement sur la mémoire, autant sur sa gestion directe (optimisation de certains comportements que nous verrons plus bas) qu’indirecte (manipulation d’outils/services proposés permettant d’adapter cette gestion en fonction des besoins).
Allons-y !
Personnalisation de l'allocateur global
Si vous n’avez qu’une vague idée de ce à quoi, structurellement, un allocateur mémoire pourrait ressembler, en voici un résumé:
Il existe au moins deux "types" d’allocateurs:
jemalloc
Actuellement utilisé par le projet Rust, il propose des outils dédiés à l’analyse des performances. Par exemple, cet allocateur ne dénature (ou ne supprime) pas l’implémentation de malloc mais l’améliore pour en obtenir des résultats plus intéressants.
Intégration à Rust
Avec la venue de la 1.28, il est désormais possible de choisir l’allocateur à la compilation. Notez que, pour la plupart des OS, l’allocateur choisi par rust est jemalloc et peut être remplacé par l’allocateur du système grâce à la structure std::alloc::System ainsi qu’à l’attribut #.
use std::alloc::System;
#
static GLOBAL: System = System;
fn main() {
let mut v = Vec::new();
// Cette allocation sera effectuée
// par l'allocateur du système d'exploitation
// et non jemalloc.
v.push(1);
}
Pour diverses raisons, vous pourriez également avoir besoin d’utiliser un allocateur fait-maison pour combler les besoins d’une situation délicate (notamment dans le cas où votre programme est très gourmand en RAM sur le long terme, effectuant de très nombreuses petites allocations et ralentissant alors le fonctionnement de l’implémentation classique de malloc). La bibliothèque standard propose le trait GlobalAlloc pour fournir les services nécessaires à la bonne utilisation de l’allocateur et permettre son enregistrement en tant qu’allocateur global lors l’exécution.
Amélioration de la formulation des erreurs de formatage
Cas très spécifique pour cette révision, puisqu’elle consiste à améliorer l’intelligibilité du diagnostic fourni par le compilateur lorsque l’utilisateur soumet un nom d’argument invalide dans son modèle de formatage.
A titre informatif, le formatage d’une chaîne de caractères en Rust par le biais d’arguments positionnels nommés (et non indexés) se déroule comme suit:
println!("{bar}{foo}", foo = ", world!", bar = "Hello")
foo et bar ne sont pas initialisés au préalable; l’ordre d’initialisation n’est pas important.
Cependant, les identificateurs utilisés pour le formatage ne peuvent pas être préfixés par un underscore (_) et le compilateur nous renvoyait jusqu’ici un message assez peu… compréhensible.
format!("{_foo}", _foo = 6usize);
error: invalid format string: expected `'}'`, found `'_'`
|
2 | format!("{_foo}", _foo = 6usize);
| ^^^^^^^^
Si nous analysons le message "tel quel", on remarque que le compilateur reste plutôt évasif. Le problème d’exhaustivité tend à se régler dans cette nouvelle version grâce à un message d’erreur spécifique à ce cas.
error: invalid format string: invalid argument name `_foo`
|
2 | let _ = format!("{_foo}", _foo = 6usize);
| ^^^^ invalid argument name in format string
|
= note: argument names cannot start with an underscore
Mieux ! :)
Optimisation des types numériques non signés
Une nouvelle collection de wrappers, censés représenter des entiers non signés et non nuls, pointe le bout de son nez pour amorcer une optimisation ciblant la mémoire consommée par les enums. Le cas le plus pertinent reste le stockage d’un entier non signé dans un conteneur Option
assert_eq!(std::mem::size_of::
assert_eq!(std::mem::size_of::
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.