Skip to content

Commit

Permalink
add benchmarks in the browser
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Nov 17, 2022
1 parent d77f3b7 commit 1688c36
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 62 deletions.
62 changes: 51 additions & 11 deletions tpke-wasm/BENCHMARK.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,69 @@ cargo bench

## Results

Using fixed values, such that `shares=num_entities=threshold`.

Rounding to nearest ms.

### WASM Results

```
encrypt: shares=8: 71 ms
encrypt: shares=16: 70 ms
encrypt: shares=32: 70 ms
encrypt: shares=64: 70 ms
encrypt: shares=128: 72 ms
combine: shares=8: 145 ms
combine: shares=16: 278 ms
combine: shares=32: 554 ms
combine: shares=64: 1079 ms
combine: shares=128: 2253 ms
```

### Rust Results

Results rewritten for clarity:

```
encrypt: shares=8: 5 ms
encrypt: shares=16: 5 ms
encrypt: shares=32: 5 ms
encrypt: shares=64: 5 ms
encrypt: shares=128: 5 ms
combine: shares=8: 10 ms
combine: shares=16: 20 ms
combine: shares=32: 39 ms
combine: shares=64: 82 ms
combine: shares=128: 162 ms
```

Raw results from `cargo bench`:

```
TPKE-WASM/tpke-wasm::encrypt - num_shares=8, num_entities=8, threshold=8
time: [4.8427 ms 4.9178 ms 5.0113 ms]
Found 2 outliers among 10 measurements (20.00%)
2 (20.00%) high mild
time: [4.8288 ms 4.9155 ms 5.0219 ms]
TPKE-WASM/tpke-wasm::combine - num_shares=8, num_entities=8, threshold=8
time: [10.197 ms 10.452 ms 10.994 ms]
TPKE-WASM/tpke-wasm::encrypt - num_shares=16, num_entities=16, threshold=16
time: [4.8967 ms 4.9732 ms 5.1114 ms]
Found 1 outliers among 10 measurements (10.00%)
1 (10.00%) high mild
time: [4.9404 ms 5.0003 ms 5.1142 ms]
TPKE-WASM/tpke-wasm::combine - num_shares=16, num_entities=16, threshold=16
time: [19.536 ms 20.278 ms 20.924 ms]
TPKE-WASM/tpke-wasm::encrypt - num_shares=32, num_entities=32, threshold=32
time: [4.8219 ms 5.0377 ms 5.3367 ms]
Found 1 outliers among 10 measurements (10.00%)
1 (10.00%) high severe
time: [4.8744 ms 5.0070 ms 5.1049 ms]
TPKE-WASM/tpke-wasm::combine - num_shares=32, num_entities=32, threshold=32
time: [38.619 ms 39.276 ms 39.939 ms]
TPKE-WASM/tpke-wasm::encrypt - num_shares=64, num_entities=64, threshold=64
time: [4.8865 ms 4.9192 ms 4.9529 ms]
time: [5.0275 ms 5.1389 ms 5.2306 ms]
TPKE-WASM/tpke-wasm::combine - num_shares=64, num_entities=64, threshold=64
time: [76.279 ms 82.054 ms 87.068 ms]
TPKE-WASM/tpke-wasm::encrypt - num_shares=128, num_entities=128, threshold=128
time: [4.8900 ms 4.9389 ms 4.9834 ms]
time: [4.9211 ms 5.0305 ms 5.1302 ms]
TPKE-WASM/tpke-wasm::combine - num_shares=128, num_entities=128, threshold=128
time: [155.29 ms 162.48 ms 174.21 ms]
```
55 changes: 50 additions & 5 deletions tpke-wasm/benches/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,75 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};

