Calcul multi-cœurs des SHA-1
Pour effectuer les calculs de SHA-1 en parallèle, nous allons utiliser le crate rayon
. Celui-ci fournit notamment des extensions sur les types classiques permettant d'obtenir des itérateurs parallèles qui exploitent automatiquement tous les cœurs de la machine courante.
- Ajoutez
rayon
comme dépendance à votreCargo.toml
. - Dans votre module
hibp
, importez le prélude derayon
qui fournira toutes les fonctions et extensions utiles,rayon::prelude::*
. - Écrivez une fonction
hibp::all_sha1()
qui calcule en parallèle tous les préfixes et suffixes des SHA-1 des comptes passés en paramètre en utilisant la fonctionhibp::sha1()
définie précedemment :
fn all_sha1(accounts: &[Account]) -> Vec<(String, String, &Account)> {
todo!()
}
Dans cette fonction, vous serez probablement amenés à utiliser la méthode d'extension par_iter()
fournie par rayon
en lieu et place de iter()
.
Test des performances
Pour pouvoir comparer les performances avec et sans rayon, nous allons mettre en place le début de l'infrastructure permettant d'ajouter notre nouvelle commande à notre programme principal.
-
Écrivez une fonction publique
hibp::all_sha1_timed()
avec la même signature quehibp::all_sha1()
qui affiche le nombre de micro-secondes écoulées dans cette fonction avant d'en retourner le résultat. Vous pourrez utiliser les typesstd::time::{Instant, Duration}
qui représentent respectivement un point dans le temps (opaque) et une durée, obtenue par exemple en soustrayant deux points dans le temps. Grâce àInstant::now()
vous pouvez capturer la date courante, et avec la méthodeas_micros()
sur une valeur de typeDuration
vous obtiendrez sa durée en microsecondes. -
Dans votre programme principal, ajoutez une sous-commande
hibp
. Celle-ci devra prendre en paramètre obligatoire un fichier. Les comptes seront chargés depuis ce fichier, puishibp::all_sha1_timed()
sera invoquée. On verra donc le temps de calcul des SHA-1. -
Essayez de remplacer
par_iter()
pariter()
et comparez les temps de traitement.
Regroupement des SHA-1 de même préfixe
- Implémentez la fonction
hibp::sha1_by_prefix()
qui à partir des comptes et en utilisant les méthodes précédentes regroupe au sein d'une table de hashage les comptes dont le SHA-1 a le même préfixe et accompagne chaque compte de son suffixe :
fn sha1_by_prefix(accounts: &[Account]) -> HashMap<String, Vec<(String, &Account)>> {
todo!()
}
Par exemple, on prendra l'exemple fictif supposant que :
- Le compte "elba" a comme mot de passe "BWE!y4xj:i" et son SHA-1 est
8E7336BBDBE0B7F31DE9A06B053ECDF5E356A946
. - Le compte "dyanna" a comme mot de passe "NvLK25b+" et son SHA-1 est
EF867658E9572AC965BBDC5212FAE656570DB09B
. - Le compte "tahira" a comme mot de passe "xQS?" et son SHA-1 est
8E7334AB061EAB6673D2C591D6C77CEEE12DE961
.
Dans ce cas, la fonction hibp::sha1_by_prefix()
renverra, en pseudo-notation :
{
"8E733": [
("6BBDBE0B7F31DE9A06B053ECDF5E356A946",
Account { login: "elba", password: "BWE!y4xj:i" }),
("4AB061EAB6673D2C591D6C77CEEE12DE961",
Account { login: "tahira", password: "xQS?" })
],
"EF867": [
("658E9572AC965BBDC5212FAE656570DB09B",
Account { login: "dyanna", password: "NvLK25b+" }),
],
}