synthra 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +40 -0
  4. data/.yardopts +18 -0
  5. data/ACCESS_DOCS.md +116 -0
  6. data/ADVANCED_FEATURES_SUMMARY.md +245 -0
  7. data/CHANGELOG.md +498 -0
  8. data/CODE_OF_CONDUCT.md +122 -0
  9. data/CONTRIBUTING.md +307 -0
  10. data/DOCUMENTATION.md +204 -0
  11. data/DOCUMENTATION_GUIDE.md +194 -0
  12. data/LICENSE +22 -0
  13. data/README.md +1458 -0
  14. data/Rakefile +128 -0
  15. data/benchmark/README.md +591 -0
  16. data/benchmark/batch_generation.rb +63 -0
  17. data/benchmark/engine_comparison.rb +295 -0
  18. data/benchmark/single_record.rb +108 -0
  19. data/benchmark/streaming.rb +74 -0
  20. data/docs/ACTIVERECORD_INFERENCE.md +524 -0
  21. data/docs/API_SERVER.md +278 -0
  22. data/docs/CONFIG_FILE.md +315 -0
  23. data/docs/DATA_CONTRACTS.md +312 -0
  24. data/docs/ENHANCED_REPL.md +304 -0
  25. data/docs/FACTORY_BOT.md +271 -0
  26. data/docs/GITHUB_ACTION.md +420 -0
  27. data/docs/GRAPHQL_EXPORT.md +303 -0
  28. data/docs/GRAPHQL_FEDERATION.md +651 -0
  29. data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
  30. data/docs/LSP.md +189 -0
  31. data/docs/MIGRATION_GENERATOR.md +547 -0
  32. data/docs/MOCK_SERVER.md +280 -0
  33. data/docs/NATIVE_ENGINE.md +298 -0
  34. data/docs/OPENAPI_EXPORT.md +252 -0
  35. data/docs/PERFORMANCE_MODE.md +228 -0
  36. data/docs/PERSONAS.md +547 -0
  37. data/docs/PROPERTY_TESTING.md +284 -0
  38. data/docs/PROTOBUF_EXPORT.md +276 -0
  39. data/docs/QUALITY_METRICS.md +555 -0
  40. data/docs/QUICK_REFERENCE.md +88 -0
  41. data/docs/RAILS_ENGINE.md +404 -0
  42. data/docs/RAILS_INTEGRATION.md +454 -0
  43. data/docs/README.md +175 -0
  44. data/docs/REPL_QUICK_REFERENCE.md +149 -0
  45. data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
  46. data/docs/SCENARIOS.md +576 -0
  47. data/docs/SECURITY_TESTING.md +318 -0
  48. data/docs/SNAPSHOT_TESTING.md +308 -0
  49. data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
  50. data/docs/TERRAFORM_EXPORT.md +447 -0
  51. data/docs/TIME_TRAVEL.md +507 -0
  52. data/docs/USAGE_GUIDE.md +980 -0
  53. data/docs/WEBHOOK_SIMULATOR.md +579 -0
  54. data/docs/advanced_features.md +183 -0
  55. data/docs/api_reference.md +153 -0
  56. data/docs/behaviors.md +138 -0
  57. data/docs/best_practices.md +191 -0
  58. data/docs/dsl_reference.md +172 -0
  59. data/docs/examples.md +162 -0
  60. data/docs/generation_modes.md +125 -0
  61. data/docs/getting_started.md +92 -0
  62. data/docs/index.html +177 -0
  63. data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
  64. data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
  65. data/docs/troubleshooting.md +215 -0
  66. data/docs/type_reference.md +224 -0
  67. data/examples/hostile_mode_demo.rb +64 -0
  68. data/exe/synthra +6 -0
  69. data/ext/synthra_native/Cargo.lock +972 -0
  70. data/ext/synthra_native/Cargo.toml +46 -0
  71. data/ext/synthra_native/extconf.rb +41 -0
  72. data/ext/synthra_native/src/generator.rs +397 -0
  73. data/ext/synthra_native/src/lib.rs +229 -0
  74. data/ext/synthra_native/src/types.rs +1485 -0
  75. data/lib/generators/synthra/install_generator.rb +86 -0
  76. data/lib/generators/synthra/templates/api_response.dsl +15 -0
  77. data/lib/generators/synthra/templates/fake_data.rake +116 -0
  78. data/lib/generators/synthra/templates/synthra.yml +31 -0
  79. data/lib/generators/synthra/templates/synthra_support.rb +19 -0
  80. data/lib/generators/synthra/templates/user.dsl +11 -0
  81. data/lib/synthra/activerecord_inference.rb +394 -0
  82. data/lib/synthra/api.rb +381 -0
  83. data/lib/synthra/api_server.rb +718 -0
  84. data/lib/synthra/behaviors/applicator.rb +165 -0
  85. data/lib/synthra/behaviors/base.rb +155 -0
  86. data/lib/synthra/behaviors/close_connection.rb +60 -0
  87. data/lib/synthra/behaviors/deprecated.rb +100 -0
  88. data/lib/synthra/behaviors/failure.rb +69 -0
  89. data/lib/synthra/behaviors/latency.rb +103 -0
  90. data/lib/synthra/behaviors/partial_data.rb +83 -0
  91. data/lib/synthra/behaviors/randomize_order.rb +74 -0
  92. data/lib/synthra/behaviors/registry.rb +238 -0
  93. data/lib/synthra/behaviors/simulate_error.rb +79 -0
  94. data/lib/synthra/cli/commands/base.rb +105 -0
  95. data/lib/synthra/cli/commands/diff.rb +227 -0
  96. data/lib/synthra/cli/commands/docs.rb +67 -0
  97. data/lib/synthra/cli/commands/export.rb +150 -0
  98. data/lib/synthra/cli/commands/generate.rb +72 -0
  99. data/lib/synthra/cli/commands/import.rb +80 -0
  100. data/lib/synthra/cli/commands/lint.rb +53 -0
  101. data/lib/synthra/cli/commands/live.rb +57 -0
  102. data/lib/synthra/cli/commands/seed.rb +99 -0
  103. data/lib/synthra/cli/commands/validate.rb +28 -0
  104. data/lib/synthra/cli.rb +2471 -0
  105. data/lib/synthra/config_file.rb +129 -0
  106. data/lib/synthra/configuration.rb +281 -0
  107. data/lib/synthra/contracts_registry.rb +408 -0
  108. data/lib/synthra/database_seeder.rb +268 -0
  109. data/lib/synthra/deterministic_ids.rb +218 -0
  110. data/lib/synthra/documentation_generator.rb +414 -0
  111. data/lib/synthra/engine.rb +251 -0
  112. data/lib/synthra/errors.rb +1169 -0
  113. data/lib/synthra/export/base.rb +85 -0
  114. data/lib/synthra/export/csv.rb +101 -0
  115. data/lib/synthra/export/graphql.rb +266 -0
  116. data/lib/synthra/export/graphql_federation.rb +377 -0
  117. data/lib/synthra/export/graphviz.rb +258 -0
  118. data/lib/synthra/export/javascript.rb +327 -0
  119. data/lib/synthra/export/json_data.rb +61 -0
  120. data/lib/synthra/export/json_schema.rb +290 -0
  121. data/lib/synthra/export/openapi.rb +514 -0
  122. data/lib/synthra/export/protobuf.rb +483 -0
  123. data/lib/synthra/export/python.rb +560 -0
  124. data/lib/synthra/export/sql.rb +381 -0
  125. data/lib/synthra/export/sql_insert.rb +152 -0
  126. data/lib/synthra/export/terraform.rb +501 -0
  127. data/lib/synthra/export/type_mapping.rb +389 -0
  128. data/lib/synthra/export/typescript.rb +300 -0
  129. data/lib/synthra/export/xml_data.rb +104 -0
  130. data/lib/synthra/export/yaml_data.rb +56 -0
  131. data/lib/synthra/export.rb +404 -0
  132. data/lib/synthra/factory_bot_integration.rb +157 -0
  133. data/lib/synthra/field.rb +440 -0
  134. data/lib/synthra/functions/registry.rb +104 -0
  135. data/lib/synthra/generator/context.rb +372 -0
  136. data/lib/synthra/generator/engine.rb +336 -0
  137. data/lib/synthra/generator/faker_adapter.rb +425 -0
  138. data/lib/synthra/generator/modes.rb +444 -0
  139. data/lib/synthra/generator/resolver.rb +256 -0
  140. data/lib/synthra/generator/rng.rb +273 -0
  141. data/lib/synthra/generator/streamer.rb +63 -0
  142. data/lib/synthra/generator/uniqueness.rb +118 -0
  143. data/lib/synthra/initializer.rb +97 -0
  144. data/lib/synthra/limits.rb +279 -0
  145. data/lib/synthra/live_preview.rb +518 -0
  146. data/lib/synthra/loader_config.rb +78 -0
  147. data/lib/synthra/lsp/server.rb +689 -0
  148. data/lib/synthra/migration_generator.rb +301 -0
  149. data/lib/synthra/mixin.rb +174 -0
  150. data/lib/synthra/mock_server.rb +458 -0
  151. data/lib/synthra/native_engine.rb +304 -0
  152. data/lib/synthra/openapi_importer.rb +228 -0
  153. data/lib/synthra/output/json_formatter.rb +40 -0
  154. data/lib/synthra/output/ndjson_formatter.rb +55 -0
  155. data/lib/synthra/parser/ast.rb +1287 -0
  156. data/lib/synthra/parser/lexer.rb +1152 -0
  157. data/lib/synthra/parser/parser.rb +1664 -0
  158. data/lib/synthra/parser/tokens.rb +461 -0
  159. data/lib/synthra/performance_mode.rb +364 -0
  160. data/lib/synthra/personas.rb +397 -0
  161. data/lib/synthra/property_testing.rb +172 -0
  162. data/lib/synthra/quality_metrics.rb +405 -0
  163. data/lib/synthra/rails_test_helper.rb +248 -0
  164. data/lib/synthra/registry.rb +533 -0
  165. data/lib/synthra/relationships.rb +193 -0
  166. data/lib/synthra/repl/enhanced_repl.rb +607 -0
  167. data/lib/synthra/repl/formatter.rb +191 -0
  168. data/lib/synthra/scenarios.rb +423 -0
  169. data/lib/synthra/schema.rb +605 -0
  170. data/lib/synthra/schema_inheritance.rb +104 -0
  171. data/lib/synthra/schema_versioning.rb +212 -0
  172. data/lib/synthra/snapshot_testing.rb +199 -0
  173. data/lib/synthra/time_travel.rb +338 -0
  174. data/lib/synthra/type_definitions.rb +274 -0
  175. data/lib/synthra/types/address_location/addresses.rb +125 -0
  176. data/lib/synthra/types/address_location/airports.rb +200 -0
  177. data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
  178. data/lib/synthra/types/address_location/locations.rb +406 -0
  179. data/lib/synthra/types/base.rb +48 -0
  180. data/lib/synthra/types/commerce_products/commerce.rb +119 -0
  181. data/lib/synthra/types/commerce_products/companies.rb +71 -0
  182. data/lib/synthra/types/commerce_products/construction.rb +126 -0
  183. data/lib/synthra/types/commerce_products/products.rb +205 -0
  184. data/lib/synthra/types/core/collections.rb +513 -0
  185. data/lib/synthra/types/core/defaults.rb +76 -0
  186. data/lib/synthra/types/core/enums.rb +102 -0
  187. data/lib/synthra/types/core/identifiers.rb +445 -0
  188. data/lib/synthra/types/core/primitives.rb +586 -0
  189. data/lib/synthra/types/core/references.rb +466 -0
  190. data/lib/synthra/types/core/sequences.rb +304 -0
  191. data/lib/synthra/types/crypto/crypto.rb +162 -0
  192. data/lib/synthra/types/date_time/dates.rb +387 -0
  193. data/lib/synthra/types/finance_banking/banking.rb +424 -0
  194. data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
  195. data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
  196. data/lib/synthra/types/formula.rb +184 -0
  197. data/lib/synthra/types/health_medical/medical.rb +150 -0
  198. data/lib/synthra/types/hostile_payloads.rb +122 -0
  199. data/lib/synthra/types/json_array.rb +51 -0
  200. data/lib/synthra/types/media_entertainment/media.rb +62 -0
  201. data/lib/synthra/types/naughty_string.rb +30 -0
  202. data/lib/synthra/types/personal_names/chinese.rb +41 -0
  203. data/lib/synthra/types/personal_names/identifiers.rb +187 -0
  204. data/lib/synthra/types/personal_names/names.rb +246 -0
  205. data/lib/synthra/types/personal_names/national_id.rb +89 -0
  206. data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
  207. data/lib/synthra/types/regex.rb +248 -0
  208. data/lib/synthra/types/registry.rb +182 -0
  209. data/lib/synthra/types/repeating_element.rb +50 -0
  210. data/lib/synthra/types/scenario.rb +29 -0
  211. data/lib/synthra/types/technology_internet/apps.rb +67 -0
  212. data/lib/synthra/types/technology_internet/communication.rb +162 -0
  213. data/lib/synthra/types/technology_internet/devices.rb +80 -0
  214. data/lib/synthra/types/technology_internet/formats.rb +139 -0
  215. data/lib/synthra/types/technology_internet/networking.rb +143 -0
  216. data/lib/synthra/types/template.rb +92 -0
  217. data/lib/synthra/types/text_content/business.rb +128 -0
  218. data/lib/synthra/types/text_content/colors.rb +70 -0
  219. data/lib/synthra/types/text_content/misc.rb +237 -0
  220. data/lib/synthra/types/text_content/security.rb +130 -0
  221. data/lib/synthra/types/text_content/text_generation.rb +532 -0
  222. data/lib/synthra/types/travel/travel.rb +150 -0
  223. data/lib/synthra/utils/string_distance.rb +133 -0
  224. data/lib/synthra/validator/dsl_validator.rb +339 -0
  225. data/lib/synthra/validator/path_validator.rb +615 -0
  226. data/lib/synthra/version.rb +35 -0
  227. data/lib/synthra/webhook_simulator.rb +341 -0
  228. data/lib/synthra.rb +259 -0
  229. data/schemas/address.dsl +16 -0
  230. data/schemas/api_response.dsl +8 -0
  231. data/schemas/error_payload.dsl +9 -0
  232. data/schemas/order.dsl +10 -0
  233. data/schemas/order_item.dsl +8 -0
  234. data/schemas/payment.dsl +11 -0
  235. data/schemas/social_post.dsl +13 -0
  236. data/schemas/user.dsl +10 -0
  237. data/scripts/batch_fix_all.rb +96 -0
  238. data/scripts/delete_old_files.rb +32 -0
  239. data/scripts/fix_all_grouped_files.rb +137 -0
  240. data/scripts/fix_all_indentation.rb +48 -0
  241. data/scripts/fix_all_syntax.rb +124 -0
  242. data/scripts/fix_grouped_files.rb +184 -0
  243. data/scripts/fix_syntax_errors.rb +108 -0
  244. data/scripts/group_domain_types.rb +112 -0
  245. data/scripts/group_domain_types_fixed.rb +150 -0
  246. data/scripts/merge_domains_to_one_file.rb +68 -0
  247. data/scripts/move_existing_types.rb +130 -0
  248. data/scripts/split_grouped_types.rb +142 -0
  249. data/tech_docs/README.md +134 -0
  250. data/tech_docs/advanced/streaming.md +405 -0
  251. data/tech_docs/advanced/thread_safety.md +253 -0
  252. data/tech_docs/api/overview.md +485 -0
  253. data/tech_docs/appendices/type_chart.md +193 -0
  254. data/tech_docs/basic_concepts.md +383 -0
  255. data/tech_docs/behaviors/overview.md +346 -0
  256. data/tech_docs/dsl/complex_types.md +790 -0
  257. data/tech_docs/dsl/core_types.md +464 -0
  258. data/tech_docs/dsl/datetime_types.md +325 -0
  259. data/tech_docs/dsl/field_modifiers.md +414 -0
  260. data/tech_docs/dsl/grammar.md +431 -0
  261. data/tech_docs/dsl/schema_definition.md +399 -0
  262. data/tech_docs/export/README.md +276 -0
  263. data/tech_docs/installation.md +273 -0
  264. data/tech_docs/integration/ci_cd.md +707 -0
  265. data/tech_docs/integration/ci_cd_guide.md +579 -0
  266. data/tech_docs/integration/factory_bot.md +485 -0
  267. data/tech_docs/integration/rails.md +630 -0
  268. data/tech_docs/integration/rspec.md +449 -0
  269. data/tech_docs/modes/overview.md +350 -0
  270. data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
  271. data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
  272. data/tech_docs/quick_start.md +256 -0
  273. data/tech_docs/templates/README.md +805 -0
  274. data/tech_docs/tutorials/advanced.md +371 -0
  275. data/tech_docs/tutorials/getting_started.md +189 -0
  276. data/tech_docs/tutorials/intermediate.md +231 -0
  277. data/tech_docs/tutorials/template_gallery.md +569 -0
  278. data/tech_example/01_basic_usage.rb +238 -0
  279. data/tech_example/02_types_demo.rb +336 -0
  280. data/tech_example/04_cli_usage.md +429 -0
  281. data/tech_example/05_database_seeding.rb +283 -0
  282. data/tech_example/07_rspec_integration.rb +359 -0
  283. data/tech_example/10_custom_types.rb +387 -0
  284. data/tech_example/12_behaviors.rb +372 -0
  285. data/tech_example/13_twitter_dm_example.rb +120 -0
  286. data/tech_example/14_exact_json_structure.rb +253 -0
  287. data/tech_example/16_lsp_server.rb +56 -0
  288. data/tech_example/17_property_testing.rb +92 -0
  289. data/tech_example/18_enhanced_repl.rb +120 -0
  290. data/tech_example/19_security_fuzzing.rb +145 -0
  291. data/tech_example/NEW_FEATURES.md +169 -0
  292. data/tech_example/README.md +118 -0
  293. data/tech_example/schemas/api_response.dsl +123 -0
  294. data/tech_example/schemas/ecommerce.dsl +121 -0
  295. data/tech_example/schemas/twitter_dm.dsl +109 -0
  296. data/tech_example/schemas/user.dsl +36 -0
  297. data/vscode-extension/README.md +246 -0
  298. data/vscode-extension/language-configuration.json +31 -0
  299. data/vscode-extension/package.json +55 -0
  300. data/vscode-extension/snippets/fakedatadsl.json +198 -0
  301. data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
  302. metadata +478 -0
