| ... | ... | @@ -21,6 +21,14 @@ const Crypto = struct { |
| 21 | 21 | name: []const u8, |
| 22 | 22 | }; |
| 23 | 23 | |
| 24 | fn blackBox(x: anytype) void { |
| 25 | asm volatile ("" |
| 26 | : |
| 27 | : [x] "rm" (x) |
| 28 | : "memory" |
| 29 | ); |
| 30 | } |
| 31 | |
| 24 | 32 | const hashes = [_]Crypto{ |
| 25 | 33 | Crypto{ .ty = crypto.hash.Md5, .name = "md5" }, |
| 26 | 34 | Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" }, |
| ... | ... | @@ -46,6 +54,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 |
| 46 | 54 | while (offset < bytes) : (offset += block.len) { |
| 47 | 55 | h.update(block[0..]); |
| 48 | 56 | } |
| 57 | blackBox(&h); |
| 49 | 58 | const end = timer.read(); |
| 50 | 59 | |
| 51 | 60 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; |
| ... | ... | @@ -67,19 +76,20 @@ const macs = [_]Crypto{ |
| 67 | 76 | }; |
| 68 | 77 | |
| 69 | 78 | pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { |
| 70 | | std.debug.assert(64 >= Mac.mac_length and 32 >= Mac.minimum_key_length); |
| 71 | | |
| 72 | | var in: [1 * MiB]u8 = undefined; |
| 79 | var in: [512 * KiB]u8 = undefined; |
| 73 | 80 | prng.random.bytes(in[0..]); |
| 74 | 81 | |
| 75 | | var key: [64]u8 = undefined; |
| 82 | const key_length = if (Mac.minimum_key_length == 0) 32 else Mac.minimum_key_length; |
| 83 | var key: [key_length]u8 = undefined; |
| 76 | 84 | prng.random.bytes(key[0..]); |
| 77 | 85 | |
| 86 | var mac: [Mac.mac_length]u8 = undefined; |
| 78 | 87 | var offset: usize = 0; |
| 79 | 88 | var timer = try Timer.start(); |
| 80 | 89 | const start = timer.lap(); |
| 81 | 90 | while (offset < bytes) : (offset += in.len) { |
| 82 | | Mac.create(key[0..], in[0..], key[0..]); |
| 91 | Mac.create(mac[0..], in[0..], key[0..]); |
| 92 | blackBox(&mac); |
| 83 | 93 | } |
| 84 | 94 | const end = timer.read(); |
| 85 | 95 | |
| ... | ... | @@ -106,6 +116,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c |
| 106 | 116 | var i: usize = 0; |
| 107 | 117 | while (i < exchange_count) : (i += 1) { |
| 108 | 118 | _ = DhKeyExchange.create(out[0..], out[0..], in[0..]); |
| 119 | blackBox(&out); |
| 109 | 120 | } |
| 110 | 121 | } |
| 111 | 122 | const end = timer.read(); |
| ... | ... | @@ -118,7 +129,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c |
| 118 | 129 | |
| 119 | 130 | const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }}; |
| 120 | 131 | |
| 121 | | pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { |
| 132 | pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { |
| 122 | 133 | var seed: [Signature.seed_length]u8 = undefined; |
| 123 | 134 | prng.random.bytes(seed[0..]); |
| 124 | 135 | const msg = [_]u8{0} ** 64; |
| ... | ... | @@ -129,7 +140,8 @@ pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_coun |
| 129 | 140 | { |
| 130 | 141 | var i: usize = 0; |
| 131 | 142 | while (i < signatures_count) : (i += 1) { |
| 132 | | _ = try Signature.sign(&msg, key_pair, null); |
| 143 | const s = try Signature.sign(&msg, key_pair, null); |
| 144 | blackBox(&s); |
| 133 | 145 | } |
| 134 | 146 | } |
| 135 | 147 | const end = timer.read(); |
| ... | ... | @@ -140,6 +152,40 @@ pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_coun |
| 140 | 152 | return throughput; |
| 141 | 153 | } |
| 142 | 154 | |
| 155 | const aeads = [_]Crypto{ |
| 156 | Crypto{ .ty = crypto.aead.ChaCha20Poly1305, .name = "chacha20Poly1305" }, |
| 157 | Crypto{ .ty = crypto.aead.XChaCha20Poly1305, .name = "xchacha20Poly1305" }, |
| 158 | Crypto{ .ty = crypto.aead.Gimli, .name = "gimli-aead" }, |
| 159 | }; |
| 160 | |
| 161 | pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 { |
| 162 | var in: [512 * KiB]u8 = undefined; |
| 163 | prng.random.bytes(in[0..]); |
| 164 | |
| 165 | var tag: [Aead.tag_length]u8 = undefined; |
| 166 | |
| 167 | var key: [Aead.key_length]u8 = undefined; |
| 168 | prng.random.bytes(key[0..]); |
| 169 | |
| 170 | var nonce: [Aead.nonce_length]u8 = undefined; |
| 171 | prng.random.bytes(nonce[0..]); |
| 172 | |
| 173 | var offset: usize = 0; |
| 174 | var timer = try Timer.start(); |
| 175 | const start = timer.lap(); |
| 176 | while (offset < bytes) : (offset += in.len) { |
| 177 | Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key); |
| 178 | Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key) catch unreachable; |
| 179 | } |
| 180 | blackBox(&in); |
| 181 | const end = timer.read(); |
| 182 | |
| 183 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; |
| 184 | const throughput = @floatToInt(u64, 2 * bytes / elapsed_s); |
| 185 | |
| 186 | return throughput; |
| 187 | } |
| 188 | |
| 143 | 189 | fn usage() void { |
| 144 | 190 | std.debug.warn( |
| 145 | 191 | \\throughput_test [options] |
| ... | ... | @@ -198,29 +244,36 @@ pub fn main() !void { |
| 198 | 244 | |
| 199 | 245 | inline for (hashes) |H| { |
| 200 | 246 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { |
| 201 | | const throughput = try benchmarkHash(H.ty, mode(32 * MiB)); |
| 202 | | try stdout.print("{:>11}: {:5} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); |
| 247 | const throughput = try benchmarkHash(H.ty, mode(128 * MiB)); |
| 248 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); |
| 203 | 249 | } |
| 204 | 250 | } |
| 205 | 251 | |
| 206 | 252 | inline for (macs) |M| { |
| 207 | 253 | if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { |
| 208 | 254 | const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); |
| 209 | | try stdout.print("{:>11}: {:5} MiB/s\n", .{ M.name, throughput / (1 * MiB) }); |
| 255 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ M.name, throughput / (1 * MiB) }); |
| 210 | 256 | } |
| 211 | 257 | } |
| 212 | 258 | |
| 213 | 259 | inline for (exchanges) |E| { |
| 214 | 260 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 215 | 261 | const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); |
| 216 | | try stdout.print("{:>11}: {:5} exchanges/s\n", .{ E.name, throughput }); |
| 262 | try stdout.print("{:>17}: {:7} exchanges/s\n", .{ E.name, throughput }); |
| 217 | 263 | } |
| 218 | 264 | } |
| 219 | 265 | |
| 220 | 266 | inline for (signatures) |E| { |
| 221 | 267 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 222 | | const throughput = try benchmarkSignatures(E.ty, mode(1000)); |
| 223 | | try stdout.print("{:>11}: {:5} signatures/s\n", .{ E.name, throughput }); |
| 268 | const throughput = try benchmarkSignature(E.ty, mode(1000)); |
| 269 | try stdout.print("{:>17}: {:7} signatures/s\n", .{ E.name, throughput }); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | inline for (aeads) |E| { |
| 274 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 275 | const throughput = try benchmarkAead(E.ty, mode(128 * MiB)); |
| 276 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ E.name, throughput / (1 * MiB) }); |
| 224 | 277 | } |
| 225 | 278 | } |
| 226 | 279 | } |