No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.rs 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #[macro_use]
  2. extern crate serde_derive;
  3. extern crate serde;
  4. extern crate serde_json;
  5. extern crate serde_cbor;
  6. extern crate bincode;
  7. extern crate rand;
  8. extern crate time;
  9. use time::PreciseTime;
  10. use rand::prelude::*;
  11. use std::fs::File;
  12. use std::io::Write;
  13. use std::sync::mpsc::*;
  14. use std::thread;
  15. use std::collections::HashMap;
  16. const ITERATIONS : u32 = 50;
  17. const MAX_BLOCK_SIZE : u32 = 250_000;
  18. const STEP_SIZE : u32 = 10_000;
  19. const TOTAL_STEPS : u32 = MAX_BLOCK_SIZE / STEP_SIZE;
  20. const ADDRESS_BYTES : u32 = 12;
  21. const TREE_HEIGHT : u32 = 6;
  22. const DATA_SIZE_MIN : u32 = 16;
  23. const DATA_SIZE_MAX : u32 = 128;
  24. const STORAGE_ENTRIES : u32 = 32;
  25. #[derive(Serialize, Deserialize, Debug, PartialEq)]
  26. struct Transaction {
  27. from: String,
  28. to: String,
  29. value: usize
  30. }
  31. #[derive(Serialize, Deserialize, Debug, PartialEq)]
  32. enum TreeNode {
  33. Leaf(String, u8),
  34. Other(Box<TreeNode>, Box<TreeNode>)
  35. }
  36. #[derive(Serialize, Deserialize, Debug, PartialEq)]
  37. struct Block {
  38. transactions: Vec<Transaction>,
  39. tree: TreeNode,
  40. nonce: u64,
  41. flag: bool,
  42. data: Vec<u8>,
  43. storage: HashMap<String, u32>
  44. }
  45. fn random_address() -> String {
  46. let mut rng = thread_rng();
  47. let mut result = String::from("0x");
  48. for _ in 0..ADDRESS_BYTES { result.push_str(&format!("{:02X}", rng.gen::<u8>())); }
  49. result
  50. }
  51. fn random_transaction() -> Transaction {
  52. Transaction {
  53. from: random_address(),
  54. to: random_address(),
  55. value: thread_rng().gen()
  56. }
  57. }
  58. fn random_tree(n: u32) -> TreeNode {
  59. if n == 1 {
  60. TreeNode::Leaf(random_address(), thread_rng().gen())
  61. } else {
  62. TreeNode::Other(
  63. Box::new(random_tree(n - 1)),
  64. Box::new(random_tree(n - 1))
  65. )
  66. }
  67. }
  68. fn random_data() -> Vec<u8> {
  69. let mut result = Vec::new();
  70. (0..thread_rng().gen_range(DATA_SIZE_MIN, DATA_SIZE_MAX)).for_each(|_| result.push(thread_rng().gen()));
  71. result
  72. }
  73. fn random_storage() -> HashMap<String, u32> {
  74. let mut storage : HashMap<String, u32> = HashMap::new();
  75. (0..STORAGE_ENTRIES).for_each(|_| {
  76. storage.insert(random_address(), thread_rng().gen());
  77. });
  78. storage
  79. }
  80. fn random_block(transaction_count: usize) -> Block {
  81. let mut result = Block {
  82. transactions: Vec::with_capacity(transaction_count),
  83. tree: random_tree(TREE_HEIGHT),
  84. nonce: thread_rng().gen(),
  85. flag: thread_rng().gen(),
  86. data: random_data(),
  87. storage: random_storage()
  88. };
  89. for _ in 0..transaction_count { result.transactions.push(random_transaction()); }
  90. result
  91. }
  92. struct Benchmark {
  93. serialize: f64,
  94. deserialize: f64
  95. }
  96. fn round_trip_json(block: Block) -> Benchmark {
  97. let serialize_start = PreciseTime::now();
  98. let serialized = serde_json::to_string(&block).unwrap();
  99. let serialize = serialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  100. let deserialize_start = PreciseTime::now();
  101. let deserialized : Block = serde_json::from_str(&serialized).unwrap();
  102. let deserialize = deserialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  103. assert_eq!(deserialized, block);
  104. Benchmark {
  105. serialize: serialize as f64,
  106. deserialize: deserialize as f64
  107. }
  108. }
  109. fn round_trip_cbor(block: Block) -> Benchmark {
  110. let serialize_start = PreciseTime::now();
  111. let serialized = serde_cbor::to_vec(&block).unwrap();
  112. let serialize = serialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  113. let deserialize_start = PreciseTime::now();
  114. let deserialized : Block = serde_cbor::from_slice(&serialized).unwrap();
  115. let deserialize = deserialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  116. assert_eq!(deserialized, block);
  117. Benchmark {
  118. serialize: serialize as f64,
  119. deserialize: deserialize as f64
  120. }
  121. }
  122. fn round_trip_bincode(block: Block) -> Benchmark {
  123. let serialize_start = PreciseTime::now();
  124. let serialized : Vec<u8> = bincode::serialize(&block).unwrap();
  125. let serialize = serialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  126. let deserialize_start = PreciseTime::now();
  127. let deserialized : Block = bincode::deserialize(&serialized[..]).unwrap();
  128. let deserialize = deserialize_start.to(PreciseTime::now()).num_nanoseconds().unwrap();
  129. assert_eq!(deserialized, block);
  130. Benchmark {
  131. serialize: serialize as f64,
  132. deserialize: deserialize as f64
  133. }
  134. }
  135. fn time_round_trip(f: &Fn(Block) -> Benchmark, block_size: usize, iterations: u32) -> Benchmark {
  136. let mut serialize = 0f64;
  137. let mut deserialize = 0f64;
  138. for _ in 0..iterations {
  139. let block = random_block(block_size);
  140. let benchmark = f(block);
  141. serialize += benchmark.serialize;
  142. deserialize += benchmark.deserialize;
  143. }
  144. Benchmark {
  145. serialize: (serialize as f64 / iterations as f64) / 1_000_000f64,
  146. deserialize: (deserialize as f64 / iterations as f64) / 1_000_000f64
  147. }
  148. }
  149. fn main() {
  150. struct BenchmarkResult {
  151. index: u32,
  152. json: Benchmark,
  153. cbor: Benchmark,
  154. bincode: Benchmark
  155. }
  156. let (sender, receiver) = channel();
  157. for i in 1..TOTAL_STEPS+1 {
  158. let my_sender = sender.clone();
  159. thread::spawn(move || {
  160. let block_size = (i * STEP_SIZE) as usize;
  161. let json = time_round_trip(&round_trip_json, block_size, ITERATIONS);
  162. let cbor = time_round_trip(&round_trip_cbor, block_size, ITERATIONS);
  163. let bincode = time_round_trip(&round_trip_bincode, block_size, ITERATIONS);
  164. my_sender.send(BenchmarkResult {
  165. index: i,
  166. json: json,
  167. cbor: cbor,
  168. bincode: bincode
  169. }).unwrap();
  170. });
  171. }
  172. let results = (1..TOTAL_STEPS+1).into_iter()
  173. .map(|_| {
  174. let result = receiver.recv().unwrap();
  175. let i = result.index;
  176. let block_size = i * STEP_SIZE;
  177. println!("Got results for {} ({})", i, block_size);
  178. (result.index, result)
  179. })
  180. .collect::<HashMap<u32, BenchmarkResult>>();
  181. let mut fh = File::create("data.csv").unwrap();
  182. let columns = [
  183. "Block Size",
  184. "JSON Serialize ms/op", "JSON Deserialize ms/op",
  185. "CBOR Serialize ms/op", "CBOR Deserialize ms/op",
  186. "Bincode Serialize ms/op", "Bincode Deserialize ms/op"
  187. ];
  188. for i in 0..columns.len() {
  189. write!(fh, "{}", columns[i]).unwrap();
  190. if i != columns.len() - 1 {
  191. write!(fh, ",").unwrap();
  192. }
  193. }
  194. write!(fh, "\n").unwrap();
  195. for i in 1..TOTAL_STEPS+1 {
  196. let result = results.get(&i).unwrap();
  197. let block_size = i * STEP_SIZE;
  198. let json = &result.json;
  199. let cbor = &result.cbor;
  200. let bincode = &result.bincode;
  201. writeln!(fh, "{},{:.4},{:.4},{:.4},{:.4},{:.4},{:.4}", block_size,
  202. json.serialize, json.deserialize,
  203. cbor.serialize, cbor.deserialize,
  204. bincode.serialize, bincode.deserialize).unwrap();
  205. }
  206. }