1use datafake_rs::{DataFakeError, DataGenerator};
2use serde_json::json;
3use std::time::Instant;
4
5fn main() -> Result<(), DataFakeError> {
6 let config = json!({
7 "metadata": {
8 "name": "Complex Benchmark Test",
9 "description": "Complex data generation benchmark with JSONLogic and fake operators"
10 },
11 "variables": {
12 "user_id": {"fake": ["uuid"]},
13 "base_timestamp": {"fake": ["u64", 1704067200, 1735689600]},
14 "country_code": {"fake": ["country_code"]},
15 "currency": {"fake": ["currency_code"]},
16 "age": {"fake": ["u8", 18, 65]},
17 "is_premium": {"fake": ["bool"]},
18 "base_salary": {"fake": ["f64", 30000, 150000]},
19 "company_name": {"fake": ["company_name"]},
20 "random_score": {"fake": ["f64", 0, 1]}
21 },
22 "schema": {
23 "id": {"var": "user_id"},
24 "timestamp": {"var": "base_timestamp"},
25 "user": {
26 "personal": {
27 "first_name": {"fake": ["first_name"]},
28 "last_name": {"fake": ["last_name"]},
29 "full_name": {
30 "cat": [
31 {"fake": ["first_name"]},
32 " ",
33 {"fake": ["last_name"]}
34 ]
35 },
36 "email": {
37 "if": [
38 {"var": "is_premium"},
39 {"fake": ["email"]},
40 {"fake": ["free_email"]}
41 ]
42 },
43 "phone": {"fake": ["phone_number"]},
44 "age": {"var": "age"},
45 "is_adult": {">=": [{"var": "age"}, 18]},
46 "age_group": {
47 "if": [
48 {"<": [{"var": "age"}, 25]},
49 "young",
50 {"if": [
51 {"<": [{"var": "age"}, 40]},
52 "adult",
53 {"if": [
54 {"<": [{"var": "age"}, 60]},
55 "middle-aged",
56 "senior"
57 ]}
58 ]}
59 ]
60 },
61 "username": {
62 "cat": [
63 {"fake": ["word"]},
64 "_",
65 {"fake": ["word"]},
66 "_",
67 {"fake": ["u16", 100, 999]}
68 ]
69 },
70 "password_hash": {"fake": ["password", 12, 16]},
71 "bio": {"fake": ["paragraph", 2, 4]}
72 },
73 "address": {
74 "street": {"fake": ["street_name"]},
75 "building": {"fake": ["u16", 1, 999]},
76 "full_address": {
77 "cat": [
78 {"fake": ["u16", 1, 999]},
79 " ",
80 {"fake": ["street_name"]},
81 " ",
82 {"fake": ["street_suffix"]}
83 ]
84 },
85 "city": {"fake": ["city"]},
86 "state": {"fake": ["state_name"]},
87 "country": {"var": "country_code"},
88 "postal_code": {"fake": ["post_code"]},
89 "coordinates": {
90 "lat": {"fake": ["latitude"]},
91 "lng": {"fake": ["longitude"]},
92 "formatted": {
93 "cat": [
94 {"fake": ["latitude"]},
95 ", ",
96 {"fake": ["longitude"]}
97 ]
98 }
99 }
100 },
101 "professional": {
102 "company": {"var": "company_name"},
103 "job_title": {"fake": ["profession"]},
104 "department": {"fake": ["industry"]},
105 "years_experience": {
106 "max": [
107 0,
108 {"-": [
109 {"var": "age"},
110 18
111 ]}
112 ]
113 },
114 "email": {
115 "cat": [
116 {"fake": ["word"]},
117 ".",
118 {"fake": ["word"]},
119 "@",
120 {"fake": ["word"]},
121 ".com"
122 ]
123 },
124 "company_suffix": {"fake": ["company_suffix"]},
125 "catch_phrase": {"fake": ["catch_phrase"]}
126 },
127 "financial": {
128 "currency": {"var": "currency"},
129 "credit_card": {"fake": ["credit_card_number"]},
130 "bank_account": {"fake": ["bic"]},
131 "base_salary": {"var": "base_salary"},
132 "bonus_percentage": {
133 "if": [
134 {"var": "is_premium"},
135 {"fake": ["f64", 15, 30]},
136 {"fake": ["f64", 5, 15]}
137 ]
138 },
139 "total_compensation": {
140 "*": [
141 {"var": "base_salary"},
142 {"+": [
143 1,
144 {"/": [
145 {"if": [
146 {"var": "is_premium"},
147 0.225,
148 0.1
149 ]},
150 1
151 ]}
152 ]}
153 ]
154 },
155 "credit_score": {
156 "if": [
157 {"var": "is_premium"},
158 {"fake": ["u16", 700, 850]},
159 {"fake": ["u16", 500, 700]}
160 ]
161 },
162 "has_debt": {"<": [{"var": "random_score"}, 0.6]},
163 "debt_amount": {
164 "if": [
165 {"<": [{"var": "random_score"}, 0.6]},
166 {"fake": ["f64", 1000, 50000]},
167 0
168 ]
169 }
170 },
171 "internet": {
172 "ip_v4": {"fake": ["ipv4"]},
173 "ip_v6": {"fake": ["ipv6"]},
174 "mac_address": {"fake": ["mac_address"]},
175 "user_agent": {"fake": ["user_agent"]},
176 "domain": {
177 "cat": [
178 {"fake": ["word"]},
179 ".",
180 {"fake": ["domain_suffix"]}
181 ]
182 },
183 "bandwidth_mbps": {
184 "if": [
185 {"var": "is_premium"},
186 {"fake": ["u16", 100, 1000]},
187 {"fake": ["u16", 10, 100]}
188 ]
189 }
190 },
191 "preferences": {
192 "theme": {
193 "if": [
194 {"<": [{"var": "random_score"}, 0.7]},
195 "dark",
196 "light"
197 ]
198 },
199 "language": {
200 "if": [
201 {"==": [{"var": "country_code"}, "US"]},
202 "en-US",
203 {"if": [
204 {"==": [{"var": "country_code"}, "GB"]},
205 "en-GB",
206 {"if": [
207 {"==": [{"var": "country_code"}, "FR"]},
208 "fr-FR",
209 "en-US"
210 ]}
211 ]}
212 ]
213 },
214 "notifications": {
215 "email": {"var": "is_premium"},
216 "push": {"<": [{"var": "random_score"}, 0.8]},
217 "sms": {"and": [
218 {"var": "is_premium"},
219 {"<": [{"var": "random_score"}, 0.5]}
220 ]}
221 },
222 "privacy_level": {
223 "if": [
224 {"var": "is_premium"},
225 {"if": [
226 {"<": [{"var": "random_score"}, 0.7]},
227 "high",
228 "medium"
229 ]},
230 {"if": [
231 {"<": [{"var": "random_score"}, 0.3]},
232 "high",
233 {"if": [
234 {"<": [{"var": "random_score"}, 0.7]},
235 "medium",
236 "low"
237 ]}
238 ]}
239 ]
240 }
241 },
242 "metadata": {
243 "account_created": {"fake": ["u64", 1577836800, 1704067200]},
244 "last_login": {"fake": ["u64", 1735689600, 1738368000]},
245 "login_count": {
246 "*": [
247 {"fake": ["u16", 10, 365]},
248 {"-": [
249 2024,
250 {"+": [
251 2020,
252 {"fake": ["u8", 0, 3]}
253 ]}
254 ]}
255 ]
256 },
257 "is_verified": {"or": [
258 {"var": "is_premium"},
259 {"<": [{"var": "random_score"}, 0.7]}
260 ]},
261 "subscription_tier": {
262 "if": [
263 {"var": "is_premium"},
264 {"if": [
265 {"<": [{"var": "random_score"}, 0.5]},
266 "pro",
267 "enterprise"
268 ]},
269 "free"
270 ]
271 },
272 "risk_score": {
273 "max": [
274 0,
275 {"min": [
276 100,
277 {"+": [
278 {"if": [{"var": "is_verified"}, 0, 20]},
279 {"if": [{"var": "is_premium"}, 0, 15]},
280 {"*": [
281 {"var": "random_score"},
282 65
283 ]}
284 ]}
285 ]}
286 ]
287 }
288 }
289 },
290 "activity": {
291 "recent_transactions": [
292 {
293 "id": {"fake": ["uuid"]},
294 "amount": {
295 "*": [
296 {"fake": ["f64", 10, 500]},
297 {"if": [{"var": "is_premium"}, 1.5, 1]}
298 ]
299 },
300 "merchant": {"fake": ["company_name"]},
301 "category": {"fake": ["industry"]},
302 "timestamp": {"fake": ["u64", 1735000000, 1738000000]},
303 "approved": {"or": [
304 {"var": "is_premium"},
305 {">": [{"var": "random_score"}, 0.1]}
306 ]}
307 },
308 {
309 "id": {"fake": ["uuid"]},
310 "amount": {
311 "*": [
312 {"fake": ["f64", 10, 500]},
313 {"if": [{"var": "is_premium"}, 1.5, 1]}
314 ]
315 },
316 "merchant": {"fake": ["company_name"]},
317 "category": {"fake": ["industry"]},
318 "timestamp": {"fake": ["u64", 1735000000, 1738000000]},
319 "approved": {"or": [
320 {"var": "is_premium"},
321 {">": [{"var": "random_score"}, 0.1]}
322 ]}
323 },
324 {
325 "id": {"fake": ["uuid"]},
326 "amount": {
327 "*": [
328 {"fake": ["f64", 10, 500]},
329 {"if": [{"var": "is_premium"}, 1.5, 1]}
330 ]
331 },
332 "merchant": {"fake": ["company_name"]},
333 "category": {"fake": ["industry"]},
334 "timestamp": {"fake": ["u64", 1735000000, 1738000000]},
335 "approved": {"or": [
336 {"var": "is_premium"},
337 {">": [{"var": "random_score"}, 0.1]}
338 ]}
339 }
340 ],
341 "engagement_score": {
342 "*": [
343 100,
344 {"min": [
345 1,
346 {"max": [
347 0,
348 {"+": [
349 {"if": [{"var": "is_premium"}, 0.3, 0]},
350 {"if": [{"var": "is_verified"}, 0.2, 0]},
351 {"*": [{"var": "random_score"}, 0.5]}
352 ]}
353 ]}
354 ]}
355 ]
356 },
357 "features_used": {
358 "if": [
359 {"var": "is_premium"},
360 ["dashboard", "profile", "settings", "analytics", "api", "export", "import"],
361 ["dashboard", "profile", "settings"]
362 ]
363 }
364 }
365 }
366 });
367
368 let generator = DataGenerator::from_value(config)?;
369
370 println!("Starting benchmark: generating complex data 100,000 times...");
371 println!("This benchmark uses a mix of:");
372 println!("- Fake data operators");
373 println!("- JSONLogic expressions (if/then/else, arithmetic, string operations)");
374 println!("- Variable references");
375 println!("- Complex nested structures");
376 println!();
377
378 let iterations = 100_000;
379 let mut last_progress = 0;
380
381 let start = Instant::now();
382
383 for i in 0..iterations {
384 let _ = generator.generate()?;
385
386 let progress = (i * 100) / iterations;
387 if progress > last_progress && progress % 10 == 0 {
388 println!("Progress: {progress}%");
389 last_progress = progress;
390 }
391 }
392
393 let duration = start.elapsed();
394
395 println!("\n=== Benchmark Results ===");
396 println!("Total iterations: {iterations}");
397 println!("Total time: {duration:.2?}");
398 println!(
399 "Average time per generation: {:.2?}",
400 duration / iterations as u32
401 );
402 println!(
403 "Generations per second: {:.2}",
404 iterations as f64 / duration.as_secs_f64()
405 );
406
407 let sample = generator.generate()?;
408 println!(
409 "\nSample output size: {} bytes",
410 serde_json::to_string(&sample)?.len()
411 );
412 println!("\nSample output (pretty printed):");
413 println!("{}", serde_json::to_string_pretty(&sample)?);
414
415 Ok(())
416}