@@ -0,0 +1,901 @@
1
+ # FakeDataDSL Performance Optimization Guide
2
+
3
+ A comprehensive guide to achieving maximum performance while maintaining data quality with Faker.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Executive Summary](#executive-summary)
10
+ - [Performance Tiers](#performance-tiers)
11
+ - [Baseline Analysis](#baseline-analysis)
12
+ - [Optimization Strategies](#optimization-strategies)
13
+ - [Tier 1: Standard Engine](#tier-1-standard-engine)
14
+ - [Tier 2: Streaming Engine](#tier-2-streaming-engine)
15
+ - [Tier 3: Cached Faker Engine](#tier-3-cached-faker-engine)
16
+ - [Tier 4: Pooled Engine](#tier-4-pooled-engine)
17
+ - [Tier 5: Native Extension](#tier-5-native-extension)
18
+ - [Detailed Comparison](#detailed-comparison)
19
+ - [Memory Optimization](#memory-optimization)
20
+ - [Faker Integration Strategy](#faker-integration-strategy)
21
+ - [Implementation Guide](#implementation-guide)
22
+ - [Benchmarks](#benchmarks)
23
+ - [Decision Matrix](#decision-matrix)
24
+
25
+ ---
26
+
27
+ ## Executive Summary
28
+
29
+ | Target | Engine | Time for 10M | Memory | Faker Support | Data Uniqueness |
30
+ |--------|--------|--------------|--------|---------------|-----------------|
31
+ | Development | Standard | ~8 min | Growing | ✅ Full | 100% unique |
32
+ | Production | Streaming | ~100 sec | O(1) | ✅ Full | 100% unique |
33
+ | High Volume | Cached Faker | ~40 sec | O(pool) | ✅ Cached | 95% unique |
34
+ | Extreme Volume | Pooled | ~5-10 sec | O(pool) | ✅ Pre-gen | IDs unique |
35
+ | Maximum Speed | Native (Rust + fake-rs) | **~3 sec** | O(1) | ✅ Full | IDs unique |
36
+
37
+ **Recommendation:**
38
+ - For most Ruby-only setups: use **Cached Faker Engine** (Tier 3) - 300K records/sec with Faker quality
39
+ - For maximum performance: use **Native Rust Extension with fake-rs** (Tier 5) - 3-4M records/sec with full faker functionality
40
+ - Default threads: **2** (configurable, use `threads: 0` for all cores)
41
+
42
+ > 💡 **Key Insight:** [fake-rs](https://github.com/cksac/fake-rs) is a native Rust library that provides the same faker functionality as Ruby's Faker gem, but runs at native speed. This eliminates the Ruby-Rust boundary crossing overhead entirely! See [NATIVE_RUST_EXTENSION.md](./NATIVE_RUST_EXTENSION.md) for implementation details.
43
+
44
+ ---
45
+
46
+ ## Performance Tiers
47
+
48
+ ```
49
+ ┌─────────────────────────────────────────────────────────────────────────────┐
50
+ │ PERFORMANCE TIERS OVERVIEW │
51
+ ├─────────────────────────────────────────────────────────────────────────────┤
52
+ │ │
53
+ │ Tier 1: Standard Engine │
54
+ │ ├── Speed: 20K records/sec │
55
+ │ ├── Memory: O(n) - grows with records │
56
+ │ ├── Faker: Full support, every call │
57
+ │ └── Use: Development, small batches │
58
+ │ │
59
+ │ Tier 2: Streaming Engine │
60
+ │ ├── Speed: 50-100K records/sec │
61
+ │ ├── Memory: O(1) - constant │
62
+ │ ├── Faker: Full support, every call │
63
+ │ └── Use: Production, unlimited records │
64
+ │ │
65
+ │ Tier 3: Cached Faker Engine │
66
+ │ ├── Speed: 200-300K records/sec │
67
+ │ ├── Memory: O(pool) - pool size only │
68
+ │ ├── Faker: Cached pools, sampled │
69
+ │ └── Use: High-volume testing, data lakes │
70
+ │ │
71
+ │ Tier 4: Pooled Engine │
72
+ │ ├── Speed: 500K-2M records/sec │
73
+ │ ├── Memory: O(pool) - record pool │
74
+ │ ├── Faker: Pre-generated at startup │
75
+ │ └── Use: Extreme volume, benchmarks │
76
+ │ │
77
+ │ Tier 5: Native Extension (Rust + fake-rs) │
78
+ │ ├── Speed: 2M/sec (2 threads) to 4M/sec (all cores) │
79
+ │ ├── Memory: O(1) - minimal │
80
+ │ ├── Faker: ✅ Full via fake-rs (native Rust faker) │
81
+ │ ├── Threads: Default 2 (configurable, 0 = all cores) │
82
+ │ └── Use: Maximum performance with Faker quality │
83
+ │ │
84
+ └─────────────────────────────────────────────────────────────────────────────┘
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Baseline Analysis
90
+
91
+ ### Why Faker is Slow (But Worth It)
92
+
93
+ Faker provides realistic, locale-aware, contextually appropriate data. Here's the cost:
94
+
95
+ ```
96
+ ┌─────────────────────────────────────────────────────────────────────────────┐
97
+ │ FAKER OPERATION COSTS │
98
+ ├─────────────────────────────────────────────────────────────────────────────┤
99
+ │ Operation │ Time (μs) │ Calls/Record │ Total (μs) │
100
+ ├────────────────────────────────────┼───────────┼──────────────┼────────────┤
101
+ │ Faker::Name.name │ 15-30 │ 1 │ 15-30 │
102
+ │ Faker::Internet.email │ 20-40 │ 1 │ 20-40 │
103
+ │ Faker::Address.full_address │ 50-100 │ 1 │ 50-100 │
104
+ │ Faker::Lorem.paragraph │ 30-60 │ 1 │ 30-60 │
105
+ │ Faker::PhoneNumber.phone_number │ 10-20 │ 1 │ 10-20 │
106
+ │ Faker::Company.name │ 15-25 │ 1 │ 15-25 │
107
+ │ UUID generation │ 1-2 │ 1 │ 1-2 │
108
+ │ Random number │ 0.1 │ 5 │ 0.5 │
109
+ ├────────────────────────────────────┼───────────┼──────────────┼────────────┤
110
+ │ TOTAL per record (10 fields) │ │ │ ~150-300 │
111
+ └─────────────────────────────────────────────────────────────────────────────┘
112
+
113
+ At 200μs per record: 5,000 records/sec maximum
114
+ At 150μs per record: 6,666 records/sec maximum
115
+
116
+ With overhead (memory, I/O): ~3,000-5,000 records/sec realistic
117
+ ```
118
+
119
+ ### Bottleneck Breakdown
120
+
121
+ ```
122
+ ┌─────────────────────────────────────────────────────────────────────────────┐
123
+ │ WHERE TIME IS SPENT │
124
+ ├─────────────────────────────────────────────────────────────────────────────┤
125
+ │ │
126
+ │ ████████████████████████████████████░░░░░░░░░░░░░ 70% Faker Calls │
127
+ │ ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 15% Memory Allocation │
128
+ │ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 8% Type Lookup/Mutex │
129
+ │ ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5% I/O (JSON/File) │
130
+ │ █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2% Other Overhead │
131
+ │ │
132
+ └─────────────────────────────────────────────────────────────────────────────┘
133
+
134
+ Key Insight: Faker calls dominate. Reducing Faker calls = biggest gain.
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Optimization Strategies
140
+
141
+ ### Tier 1: Standard Engine
142
+
143
+ **Current default implementation.**
144
+
145
+ #### Architecture
146
+
147
+ ```
148
+ ┌─────────────────────────────────────────────────────────────────────────────┐
149
+ │ STANDARD ENGINE │
150
+ ├─────────────────────────────────────────────────────────────────────────────┤
151
+ │ │
152
+ │ for each record: │
153
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
154
+ │ │ 1. Create new Context object [200ns] │ │
155
+ │ │ 2. Create new Applicator object [100ns] │ │
156
+ │ │ 3. For each field: │ │
157
+ │ │ ├── Lookup type (mutex) [100ns] │ │
158
+ │ │ ├── Call Faker [10-50μs] │ │
159
+ │ │ └── Store in result hash [50ns] │ │
160
+ │ │ 4. Apply behaviors [100ns] │ │
161
+ │ │ 5. Return record │ │
162
+ │ └─────────────────────────────────────────────────────────────────────┘ │
163
+ │ │
164
+ │ results.push(record) ← Memory grows with each record │
165
+ │ │
166
+ └─────────────────────────────────────────────────────────────────────────────┘
167
+ ```
168
+
169
+ #### Characteristics
170
+
171
+ | Metric | Value |
172
+ |--------|-------|
173
+ | **Speed** | 15,000 - 25,000 records/sec |
174
+ | **Memory** | ~500 bytes/record (grows linearly) |
175
+ | **10M Records** | ~8 minutes, ~5GB RAM |
176
+ | **Faker Support** | Full - every field, every record |
177
+ | **Uniqueness** | 100% unique data |
178
+ | **Thread Safety** | ✅ Yes (mutex protected) |
179
+
180
+ #### Best For
181
+
182
+ - Development and debugging
183
+ - Small batches (< 10K records)
184
+ - When memory is not a constraint
185
+ - When you need full Faker variety
186
+
187
+ #### Code Example
188
+
189
+ ```ruby
190
+ # Standard usage
191
+ schema = FakeDataDSL.load('user.dsl')
192
+ records = schema.generate_many(1000, seed: 42)
193
+ ```
194
+
195
+ ---
196
+
197
+ ### Tier 2: Streaming Engine
198
+
199
+ **Memory-constant generation with full Faker support.**
200
+
201
+ #### Architecture
202
+
203
+ ```
204
+ ┌─────────────────────────────────────────────────────────────────────────────┐
205
+ │ STREAMING ENGINE │
206
+ ├─────────────────────────────────────────────────────────────────────────────┤
207
+ │ │
208
+ │ Pre-computed (once): │
209
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
210
+ │ │ • Field specs (frozen) │ │
211
+ │ │ • Type generators (cached) │ │
212
+ │ │ • Configuration values │ │
213
+ │ └─────────────────────────────────────────────────────────────────────┘ │
214
+ │ │
215
+ │ for each record: │
216
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
217
+ │ │ 1. Reuse Context object (reset, not recreate) [50ns] │ │
218
+ │ │ 2. Reuse Applicator object [0ns] │ │
219
+ │ │ 3. For each field: │ │
220
+ │ │ ├── Use cached type generator [10ns] │ │
221
+ │ │ ├── Call Faker [10-50μs] │ │
222
+ │ │ └── Store in reused hash [30ns] │ │
223
+ │ │ 4. Yield/write record immediately │ │
224
+ │ │ 5. Clear buffers for reuse │ │
225
+ │ └─────────────────────────────────────────────────────────────────────┘ │
226
+ │ │
227
+ │ yield record ← Memory stays constant │
228
+ │ │
229
+ └─────────────────────────────────────────────────────────────────────────────┘
230
+ ```
231
+
232
+ #### Characteristics
233
+
234
+ | Metric | Value |
235
+ |--------|-------|
236
+ | **Speed** | 50,000 - 100,000 records/sec |
237
+ | **Memory** | ~100KB constant (regardless of count) |
238
+ | **10M Records** | ~100-200 seconds, ~100KB RAM |
239
+ | **Faker Support** | Full - every field, every record |
240
+ | **Uniqueness** | 100% unique data |
241
+ | **Thread Safety** | ✅ Yes (thread-local state) |
242
+
243
+ #### Improvements Over Standard
244
+
245
+ | Optimization | Benefit |
246
+ |--------------|---------|
247
+ | Pre-computed field specs | -15% time |
248
+ | Reused Context objects | -10% time, -90% memory |
249
+ | Cached type lookups | -10% time |
250
+ | Streaming output | O(1) memory |
251
+ | Buffered I/O | -5% time |
252
+
253
+ #### Best For
254
+
255
+ - Production workloads
256
+ - Large batches (100K+ records)
257
+ - Memory-constrained environments
258
+ - Streaming to files/databases
259
+
260
+ #### Code Example
261
+
262
+ ```ruby
263
+ engine = FakeDataDSL::Generator::StreamingEngine.new(schema)
264
+
265
+ # Stream to file (constant memory)
266
+ engine.to_file(10_000_000, '/tmp/users.jsonl', seed: 42)
267
+
268
+ # Stream with block processing
269
+ engine.each(10_000_000, seed: 42) do |record|
270
+ # Process immediately, record is recycled
271
+ database.insert(record)
272
+ end
273
+ ```
274
+
275
+ ---
276
+
277
+ ### Tier 3: Cached Faker Engine
278
+
279
+ **Pre-generated Faker pools for 3-5x speedup while maintaining variety.**
280
+
281
+ #### Architecture
282
+
283
+ ```
284
+ ┌─────────────────────────────────────────────────────────────────────────────┐
285
+ │ CACHED FAKER ENGINE │
286
+ ├─────────────────────────────────────────────────────────────────────────────┤
287
+ │ │
288
+ │ Startup (one-time cost): │
289
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
290
+ │ │ Generate Faker pools: │ │
291
+ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
292
+ │ │ │ names[10K] │ │ emails[10K] │ │ phones[10K] │ │ cities[10K] │ │ │
293
+ │ │ │ "John Doe" │ │ "j@x.com" │ │ "555-1234" │ │ "New York" │ │ │
294
+ │ │ │ "Jane Doe" │ │ "k@y.com" │ │ "555-5678" │ │ "Chicago" │ │ │
295
+ │ │ │ ... │ │ ... │ │ ... │ │ ... │ │ │
296
+ │ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
297
+ │ │ │ │
298
+ │ │ Time: ~5-10 seconds for 10K entries per type │ │
299
+ │ │ Memory: ~5-20MB for all pools │ │
300
+ │ └─────────────────────────────────────────────────────────────────────┘ │
301
+ │ │
302
+ │ Runtime (per record): │
303
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
304
+ │ │ 1. Generate unique ID (always fresh) [1μs] │ │
305
+ │ │ 2. Sample from pools: │ │
306
+ │ │ ├── name = names[rand(10000)] [10ns] │ │
307
+ │ │ ├── email = emails[rand(10000)] + index [20ns] │ │
308
+ │ │ ├── phone = phones[rand(10000)] [10ns] │ │
309
+ │ │ └── ... (array index, not Faker call!) │ │
310
+ │ │ 3. Generate numbers/booleans (fast) [100ns] │ │
311
+ │ │ 4. Yield record │ │
312
+ │ └─────────────────────────────────────────────────────────────────────┘ │
313
+ │ │
314
+ │ Key: Faker called 10K times at startup, then NEVER during generation │
315
+ │ │
316
+ └─────────────────────────────────────────────────────────────────────────────┘
317
+ ```
318
+
319
+ #### Pool Configuration
320
+
321
+ ```ruby
322
+ # Default pool sizes (configurable)
323
+ FAKER_POOLS = {
324
+ # Personal
325
+ first_name: { size: 5_000, generator: -> { Faker::Name.first_name } },
326
+ last_name: { size: 5_000, generator: -> { Faker::Name.last_name } },
327
+ full_name: { size: 10_000, generator: -> { Faker::Name.name } },
328
+ email_domain: { size: 1_000, generator: -> { Faker::Internet.domain_name } },
329
+
330
+ # Contact
331
+ phone: { size: 5_000, generator: -> { Faker::PhoneNumber.phone_number } },
332
+ cell_phone: { size: 5_000, generator: -> { Faker::PhoneNumber.cell_phone } },
333
+
334
+ # Address
335
+ street: { size: 10_000, generator: -> { Faker::Address.street_address } },
336
+ city: { size: 5_000, generator: -> { Faker::Address.city } },
337
+ state: { size: 100, generator: -> { Faker::Address.state } },
338
+ zip_code: { size: 10_000, generator: -> { Faker::Address.zip_code } },
339
+ country: { size: 250, generator: -> { Faker::Address.country } },
340
+
341
+ # Business
342
+ company: { size: 5_000, generator: -> { Faker::Company.name } },
343
+ job_title: { size: 2_000, generator: -> { Faker::Job.title } },
344
+
345
+ # Content
346
+ sentence: { size: 10_000, generator: -> { Faker::Lorem.sentence } },
347
+ paragraph: { size: 5_000, generator: -> { Faker::Lorem.paragraph } },
348
+
349
+ # Internet
350
+ username: { size: 10_000, generator: -> { Faker::Internet.username } },
351
+ url: { size: 5_000, generator: -> { Faker::Internet.url } },
352
+ ip_address: { size: 10_000, generator: -> { Faker::Internet.ip_v4_address } },
353
+
354
+ # Finance
355
+ credit_card: { size: 5_000, generator: -> { Faker::Finance.credit_card } },
356
+ bank_name: { size: 500, generator: -> { Faker::Bank.name } },
357
+ }
358
+ ```
359
+
360
+ #### Characteristics
361
+
362
+ | Metric | Value |
363
+ |--------|-------|
364
+ | **Speed** | 200,000 - 300,000 records/sec |
365
+ | **Memory** | ~20MB (pools) + 100KB (runtime) |
366
+ | **10M Records** | ~35-50 seconds |
367
+ | **Startup Time** | ~5-10 seconds (pool generation) |
368
+ | **Faker Support** | ✅ All Faker types (cached) |
369
+ | **Uniqueness** | IDs: 100% unique, Other: 10K variations |
370
+ | **Thread Safety** | ✅ Yes (pools are read-only) |
371
+
372
+ #### Uniqueness Strategy
373
+
374
+ ```
375
+ ┌─────────────────────────────────────────────────────────────────────────────┐
376
+ │ UNIQUENESS HANDLING │
377
+ ├─────────────────────────────────────────────────────────────────────────────┤
378
+ │ │
379
+ │ Field Type Strategy Uniqueness │
380
+ │ ───────────────────────────────────────────────────────────────────────── │
381
+ │ uuid/id Always generated fresh 100% unique │
382
+ │ email pool[rand] + index suffix 100% unique │
383
+ │ username pool[rand] + index suffix 100% unique │
384
+ │ name pool[rand] 10K variations │
385
+ │ phone pool[rand] 5K variations │
386
+ │ address composite from pools 50M+ combinations │
387
+ │ text/lorem pool[rand] 10K variations │
388
+ │ number Random in range Effectively unique │
389
+ │ boolean Random N/A │
390
+ │ timestamp Base + random offset Effectively unique │
391
+ │ │
392
+ │ Result: For 10M records, IDs are unique, other fields have realistic │
393
+ │ variation without detectable patterns. │
394
+ │ │
395
+ └─────────────────────────────────────────────────────────────────────────────┘
396
+ ```
397
+
398
+ #### Best For
399
+
400
+ - High-volume data generation (1M+ records)
401
+ - Test data factories
402
+ - Data lake population
403
+ - Load testing data
404
+ - When you need Faker variety but faster
405
+
406
+ #### Code Example
407
+
408
+ ```ruby
409
+ # Create engine (generates pools at startup)
410
+ engine = FakeDataDSL::Generator::CachedFakerEngine.new(schema, pool_size: 10_000)
411
+
412
+ # Generate 10M records
413
+ engine.to_file(10_000_000, '/tmp/users.jsonl', seed: 42)
414
+
415
+ # Custom pool configuration
416
+ engine = FakeDataDSL::Generator::CachedFakerEngine.new(schema,
417
+ pool_config: {
418
+ name: { size: 50_000 }, # More name variety
419
+ email: { size: 100_000 }, # More email variety
420
+ city: { size: 10_000 } # More city variety
421
+ }
422
+ )
423
+ ```
424
+
425
+ ---
426
+
427
+ ### Tier 4: Pooled Engine
428
+
429
+ **Pre-generated complete records for maximum speed.**
430
+
431
+ #### Architecture
432
+
433
+ ```
434
+ ┌─────────────────────────────────────────────────────────────────────────────┐
435
+ │ POOLED ENGINE │
436
+ ├─────────────────────────────────────────────────────────────────────────────┤
437
+ │ │
438
+ │ Startup (one-time cost): │
439
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
440
+ │ │ Generate complete record pool using Standard Engine: │ │
441
+ │ │ │ │
442
+ │ │ pool[0] = { id: "...", name: "John", email: "j@x.com", ... } │ │
443
+ │ │ pool[1] = { id: "...", name: "Jane", email: "k@y.com", ... } │ │
444
+ │ │ pool[2] = { id: "...", name: "Bob", email: "b@z.com", ... } │ │
445
+ │ │ ... │ │
446
+ │ │ pool[99K] = { id: "...", name: "Amy", email: "a@w.com", ... } │ │
447
+ │ │ │ │
448
+ │ │ Time: ~30-60 seconds for 100K records │ │
449
+ │ │ Memory: ~50-100MB for pool │ │
450
+ │ └─────────────────────────────────────────────────────────────────────┘ │
451
+ │ │
452
+ │ Runtime (per record): │
453
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
454
+ │ │ 1. Pick random template: template = pool[rand(100000)] [5ns] │ │
455
+ │ │ 2. Generate unique ID [500ns] │ │
456
+ │ │ 3. Clone + override ID: record = template.merge(id: x) [200ns] │ │
457
+ │ │ 4. Yield record │ │
458
+ │ └─────────────────────────────────────────────────────────────────────┘ │
459
+ │ │
460
+ │ Total per record: ~1μs = 1,000,000 records/sec theoretical │
461
+ │ With I/O overhead: ~500,000 - 1,000,000 records/sec actual │
462
+ │ │
463
+ └─────────────────────────────────────────────────────────────────────────────┘
464
+ ```
465
+
466
+ #### Characteristics
467
+
468
+ | Metric | Value |
469
+ |--------|-------|
470
+ | **Speed** | 500,000 - 2,000,000 records/sec |
471
+ | **Memory** | ~100MB (pool) + 100KB (runtime) |
472
+ | **10M Records** | ~5-20 seconds |
473
+ | **Startup Time** | ~30-60 seconds (pool generation) |
474
+ | **Faker Support** | ✅ Full (at pool generation) |
475
+ | **Uniqueness** | IDs: 100%, Other: 100K templates |
476
+ | **Thread Safety** | ✅ Yes (pool is read-only) |
477
+
478
+ #### Comparison: Cached Faker vs Pooled
479
+
480
+ ```
481
+ ┌─────────────────────────────────────────────────────────────────────────────┐
482
+ │ CACHED FAKER vs POOLED │
483
+ ├─────────────────────────────────────────────────────────────────────────────┤
484
+ │ │
485
+ │ Cached Faker Pooled │
486
+ │ ──────────── ────── │
487
+ │ What's Cached Individual fields Complete records │
488
+ │ Pool Size 10K per field type 100K full records │
489
+ │ Memory ~20MB ~100MB │
490
+ │ Combinations Billions (cross-product) 100K templates │
491
+ │ Speed 200-300K/sec 500K-2M/sec │
492
+ │ Field Correlation Random (uncorrelated) Preserved from Faker │
493
+ │ Startup Time ~10 sec ~60 sec │
494
+ │ │
495
+ │ Example: │
496
+ │ ───────────────────────────────────────────────────────────────────────── │
497
+ │ Cached Faker: name="John" may have email="sarah@example.com" (uncorrelated)│
498
+ │ Pooled: name="John" always has email="john.doe@example.com" │
499
+ │ (correlations preserved from original Faker generation) │
500
+ │ │
501
+ └─────────────────────────────────────────────────────────────────────────────┘
502
+ ```
503
+
504
+ #### Best For
505
+
506
+ - Maximum speed requirements
507
+ - Benchmark data generation
508
+ - When field correlations don't matter
509
+ - Pre-warming test databases
510
+
511
+ #### Code Example
512
+
513
+ ```ruby
514
+ # Create engine (generates pool at startup - takes ~60 seconds)
515
+ engine = FakeDataDSL::Generator::PooledEngine.new(schema, pool_size: 100_000)
516
+
517
+ # Generate 10M records in ~10 seconds
518
+ engine.to_file(10_000_000, '/tmp/users.jsonl', seed: 42)
519
+ ```
520
+
521
+ ---
522
+
523
+ ### Tier 5: Native Extension
524
+
525
+ **Rust/C implementation for maximum performance.**
526
+
527
+ #### Architecture
528
+
529
+ ```
530
+ ┌─────────────────────────────────────────────────────────────────────────────┐
531
+ │ NATIVE EXTENSION │
532
+ ├─────────────────────────────────────────────────────────────────────────────┤
533
+ │ │
534
+ │ Ruby Layer (thin wrapper): │
535
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
536
+ │ │ • Parse schema │ │
537
+ │ │ • Convert to native field specs │ │
538
+ │ │ • Call native generation │ │
539
+ │ │ • Return results to Ruby │ │
540
+ │ └─────────────────────────────────────────────────────────────────────┘ │
541
+ │ │ │
542
+ │ ▼ │
543
+ │ Native Layer (Rust/C): │
544
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
545
+ │ │ • Ultra-fast RNG (Xoshiro256++) │ │
546
+ │ │ • SIMD-optimized string generation │ │
547
+ │ │ • Zero-copy JSON serialization │ │
548
+ │ │ • Parallel generation with Rayon │ │
549
+ │ │ • Direct file I/O with memory-mapped buffers │ │
550
+ │ │ │ │
551
+ │ │ Per record: ~100-200 nanoseconds │ │
552
+ │ │ Throughput: 5-10M records/sec per core │ │
553
+ │ └─────────────────────────────────────────────────────────────────────┘ │
554
+ │ │
555
+ │ Limitations: │
556
+ │ • No Faker (would require Ruby callback = slow) │
557
+ │ • Limited to types implementable in native code │
558
+ │ • UUID, numbers, booleans, simple text, enums │
559
+ │ │
560
+ └─────────────────────────────────────────────────────────────────────────────┘
561
+ ```
562
+
563
+ #### Characteristics
564
+
565
+ | Metric | Value |
566
+ |--------|-------|
567
+ | **Speed** | 2,000,000 - 10,000,000 records/sec |
568
+ | **Memory** | ~10MB constant |
569
+ | **10M Records** | 1-5 seconds |
570
+ | **Faker Support** | ❌ No (native types only) |
571
+ | **Uniqueness** | 100% (native RNG) |
572
+ | **Thread Safety** | ✅ Yes (Rust safety) |
573
+ | **Dependencies** | Rust toolchain required |
574
+
575
+ #### Supported Types (Native)
576
+
577
+ | Type | Native Implementation |
578
+ |------|----------------------|
579
+ | `uuid` | ✅ UUID v4 via native RNG |
580
+ | `number` | ✅ Native integer/float |
581
+ | `boolean` | ✅ Native random |
582
+ | `text` | ✅ Random alphanumeric |
583
+ | `enum` | ✅ Array sampling |
584
+ | `timestamp` | ✅ Base + offset |
585
+ | `name` | ⚠️ Simple pool (not Faker) |
586
+ | `email` | ⚠️ Generated pattern |
587
+ | `address` | ❌ Use Ruby fallback |
588
+ | `lorem` | ❌ Use Ruby fallback |
589
+
590
+ #### Best For
591
+
592
+ - Absolute maximum performance
593
+ - Simple schemas only
594
+ - When Faker variety isn't needed
595
+ - Synthetic benchmark data
596
+
597
+ ---
598
+
599
+ ## Detailed Comparison
600
+
601
+ ### Speed Comparison
602
+
603
+ ```
604
+ ┌─────────────────────────────────────────────────────────────────────────────┐
605
+ │ RECORDS PER SECOND │
606
+ ├─────────────────────────────────────────────────────────────────────────────┤
607
+ │ │
608
+ │ Native ████████████████████████████████████████████████████ 5,000,000 │
609
+ │ Pooled ██████████████████████████████████████░░░░░░░░░░░░░░ 1,500,000 │
610
+ │ Cached ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 250,000 │
611
+ │ Streaming █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 75,000 │
612
+ │ Standard ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 20,000 │
613
+ │ │
614
+ │ 0 1M 2M 3M 4M 5M │
615
+ │ │
616
+ └─────────────────────────────────────────────────────────────────────────────┘
617
+ ```
618
+
619
+ ### Time for 10 Million Records
620
+
621
+ ```
622
+ ┌─────────────────────────────────────────────────────────────────────────────┐
623
+ │ TIME FOR 10M RECORDS │
624
+ ├─────────────────────────────────────────────────────────────────────────────┤
625
+ │ │
626
+ │ Engine Time With YJIT Practical Use Case │
627
+ │ ───────────────────────────────────────────────────────────────────────── │
628
+ │ Standard ~8 minutes ~5 minutes Development, small batches │
629
+ │ Streaming ~2 minutes ~80 seconds Production, unlimited size │
630
+ │ Cached ~40 seconds ~25 seconds High-volume testing │
631
+ │ Pooled ~10 seconds ~5 seconds Extreme volume │
632
+ │ Native ~2 seconds N/A Maximum speed, simple data │
633
+ │ │
634
+ └─────────────────────────────────────────────────────────────────────────────┘
635
+ ```
636
+
637
+ ### Memory Usage
638
+
639
+ ```
640
+ ┌─────────────────────────────────────────────────────────────────────────────┐
641
+ │ MEMORY USAGE FOR 10M RECORDS │
642
+ ├─────────────────────────────────────────────────────────────────────────────┤
643
+ │ │
644
+ │ Engine Peak Memory Memory Pattern │
645
+ │ ───────────────────────────────────────────────────────────────────────── │
646
+ │ Standard ~5 GB Linear growth (500 bytes × 10M) │
647
+ │ Streaming ~100 KB Constant (buffers only) │
648
+ │ Cached ~25 MB Constant (pools + buffers) │
649
+ │ Pooled ~100 MB Constant (record pool + buffers) │
650
+ │ Native ~10 MB Constant (native buffers) │
651
+ │ │
652
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
653
+ │ │ Standard: ▁▂▃▄▅▆▇█████████████████████████████████ 5GB │ │
654
+ │ │ Streaming: ▁░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100KB │ │
655
+ │ │ Cached: ▁▁░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 25MB │ │
656
+ │ │ Pooled: ▁▁▂░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100MB │ │
657
+ │ │ Native: ▁░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 10MB │ │
658
+ │ └─────────────────────────────────────────────────────────────────────┘ │
659
+ │ │
660
+ └─────────────────────────────────────────────────────────────────────────────┘
661
+ ```
662
+
663
+ ### Feature Comparison
664
+
665
+ ```
666
+ ┌─────────────────────────────────────────────────────────────────────────────┐
667
+ │ FEATURE MATRIX │
668
+ ├─────────────────────────────────────────────────────────────────────────────┤
669
+ │ │
670
+ │ Feature Standard Streaming Cached Pooled Native │
671
+ │ ───────────────────────────────────────────────────────────────────────── │
672
+ │ Full Faker Support ✅ ✅ ✅ ✅ ❌ │
673
+ │ All DSL Types ✅ ✅ ✅ ✅ ⚠️ │
674
+ │ 100% Unique Data ✅ ✅ ⚠️ ⚠️ ✅ │
675
+ │ Constant Memory ❌ ✅ ✅ ✅ ✅ │
676
+ │ Thread Safe ✅ ✅ ✅ ✅ ✅ │
677
+ │ Deterministic (seed) ✅ ✅ ✅ ✅ ✅ │
678
+ │ Stream to File ✅ ✅ ✅ ✅ ✅ │
679
+ │ Stream to Block ✅ ✅ ✅ ✅ ✅ │
680
+ │ Behaviors Support ✅ ✅ ⚠️ ⚠️ ❌ │
681
+ │ No Native Dependencies ✅ ✅ ✅ ✅ ❌ │
682
+ │ │
683
+ │ Legend: ✅ Full ⚠️ Partial ❌ None │
684
+ │ │
685
+ └─────────────────────────────────────────────────────────────────────────────┘
686
+ ```
687
+
688
+ ---
689
+
690
+ ## Memory Optimization
691
+
692
+ ### Streaming Output Patterns
693
+
694
+ ```ruby
695
+ # Pattern 1: Direct file streaming (best for large files)
696
+ engine.to_file(count, path)
697
+
698
+ # Pattern 2: Block processing (best for databases)
699
+ engine.each(count) do |record|
700
+ batch << record.dup
701
+ if batch.size >= 1000
702
+ Database.insert_all(batch)
703
+ batch.clear
704
+ end
705
+ end
706
+
707
+ # Pattern 3: Lazy enumeration (best for pipelines)
708
+ engine.stream(count)
709
+ .lazy
710
+ .select { |r| r['age'] > 18 }
711
+ .take(100_000)
712
+ .each { |r| process(r) }
713
+ ```
714
+
715
+ ### Buffer Size Tuning
716
+
717
+ ```ruby
718
+ # Configure buffer sizes for your workload
719
+ FakeDataDSL.configure do |config|
720
+ config.output_buffer_size = 64 * 1024 * 1024 # 64MB for large files
721
+ config.record_buffer_size = 4096 # 4KB per record max
722
+ end
723
+ ```
724
+
725
+ ---
726
+
727
+ ## Faker Integration Strategy
728
+
729
+ ### How Caching Preserves Faker Quality
730
+
731
+ ```
732
+ ┌─────────────────────────────────────────────────────────────────────────────┐
733
+ │ FAKER CACHING STRATEGY │
734
+ ├─────────────────────────────────────────────────────────────────────────────┤
735
+ │ │
736
+ │ Goal: Get Faker's quality data without per-record Faker calls │
737
+ │ │
738
+ │ Step 1: At startup, call Faker 10K+ times per type │
739
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
740
+ │ │ names = 10_000.times.map { Faker::Name.name } │ │
741
+ │ │ # ["John Smith", "Jane Doe", "Robert Wilson", ...] │ │
742
+ │ │ │ │
743
+ │ │ emails = 10_000.times.map { Faker::Internet.email } │ │
744
+ │ │ # ["john.smith@example.com", "jane.doe@test.org", ...] │ │
745
+ │ │ │ │
746
+ │ │ # All the quality, variety, and localization of Faker! │ │
747
+ │ └─────────────────────────────────────────────────────────────────────┘ │
748
+ │ │
749
+ │ Step 2: At runtime, sample from pools (array index = O(1)) │
750
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
751
+ │ │ record[:name] = names[rng.rand(10_000)] # 10ns, not 20μs! │ │
752
+ │ │ record[:email] = make_unique(emails, index) │ │
753
+ │ └─────────────────────────────────────────────────────────────────────┘ │
754
+ │ │
755
+ │ Result: Full Faker quality, 100x faster │
756
+ │ │
757
+ └─────────────────────────────────────────────────────────────────────────────┘
758
+ ```
759
+
760
+ ### Locale Support
761
+
762
+ ```ruby
763
+ # Cached Faker respects locale settings
764
+ Faker::Config.locale = 'de' # German
765
+
766
+ engine = FakeDataDSL::Generator::CachedFakerEngine.new(schema)
767
+ # Pools contain German names: "Hans Müller", "Anna Schmidt", etc.
768
+ ```
769
+
770
+ ---
771
+
772
+ ## Implementation Guide
773
+
774
+ ### Quick Start
775
+
776
+ ```ruby
777
+ # Choose engine based on your needs:
778
+
779
+ # Small batches, full features
780
+ records = schema.generate_many(1000)
781
+
782
+ # Large batches, constant memory
783
+ schema.generate_stream(1_000_000).each { |r| process(r) }
784
+
785
+ # High volume, Faker quality
786
+ engine = FakeDataDSL::Generator::CachedFakerEngine.new(schema)
787
+ engine.to_file(10_000_000, 'data.jsonl')
788
+
789
+ # Maximum speed
790
+ engine = FakeDataDSL::Generator::PooledEngine.new(schema)
791
+ engine.to_file(10_000_000, 'data.jsonl')
792
+ ```
793
+
794
+ ### Configuration Options
795
+
796
+ ```ruby
797
+ FakeDataDSL.configure do |config|
798
+ # Memory settings
799
+ config.output_buffer_size = 64 * 1024 * 1024 # 64MB
800
+ config.context_pool_size = 10 # Reuse 10 contexts
801
+
802
+ # Cache settings
803
+ config.default_pool_size = 10_000 # Faker cache size
804
+ config.type_cache_enabled = true # Cache type lookups
805
+
806
+ # Performance settings
807
+ config.fast_mode = true # Use optimized paths
808
+ config.enable_yjit_hints = true # YJIT optimization
809
+ end
810
+ ```
811
+
812
+ ---
813
+
814
+ ## Benchmarks
815
+
816
+ ### Test Environment
817
+
818
+ ```
819
+ Hardware: Apple M1 Pro, 16GB RAM
820
+ Ruby: 3.3.0 with YJIT
821
+ Schema: 10 fields (uuid, name, email, phone, address, age, active, role, created_at, bio)
822
+ ```
823
+
824
+ ### Results
825
+
826
+ | Engine | 1K | 10K | 100K | 1M | 10M |
827
+ |--------|-----|------|-------|-----|------|
828
+ | Standard | 50ms | 500ms | 5s | 50s | 8min |
829
+ | Streaming | 20ms | 150ms | 1.5s | 15s | 2.5min |
830
+ | Cached | 10ms | 50ms | 400ms | 4s | 40s |
831
+ | Pooled | 5ms | 20ms | 150ms | 1.5s | 12s |
832
+ | Native | 2ms | 5ms | 30ms | 300ms | 3s |
833
+
834
+ ---
835
+
836
+ ## Decision Matrix
837
+
838
+ ### Choose Your Engine
839
+
840
+ ```
841
+ ┌─────────────────────────────────────────────────────────────────────────────┐
842
+ │ DECISION FLOWCHART │
843
+ ├─────────────────────────────────────────────────────────────────────────────┤
844
+ │ │
845
+ │ How many records? │
846
+ │ │ │
847
+ │ ├─► < 10,000 ──────────────────────────────► Standard Engine │
848
+ │ │ (Simple, full features) │
849
+ │ │ │
850
+ │ ├─► 10K - 100K │
851
+ │ │ │ │
852
+ │ │ ├─► Memory constrained? ────────────────► Streaming Engine │
853
+ │ │ │ │
854
+ │ │ └─► Memory available? ──────────────────► Standard Engine │
855
+ │ │ │
856
+ │ ├─► 100K - 1M │
857
+ │ │ │ │
858
+ │ │ ├─► Need Faker variety? ────────────────► Cached Faker Engine │
859
+ │ │ │ │
860
+ │ │ └─► Speed priority? ────────────────────► Pooled Engine │
861
+ │ │ │
862
+ │ └─► > 1M │
863
+ │ │ │
864
+ │ ├─► Need Faker? ────────────────────────► Cached Faker Engine │
865
+ │ │ │
866
+ │ ├─► Simple schema? ─────────────────────► Native Extension │
867
+ │ │ │
868
+ │ └─► Complex schema? ────────────────────► Pooled Engine │
869
+ │ │
870
+ └─────────────────────────────────────────────────────────────────────────────┘
871
+ ```
872
+
873
+ ### Summary Table
874
+
875
+ | Requirement | Recommended Engine |
876
+ |-------------|-------------------|
877
+ | Development/debugging | Standard |
878
+ | Production workloads | Streaming |
879
+ | Test data factories | Cached Faker |
880
+ | Load testing | Pooled |
881
+ | Benchmarks | Native (Rust + fake-rs) |
882
+ | Memory constrained | Streaming or Cached |
883
+ | Maximum Faker variety | Cached Faker or Native |
884
+ | Maximum speed | Native (Rust + fake-rs) ⭐ |
885
+ | 10M in < 1 minute | Cached or Pooled |
886
+ | 10M in < 10 seconds | Native (Rust + fake-rs) ⭐ |
887
+
888
+ ---
889
+
890
+ ## Next Steps
891
+
892
+ 1. [Streaming Engine Implementation](./streaming_engine.md)
893
+ 2. [Cached Faker Engine Implementation](./cached_faker_engine.md)
894
+ 3. [Pooled Engine Implementation](./pooled_engine.md)
895
+ 4. [Native Rust Extension with fake-rs](./NATIVE_RUST_EXTENSION.md) ⭐ **Recommended for maximum performance**
896
+ 5. [Benchmark Suite](./benchmarks.md)
897
+
898
+ ---
899
+
900
+ *Last updated: January 2026*
901
+