pub fn bench_encrypt_combine(c: &mut Criterion) {
fn encrypt_bench(
use tpke_wasm::*;

fn bench_encrypt(
num_shares: usize,
num_entities: usize,
threshold: usize,
) -> impl Fn() {
let message = "my-secret-message".as_bytes().to_vec();
let aad = "my-aad".as_bytes().to_vec();
let setup = tpke_wasm::Setup::new(threshold, num_shares, num_entities);
let setup = Setup::new(threshold, num_shares, num_entities);
move || {
let message = message.clone();
let aad = aad.clone();
black_box(tpke_wasm::encrypt(message, aad, setup.public_key));
black_box(encrypt(&message, &aad, &setup.public_key));
}
}

fn bench_combine(
num_shares: usize,
num_entities: usize,
threshold: usize,
) -> impl Fn() {
let message = "my-secret-message".as_bytes().to_vec();
let aad = "my-aad".as_bytes().to_vec();
let setup = Setup::new(threshold, num_shares, num_entities);
let ciphertext = encrypt(&message.to_vec(), &aad, &setup.public_key);
let participant_payloads: Vec<ParticipantPayload> = setup
.decrypter_indexes()
.iter()
.map(|index| {
ParticipantPayload::new(
&setup.private_context_at(*index),
&ciphertext.clone(),
)
})
.collect();
let decryption_shares: Vec<DecryptionShare> = participant_payloads
.iter()
.map(|p| p.to_decryption_share())
.collect();

move || {
let setup = setup.clone();
let decryption_shares = decryption_shares.clone();
black_box({
let mut ss_builder = SharedSecretBuilder::new(&setup);
for share in decryption_shares {
ss_builder.add_decryption_share(&share);
}
ss_builder.build();
})
}
}

let mut group = c.benchmark_group("TPKE-WASM");
group.sample_size(10);

for num_shares in [8, 16, 32, 64, 128].iter() {
let a = encrypt_bench(*num_shares, *num_shares, *num_shares);
let encrypt_fn = bench_encrypt(*num_shares, *num_shares, *num_shares);
group.measurement_time(core::time::Duration::new(30, 0));
group.bench_function(format!("tpke-wasm::encrypt - num_shares={}, num_entities={}, threshold={}", num_shares, num_shares, num_shares), |b| {
b.iter(|| a())
b.iter(|| encrypt_fn())
});

let combine_fn = bench_combine(*num_shares, *num_shares, *num_shares);
group.measurement_time(core::time::Duration::new(30, 0));
group.bench_function(format!("tpke-wasm::combine - num_shares={}, num_entities={}, threshold={}", num_shares, num_shares, num_shares), |b| {
b.iter(|| combine_fn())
});
}
}

Expand Down
74 changes: 66 additions & 8 deletions tpke-wasm/js-benches/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,74 @@
import init from "./pkg/tpke_wasm.js";
import { Setup } from "./pkg/tpke_wasm.js";
import init, {
Setup,
encrypt,
ParticipantPayload,
SharedSecretBuilder,
} from "./pkg/tpke_wasm.js";

const BENCHMARK_TRIALS = 10;

const median = (arr) => {
const mid = Math.floor(arr.length / 2),
nums = [...arr].sort((a, b) => a - b);
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
};

function benchmark_encrypt(setup) {
const message = Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const aad = Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

const perf = Array.from({ length: BENCHMARK_TRIALS }, (_, _i) => {
const t0 = performance.now();
encrypt(message, aad, setup.public_key);
const t1 = performance.now();
return t1 - t0;
});
return `${median(perf)} ms`;
}

function benchmark_combine(setup) {
const message = Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const aad = Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const ciphertext = encrypt(message, aad, setup.public_key);
// Using a push to array here instead of map because somehow map breaks
// DecryptionShare into Uint8Array during iteration
const decryptionShares = [];
setup.decrypter_indexes().forEach((index) => {
const decryptionContext = setup.private_context_at(index);
const share = new ParticipantPayload(
decryptionContext,
ciphertext
).to_decryption_share();
decryptionShares.push(share);
});

const perf = Array.from({ length: BENCHMARK_TRIALS }, (_, _i) => {
const t0 = performance.now();
const ssBuilder = new SharedSecretBuilder(setup);
decryptionShares.forEach((share) => ssBuilder.add_decryption_share(share));
ssBuilder.build();
const t1 = performance.now();
return t1 - t0;
});
return `${median(perf)} ms`;
}

const runBenchmarks = async () => {
console.log("Initializing ...");
console.log("Initializing ...");

const setup = new Setup();
const numShares = [8, 16, 32, 64, 128];
for (const shares of numShares) {
const setup = new Setup(shares, shares, shares);

console.log("Setup: ", setup);
const encrypt_results = benchmark_encrypt(setup);
console.log(`encrypt: shares=${shares}: ${encrypt_results}`);

console.log("Done!");
const combine_results = benchmark_combine(setup);
console.log(`combine: shares=${shares}: ${combine_results}`);
}
console.log("Done!");
};

init()
.then(runBenchmarks)
.catch((err) => console.error(err));
.then(runBenchmarks)
.catch((err) => console.error(err));
48 changes: 27 additions & 21 deletions tpke-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ const DECRYPTER_INDEX_LEN: usize = 8;
#[wasm_bindgen]
impl PrivateDecryptionContext {
pub(crate) fn new(
b_inv: ark_bls12_381::Fr,
b_inv: &ark_bls12_381::Fr,
decrypter_index: usize,
) -> Self {
Self {
b_inv,
b_inv: *b_inv,
decrypter_index,
}
}
Expand Down Expand Up @@ -119,12 +119,12 @@ pub struct ParticipantPayload {
impl ParticipantPayload {
#[wasm_bindgen(constructor)]
pub fn new(
decryption_context: PrivateDecryptionContext,
ciphertext: Ciphertext,
decryption_context: &PrivateDecryptionContext,
ciphertext: &Ciphertext,
) -> Self {
ParticipantPayload {
decryption_context,
ciphertext: ciphertext.ciphertext,
Self {
decryption_context: decryption_context.clone(),
ciphertext: ciphertext.ciphertext.clone(),
}
}

Expand All @@ -146,7 +146,7 @@ impl ParticipantPayload {
bytes[PrivateDecryptionContext::serialized_size()..].to_vec();
let ciphertext = tpke::Ciphertext::from_bytes(&ciphertext_bytes);

ParticipantPayload {
Self {
decryption_context,
ciphertext,
}
Expand Down Expand Up @@ -216,6 +216,7 @@ impl PrivateKey {
}

#[wasm_bindgen]
#[derive(Clone, Debug)]
pub struct Setup {
pub public_key: PublicKey,
pub private_key: PrivateKey,
Expand All @@ -239,7 +240,7 @@ impl Setup {
let private_contexts = contexts
.clone()
.into_iter()
.map(|x| PrivateDecryptionContext::new(x.b_inv, x.index))
.map(|x| PrivateDecryptionContext::new(&x.b_inv, x.index))
.collect();
let public_contexts = contexts[0].public_decryption_contexts.to_vec();

Expand Down Expand Up @@ -271,6 +272,8 @@ impl Setup {
.map(|x| x.decrypter_index)
.collect()
}

// TODO: Add `decryptorShares` helper method
}

#[wasm_bindgen]
Expand All @@ -282,20 +285,23 @@ pub struct Ciphertext {

#[wasm_bindgen]
pub fn encrypt(
message: Vec<u8>,
aad: Vec<u8>,
public_key: PublicKey,
message: &[u8],
aad: &[u8],
public_key: &PublicKey,
) -> Ciphertext {
set_panic_hook();

let mut rng = rand::thread_rng();
let ciphertext =
tpke::encrypt::<_, E>(&message, &aad, public_key.0, &mut rng);
Ciphertext { ciphertext, aad }
tpke::encrypt::<_, E>(message, aad, &public_key.0, &mut rng);
Ciphertext {
ciphertext,
aad: aad.to_vec(),
}
}

#[wasm_bindgen]
pub fn decrypt(ciphertext: Ciphertext, private_key: PrivateKey) -> Vec<u8> {
pub fn decrypt(ciphertext: &Ciphertext, private_key: &PrivateKey) -> Vec<u8> {
set_panic_hook();

tpke::checked_decrypt(
Expand All @@ -319,16 +325,16 @@ pub struct SharedSecretBuilder {
#[wasm_bindgen]
impl SharedSecretBuilder {
#[wasm_bindgen(constructor)]
pub fn new(setup: Setup) -> Self {
pub fn new(setup: &Setup) -> Self {
SharedSecretBuilder {
shares: vec![],
contexts: setup.public_contexts,
contexts: setup.public_contexts.clone(),
}
}

#[wasm_bindgen]
pub fn add_decryption_share(&mut self, share: DecryptionShare) {
self.shares.push(share.0);
pub fn add_decryption_share(&mut self, share: &DecryptionShare) {
self.shares.push(share.0.clone());
}

#[wasm_bindgen]
Expand All @@ -349,8 +355,8 @@ impl SharedSecretBuilder {

#[wasm_bindgen]
pub fn decrypt_with_shared_secret(
ciphertext: Ciphertext,
shared_secret: SharedSecret,
ciphertext: &Ciphertext,
shared_secret: &SharedSecret,
) -> Vec<u8> {
set_panic_hook();

Expand Down
Loading

0 comments on commit 1688c36

Please sign in to comment.