summaryrefslogtreecommitdiffstats
path: root/openpgp/benches
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2020-03-27 12:47:58 +0100
committerNora Widdecke <nora@sequoia-pgp.org>2021-04-13 12:38:15 +0200
commit1e6c4d8e4aeac6d8673ca2b768d7243940e70d13 (patch)
treef9552f4aa1b5d4a96698f1ba8d0ef53dd37aa98e /openpgp/benches
parent7293e6e9b01e255dc1adde9b7aa8b5666132cbdc (diff)
bench: Add benchmarks for parsing keys.
- Generate a flooded cert before the benchmark is run.
Diffstat (limited to 'openpgp/benches')
-rw-r--r--openpgp/benches/parse_cert.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/openpgp/benches/parse_cert.rs b/openpgp/benches/parse_cert.rs
new file mode 100644
index 00000000..b57b1b01
--- /dev/null
+++ b/openpgp/benches/parse_cert.rs
@@ -0,0 +1,106 @@
+use criterion::{
+ criterion_group, criterion_main, BenchmarkGroup, BenchmarkId, Criterion,
+ Throughput,
+};
+
+use sequoia_openpgp as openpgp;
+use openpgp::cert::{Cert, CertBuilder};
+use openpgp::packet::prelude::*;
+use openpgp::packet::{Signature, UserID};
+use openpgp::parse::Parse;
+use openpgp::serialize::SerializeInto;
+use openpgp::types::{Curve, KeyFlags, SignatureType};
+use openpgp::Result;
+
+use std::convert::TryInto;
+
+fn generate_certifications<'a>(
+ userid: &'a UserID,
+ cert: &'a Cert,
+ count: usize,
+) -> Result<impl Iterator<Item = Signature> + 'a> {
+
+ let k: Key<key::SecretParts, key::PrimaryRole> =
+ Key4::generate_ecc(true, Curve::Ed25519)?.into();
+ let mut keypair = k.into_keypair()?;
+
+ let iter = (0..count).map(move |_| {
+ userid
+ .certify(
+ &mut keypair,
+ cert,
+ SignatureType::PositiveCertification,
+ None,
+ None,
+ )
+ .unwrap()
+ });
+ Ok(iter)
+}
+
+fn generate_flooded_cert(
+ key_count: usize,
+ sigs_per_key: usize,
+) -> Result<Vec<u8>> {
+ // Generate a Cert for to be flooded
+ let (mut floodme, _) = CertBuilder::new()
+ .set_primary_key_flags(KeyFlags::empty().set_certification())
+ .add_userid("flood.me@example.org")
+ .generate()?;
+
+ let floodme_cloned = floodme.clone();
+ let userid = floodme_cloned.userids().nth(0).unwrap();
+
+ let certifications = (0..key_count).flat_map(|_| {
+ generate_certifications(&userid, &floodme_cloned, sigs_per_key)
+ .unwrap()
+ });
+
+ floodme = floodme.insert_packets(certifications)?;
+ floodme.export_to_vec()
+}
+
+/// Parse the cert, unwrap to notice errors
+fn read_cert(bytes: &[u8]) {
+ Cert::from_bytes(bytes).unwrap();
+}
+
+/// Generate the cert and benchmark parsing.
+/// The generated cert is signed by multiple other keys, 1 signature per key.
+fn parse_cert_generated(
+ group: &mut BenchmarkGroup<'_, criterion::measurement::WallTime>,
+ name: &str,
+ signature_count: usize,
+) {
+ let bytes = generate_flooded_cert(signature_count, 1).unwrap();
+
+ group.throughput(Throughput::Bytes(bytes.len().try_into().unwrap()));
+
+ group.bench_with_input(
+ BenchmarkId::new(name, signature_count),
+ &bytes,
+ |b, bytes| b.iter(|| read_cert(bytes)),
+ );
+}
+
+/// Benchmark parsing a generated cert with a given number of signatures
+fn bench_parse_certs_generated(c: &mut Criterion) {
+ let mut group = c.benchmark_group("parse flooded cert");
+ parse_cert_generated(&mut group, "flooded", 100);
+ parse_cert_generated(&mut group, "flooded", 316);
+ parse_cert_generated(&mut group, "flooded", 1000);
+ parse_cert_generated(&mut group, "flooded", 3162);
+ group.finish();
+}
+
+/// Benchmark parsing a typical cert
+fn bench_parse_certs(c: &mut Criterion) {
+ let mut group = c.benchmark_group("parse typical cert");
+ let bytes = include_bytes!("../tests/data/keys/neal.pgp");
+ group.throughput(Throughput::Bytes(bytes.len().try_into().unwrap()));
+ group.bench_function("neal.pgp", |b| b.iter(|| read_cert(bytes)));
+ group.finish();
+}
+
+criterion_group!(benches, bench_parse_certs, bench_parse_certs_generated);
+criterion_main!(benches);