datahike-browser-tests 1.0.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 (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
package/bb.edn ADDED
@@ -0,0 +1,269 @@
1
+ {:min-bb-version "0.8.0"
2
+ :pods {org.babashka/tools-deps-native {:version "0.1.7"}
3
+ clj-kondo/clj-kondo {:version "2025.07.28"}}
4
+ :deps {datahike/bb {:local/root "bb"}
5
+ org.babashka/http-client {:mvn/version "0.4.22"}}
6
+ :tasks {:requires [[babashka.fs :as fs]
7
+ [babashka.process :as process]
8
+ [clojure.edn :as edn]
9
+ [clojure.string :as str]
10
+ [pod.borkdude.clj-kondo :as clj-kondo]
11
+ [tools.build :as build]
12
+ [tools.clj-kondo :as clj-kondo-tools]
13
+ [tools.deploy :as deploy]
14
+ [tools.examples :as examples]
15
+ [tools.npm :as npm]
16
+ [tools.python :as python]
17
+ [tools.release :as release]
18
+ [tools.test :as test]
19
+ [tools.version :as version]]
20
+ :init (do (def config-file "config.edn")
21
+ (def config (edn/read-string (slurp config-file))))
22
+
23
+ ; tools
24
+
25
+ bench {:doc "Run benchmarks"
26
+ :depends [prep]
27
+ :task (clojure "-M:benchmark" "measure")}
28
+
29
+ ffix {:doc "Format source files"
30
+ :depends [prep]
31
+ :task (clojure "-M:ffix")}
32
+
33
+ ; checks
34
+
35
+ format {:doc "Test formatting"
36
+ :depends [prep]
37
+ :task (clojure "-M:format")}
38
+
39
+ lint {:doc "Run clj-kondo linter"
40
+ :require [[pod.borkdude.clj-kondo :as clj-kondo]]
41
+ :task (clj-kondo/print! (clj-kondo/run! {:lint "."}))}
42
+
43
+ test {:doc "Run all tests or restrict to 'native-image', 'back-compat' or a kaocha test id (see tests.edn)"
44
+ :depends [jcompile]
45
+ :task (apply test/-main config *command-line-args*)}
46
+
47
+ kaocha {:doc "Run kaocha with arbitrary arguments"
48
+ :task (apply test/kaocha *command-line-args*)}
49
+
50
+
51
+ outdated {:doc "Find outdated libraries"
52
+ :depends [prep]
53
+ :task (clojure "-M:outdated")}
54
+
55
+ ; build and release
56
+
57
+ inc {:doc "Increment the project version: [major|minor] <version>"
58
+ :task (apply version/inc config-file *command-line-args*)}
59
+
60
+ tag {:doc "Return current version as a tag"
61
+ :task (println (version/as-tag config))}
62
+
63
+ clean {:doc "Remove build files"
64
+ :task (build/clean (-> config :build :clj))}
65
+
66
+ prep {:doc "Prepare git dependencies (compile Java sources)"
67
+ :task (clojure "-X:deps prep")}
68
+
69
+ codegen-java {:doc "Generate Java API bindings from specification"
70
+ :depends [prep]
71
+ :task (let [cp (str/trim (:out (shell {:out :string} "clojure" "-Spath")))]
72
+ ;; First compile Java dependencies (Util, IEntity) so Clojure can load them
73
+ (println "Compiling Java dependencies...")
74
+ (shell "javac" "-cp" cp "-d" "target/classes"
75
+ "java/src/datahike/java/IEntity.java"
76
+ "java/src/datahike/java/Util.java")
77
+ ;; Now generate the Java API
78
+ (println "Generating Java API from specification...")
79
+ (clojure "-M" "-m" "datahike.codegen.java" "java/src-generated"))}
80
+
81
+ codegen-ts {:doc "Generate TypeScript type definitions from specification"
82
+ :task (npm/generate-typescript-definitions! "npm-package/index.d.ts")}
83
+
84
+ codegen-native {:doc "Generate native C entry points from specification"
85
+ :depends [prep]
86
+ :task (clojure "-M" "-m" "datahike.codegen.native" "libdatahike/src")}
87
+
88
+ python-version {:doc "Update Python package version from config.edn"
89
+ :task (python/update-python-version! config "pydatahike")}
90
+
91
+ codegen-python {:doc "Generate Python bindings from specification"
92
+ :depends [prep python-version]
93
+ :task (clojure "-M" "-m" "datahike.codegen.python" "pydatahike/src/datahike")}
94
+
95
+ java-examples-version {:doc "Update Java examples pom.xml version to match current version"
96
+ :task (examples/update-java-examples-version! config)}
97
+
98
+ codegen-clj-kondo {:doc "Generate clj-kondo config from API specification"
99
+ :depends [prep]
100
+ :task (clj-kondo-tools/generate-clj-kondo-config!
101
+ "resources/clj-kondo.exports/io.replikativ/datahike/config.edn"
102
+ ".clj-kondo/datahike/datahike/config.edn"
103
+ ".clj-kondo/config.edn")}
104
+
105
+ codegen-all {:doc "Generate all language bindings (TypeScript, Java, Native, Python)"
106
+ :depends [codegen-ts codegen-java codegen-native codegen-python]}
107
+
108
+ codegen-report {:doc "Show code generation coverage across all bindings"
109
+ :depends [prep]
110
+ :task (clojure "-M" "-m" "datahike.codegen.report")}
111
+
112
+ jcompile {:doc "Compile java classes"
113
+ :depends [clean codegen-java]
114
+ :task (build/compile-java (-> config :build :clj))}
115
+
116
+ javadoc {:doc "Generate Javadoc for Java API (published to javadoc.io)"
117
+ :task (build/javadoc {})}
118
+
119
+ ccompile {:doc "Compile clojure namespaces"
120
+ :task (build/compile-clojure (-> config :build :clj))}
121
+
122
+ version-resource {:doc "Generate version resource file for embedding in builds"
123
+ :task (build/write-version-resource config)}
124
+
125
+ pom {:doc "Create pom file"
126
+ :task (build/pom config (-> config :build :clj))}
127
+
128
+ jar {:doc "Build jar"
129
+ :depends [jcompile pom version-resource]
130
+ :task (build/jar config (-> config :build :clj))}
131
+
132
+ install {:doc "Install jar locally"
133
+ :task (deploy/local config (-> config :build :clj))}
134
+
135
+ clojars {:doc "Install jar to clojars"
136
+ :task (deploy/remote config (-> config :build :clj))}
137
+
138
+ release {:doc "Build and release jar to GitHub"
139
+ :task (release/-main config *command-line-args*)}
140
+
141
+
142
+ ;; http server build and release
143
+
144
+ http-server-clean {:doc "Remove build files"
145
+ :task (build/clean (-> config :build :http-server-clj))}
146
+
147
+ http-server-jcompile {:doc "Compile java classes"
148
+ :depends [http-server-clean]
149
+ :task (build/compile-java (-> config :build :http-server-clj))}
150
+
151
+ http-server-ccompile {:doc "Compile clojure namespaces for http-server"
152
+ :task (build/compile-clojure (-> config :build :http-server-clj))}
153
+
154
+ http-server-pom {:doc "Create pom file"
155
+ :task (build/pom config (-> config :build :http-server-clj))}
156
+
157
+ http-server-uber {:doc "Build jar"
158
+ :depends [http-server-jcompile http-server-pom http-server-ccompile version-resource]
159
+ :task (build/uber config (-> config :build :http-server-clj))}
160
+
161
+ http-server-install {:doc "Install uber jar locally"
162
+ :task (deploy/local config (-> config :build :http-server-clj))}
163
+
164
+ http-server-release {:doc "Build and release jar to GitHub"
165
+ :depends [http-server-uber]
166
+ :task (let [jar (build/jar-path config (-> config :build :http-server-clj))]
167
+ (release/gh-release jar config))}
168
+
169
+ ;; native image
170
+
171
+ ni-check {:doc "Check for 'native-image' program"
172
+ :task (try (shell "which" "native-image")
173
+ (println "Program native-image found!")
174
+ (catch Exception _
175
+ (println "PATH does not contain native-image! Make sure to add your GraalVM to it.")
176
+ (System/exit 1)))}
177
+
178
+ ni-cli {:doc "Build native image cli"
179
+ :depends [jcompile ni-check version-resource]
180
+ :task (clojure "-M:native-cli")}
181
+
182
+ ni-ccompile {:doc "Compile clojure namespaces for native-image"
183
+ :depends [jcompile]
184
+ :task (build/compile-clojure (-> config :build :native))}
185
+
186
+ ni-uber {:doc "Build native image uber jar"
187
+ :depends [jcompile ni-ccompile version-resource]
188
+ :task (build/uber config (-> config :build :native))}
189
+
190
+ ni-compile {:doc "Create native cpp library"
191
+ :depends [codegen-native ni-uber]
192
+ :task (build/native-compile config (-> config :build :native))}
193
+
194
+ ;; npm package
195
+
196
+ npm-version {:doc "Update npm package.json version from config.edn"
197
+ :task (npm/update-package-json-version! config "npm-package")}
198
+
199
+ npm-clean {:doc "Clean compiled files from npm package directory"
200
+ :task (npm/clean-npm-package! "npm-package")}
201
+
202
+ npm-build {:doc "Build npm package (clean, update version, generate types, compile ClojureScript)"
203
+ :depends [prep]
204
+ :task (npm/build-npm-package! config "npm-package")}
205
+
206
+ npm-test {:doc "Run npm package JavaScript tests"
207
+ :task (do
208
+ (println "Running npm package tests...")
209
+ (let [result (shell {:dir "npm-package"
210
+ :out :inherit
211
+ :err :inherit}
212
+ "node test.js")]
213
+ (when-not (zero? (:exit result))
214
+ (System/exit 1))))}
215
+
216
+ node-cljs-test {:doc "Compile and run ClojureScript tests on Node.js"
217
+ :depends [prep]
218
+ :task (do
219
+ (println "Compiling CLJS node tests...")
220
+ (shell "npx shadow-cljs compile node-test")
221
+ (println "Running CLJS node tests...")
222
+ (shell "node target/out/node-test.js"))}
223
+
224
+ browser-test {:doc "Run browser integration tests with Karma (headless Chrome)"
225
+ :depends [prep]
226
+ :task (let [;; Auto-detect Chrome binary
227
+ chrome-bin (or (System/getenv "CHROME_BIN")
228
+ (when (fs/exists? "/usr/bin/chromium-browser") "/usr/bin/chromium-browser")
229
+ (when (fs/exists? "/usr/bin/chromium") "/usr/bin/chromium")
230
+ (when (fs/exists? "/usr/bin/google-chrome") "/usr/bin/google-chrome"))]
231
+ (when-not chrome-bin
232
+ (println "ERROR: Chrome not found. Set CHROME_BIN environment variable.")
233
+ (System/exit 1))
234
+
235
+ ;; Start JVM test server in background
236
+ (println "Starting Kabel test server on ws://localhost:47296...")
237
+ (let [server-proc (process/process
238
+ ["clojure" "-M:test" "-e"
239
+ "(require 'datahike.kabel.browser-test-server) (datahike.kabel.browser-test-server/start-test-server!) (Thread/sleep Long/MAX_VALUE)"]
240
+ {:out :inherit :err :inherit})]
241
+ (try
242
+ ;; Wait for server to start
243
+ (println "Waiting for server startup (10s)...")
244
+ (Thread/sleep 10000)
245
+
246
+ ;; Compile browser tests
247
+ (println "Compiling browser tests...")
248
+ (shell "npx shadow-cljs compile browser-ci")
249
+
250
+ ;; Run Karma
251
+ (println "Running tests with Karma...")
252
+ (shell {:extra-env {"CHROME_BIN" chrome-bin}} "npx karma start --single-run")
253
+
254
+ (finally
255
+ ;; Kill the server process
256
+ (println "Stopping test server...")
257
+ (process/destroy-tree server-proc)))))}
258
+
259
+ browser-watch {:doc "Start browser test dev server (open http://localhost:8022)"
260
+ :depends [prep]
261
+ :task (do
262
+ (println "Starting browser test dev server...")
263
+ (println "Open http://localhost:8022 in your browser")
264
+ (shell "npx shadow-cljs watch browser-integration-test"))}
265
+
266
+ ;; aggregate tasks
267
+
268
+ ci {:doc "Run CI checks (Clojure/ClojureScript + npm tests)"
269
+ :depends [test npm-test format lint]}}}
@@ -0,0 +1,195 @@
1
+ (ns benchmark.cli
2
+ (:require [clojure.tools.cli :as cli]
3
+ [benchmark.measure :refer [get-measurements time-statistics]]
4
+ [benchmark.compare :refer [compare-benchmarks]]
5
+ [benchmark.config :as c]
6
+ [benchmark.store :refer [save]]
7
+ [clojure.string :refer [join]]
8
+ [datahike.store :as ds]
9
+ [datahike.config :as dc]
10
+ [datahike.index :as di]))
11
+
12
+ (def output-formats (set (keys (methods save))))
13
+ (def config-names (set (map :config-name c/named-db-configs)))
14
+ (def implemented-queries #{:simple-query
15
+ :e-join-query :e-join-query-first-fixed :e-join-query-second-fixed
16
+ :a-join-query
17
+ :v-join-query
18
+ :equals-query :equals-query-1-fixed
19
+ :less-than-query :less-than-query-1-fixed
20
+ :scalar-arg-query :scalar-arg-query-with-join
21
+ :vector-arg-query
22
+ :limit-query
23
+ :stddev-query :variance-query :max-query :median-query :avg-query})
24
+ (def implemented-functions #{:connection :transaction :query})
25
+ (def implemented-data-types #{:int :str})
26
+
27
+ (def index-names (-> (methods di/default-index-config) keys set (disj :default)))
28
+ (def backend-names (-> (methods ds/default-config) keys set (disj :default)))
29
+ (def time-stats (-> (time-statistics [0]) keys set))
30
+
31
+ (def cli-options ;; TODO: use default values from datahike.config when available
32
+ [;; CMD run
33
+ ["-u" "--db-server-url URL" "Base URL for datahike server, e.g. http://localhost:3000"
34
+ :default nil]
35
+ ["-n" "--db-name DBNAME" "Database name for datahike server" :default nil]
36
+ ["-g" "--db-token TOKEN" "Token for datahike server" :default nil]
37
+
38
+ ["-t" "--tag TAG" "Add tag to measurements"
39
+ :default #{}
40
+ :assoc-fn (fn [m k v] (assoc m k (conj (get m k) v)))]
41
+ ["-o" "--output-format FORMAT"
42
+ (str "Determines how the results will be processed. "
43
+ "Available are " output-formats " "
44
+ "Currently only edn format is supported for comparisons.")
45
+ :default "edn"
46
+ :validate [output-formats #(str "Format " % " has not been implemented. "
47
+ "Available formats are " output-formats)]]
48
+ ["-e" "--statistics VECTOR"
49
+ (str "Statistic columns shown in the printed comparison summary. "
50
+ "Available are: " time-stats)
51
+ :default [:median :mean :std]
52
+ :parse-fn read-string
53
+ :validate [vector? (str "Must be a vector of cell names. Available are: " time-stats)
54
+ #(every? time-stats %) #(str "Must be a vector of cell names. Available are: " time-stats)]]
55
+
56
+ ["-c" "--config-name CONFIGNAME"
57
+ (str "Name of preset database configuration to use. Available are: " config-names)
58
+ :validate [config-names #(str "A configuration named " % " has not been implemented. "
59
+ "Available configurations are: " config-names)]]
60
+
61
+ ["-a" "--index INDEXNAME"
62
+ (str "Name of index to use. Available are " index-names)
63
+ :default :all
64
+ :parse-fn read-string
65
+ :validate [index-names #(str "An index named " % " has not been implemented. "
66
+ "Available indices are: " index-names)]]
67
+ ["-l" "--history BOOLEAN"
68
+ (str "Boolean indication if measured databases use temporal indices")
69
+ :default false
70
+ :parse-fn read-string
71
+ :validate [#(contains? #{true false :all} %) "Must be a boolean value or keyword :all"]]
72
+ ["-b" "--backend BACKEND"
73
+ (str "Keyword for backend that is going to be used")
74
+ :default :all
75
+ :parse-fn read-string
76
+ :validate [(conj backend-names :all) #(str "A backend named " % " has not been implemented. "
77
+ "Available backends are: " backend-names)]]
78
+ ["-k" "--search-caches SIZES"
79
+ (str "Search cache sizes for which measurements should be done")
80
+ :default [dc/*default-search-cache-size*]
81
+ :parse-fn read-string
82
+ :validate [vector? "Must be a vector of non-negative integers."
83
+ #(every? nat-int? %) "Vector must consist of non-negative integers."]]
84
+ ["-m" "--store-caches SIZES"
85
+ (str "Store cache sizes for which measurements should be done")
86
+ :default [dc/*default-store-cache-size*]
87
+ :parse-fn read-string
88
+ :validate [vector? "Must be a vector of positive integers."
89
+ #(every? pos-int? %) "Vector must consist of non-negative integers."]]
90
+ ["-j" "--schema VALUE"
91
+ (str "Schema flexibility configuration. Available are: " #{:read :write})
92
+ :default :write
93
+ :parse-fn read-string
94
+ :validate [#{:read :write :all} #(str "A schema-flexibility named " % " has not been implemented. "
95
+ "Available values are: " #{:read :write})]]
96
+
97
+ ["-d" "--db-entity-counts VECTOR"
98
+ (str "Numbers of entities in database for which benchmarks should be run. "
99
+ "Must be given as a clojure vector of non-negative integers like '[0 10 100 1000]'.")
100
+ :default [0 1000]
101
+ :parse-fn read-string
102
+ :validate [vector? "Must be a vector of non-negative integers."
103
+ #(every? nat-int? %) "Vector must consist of non-negative integers."]]
104
+ ["-x" "--tx-entity-counts VECTOR"
105
+ (str "Numbers of entities in transaction for which benchmarks should be run. "
106
+ "Must be given as a clojure vector of non-negative integers like '[0 10 100 1000]'.")
107
+ :default [0 1000]
108
+ :parse-fn read-string
109
+ :validate [vector? "Must be a vector of non-negative integers."
110
+ #(every? nat-int? %) "Vector must consist of non-negative integers."]]
111
+ ["-y" "--data-types VECTOR"
112
+ (str "Vector of datatypes to test queries on. Available are: " implemented-data-types ".")
113
+ :default [:int :str]
114
+ :parse-fn read-string
115
+ :validate [vector? (str "Must be a vector of data type keywords. Available are " implemented-data-types)
116
+ #(every? implemented-data-types %) (str "Vector must consist of keywords for datatypes. "
117
+ "Available are: " implemented-data-types)]]
118
+ ["-z" "--data-found-opts BOOLEAN"
119
+ (str "Boolean indicating if query is run for existent or nonexistent values in the database.")
120
+ :default true
121
+ :parse-fn read-string
122
+ :validate [#{true false :all} "Must be a boolean value or keyword :all."]]
123
+ ["-i" "--iterations ITERATIONS"
124
+ (str "Number of measurements for each setting taken on the same database.")
125
+ :default 10
126
+ :parse-fn read-string
127
+ :validate [nat-int? "Must be a non-negative integer."]]
128
+ ["-s" "--db-samples DB-SAMPLES"
129
+ (str "Number of database instances on which the full measurements are run.")
130
+ :default 1
131
+ :parse-fn read-string
132
+ :validate [nat-int? "Must be a non-negative integer."]]
133
+ ["-q" "--query QUERYNAME"
134
+ (str "Name of query to test. Available are " implemented-queries)
135
+ :default :all
136
+ :parse-fn read-string
137
+ :validate [(conj implemented-queries :all) (str "Must be a keyword for a implemented database query "
138
+ "Available are: " implemented-queries)]]
139
+ ["-f" "--function FUNCTIONNAME"
140
+ (str "Name of function to test. Available are " implemented-functions)
141
+ :default :all
142
+ :parse-fn read-string
143
+ :validate [(conj implemented-functions :all) (str "Must be a keyword for implemented database function. "
144
+ "Available are: " implemented-functions)]]
145
+
146
+ ;; CMD compare
147
+
148
+ ["-p" "--[no-]plots" "Output comparison as plots."]
149
+
150
+ ["-h" "--help"]])
151
+
152
+
153
+ (defn print-usage-info [summary]
154
+ (println (str "Usage: clj -M:benchmark CMD [OPTIONS] [FILEPATHS] \n\n Options for command 'run':\n" summary)))
155
+
156
+ (defmulti run-command (fn [cmd _paths _options] cmd))
157
+
158
+ (defmethod run-command :default [cmd _paths _options]
159
+ (throw (Exception. (str "Command '" cmd "' does not exist. Valid commands are 'measure' and 'compare'"))))
160
+
161
+ (defmethod run-command "compare" [_cmd paths {:keys [plots statistics]}]
162
+ (compare-benchmarks paths plots statistics))
163
+
164
+
165
+ (defmethod run-command "measure" [_cmd paths {:keys [tag output-format] :as options}]
166
+ (let [server-description (select-keys options [:db-server-url :db-token :db-name])]
167
+ (if (and (= "remote-db" output-format)
168
+ (some nil? (vals server-description)))
169
+ (do (println (str "Only partial information for remote connection has been given: " server-description))
170
+ (println "Please, define URL, database name, and token to save the data on a remote datahike server."))
171
+ (let [measurements (cond->> (get-measurements options)
172
+ (seq tag) (map (fn [entity] (assoc entity :tag (join " " tag))))
173
+ true vec) ]
174
+ (save options paths measurements)))))
175
+
176
+ (defn -main [& args]
177
+ (let [{:keys [arguments options errors summary]} (cli/parse-opts args cli-options)
178
+ [cmd & paths] arguments]
179
+ (cond
180
+ (some? errors)
181
+ (do (println "Errors:" errors)
182
+ (print-usage-info summary))
183
+
184
+ (:help options)
185
+ (print-usage-info summary)
186
+
187
+ :else (run-command cmd paths options)))
188
+
189
+ (shutdown-agents))
190
+
191
+ (comment
192
+ (-main "measure" "-x" "[0 10000 5000]" "-t" "test-bench" "-o" "edn" "bench.edn")
193
+ )
194
+
195
+ ;TIMBRE_LEVEL=":info" clj -M:benchmark measure --backend :file --index :datahike.index/persistent-set -t pss -o edn pss.edn --schema :write --history false
@@ -0,0 +1,157 @@
1
+ (ns benchmark.compare
2
+ (:require [clojure.edn :as edn]
3
+ [clojure.string :refer [join]]
4
+ [incanter.core :as ic]
5
+ [incanter.charts :as charts]
6
+ [benchmark.config :as c]
7
+ [taoensso.timbre :as log]
8
+ [clojure.java.io :as io])
9
+ (:import [java.awt Color]))
10
+
11
+ (defn comparison-table [group filenames time-stats]
12
+ (let [col-mapping (zipmap (map :name c/csv-cols)
13
+ c/csv-cols)
14
+ grouped (group-by :context group)
15
+ context-sort-fn (fn [context]
16
+ (mapv #(get-in context (vec (rest (:path (% col-mapping))))) ;; rest since already in :context
17
+ c/comparison-context-cell-order))
18
+ sorted-contexts (sort-by context-sort-fn (keys grouped))
19
+ unique-context-key-spaces (map (fn [k]
20
+ (let [{:keys [title path]} (k col-mapping)]
21
+ (->> sorted-contexts
22
+ (map (fn [context]
23
+ (let [x (get-in context (vec (rest path)))]
24
+ (count (str (if (keyword? x)
25
+ (name x)
26
+ x))))))
27
+ (cons (count title))
28
+ (apply max))))
29
+ c/comparison-context-cell-order)
30
+ num-space 8
31
+ col-width (+ (* 3 (- (count time-stats) 1))
32
+ (* (count time-stats) num-space))
33
+ titles (concat (map #(get-in col-mapping [% :title])
34
+ c/comparison-context-cell-order)
35
+ filenames)
36
+ title-spaces (concat unique-context-key-spaces (repeat (count filenames) col-width))
37
+ subtitles (concat (repeat (count c/comparison-context-cell-order) "")
38
+ (apply concat (repeat (count filenames) time-stats)))
39
+ subtitle-spaces (concat unique-context-key-spaces
40
+ (repeat (* (count time-stats) (count filenames))
41
+ num-space))
42
+ dbl-fmt (str "%" num-space ".2f")
43
+ str-fmt (fn [cw] (str "%-" cw "s"))]
44
+ (str " | " (join " | " (map #(format (str-fmt %2) %1) titles title-spaces)) " |\n"
45
+ " |-" (join "-+-" (map (fn [s] (apply str (repeat s "-"))) title-spaces)) "-|\n"
46
+ " | " (join " | " (map #(format (str-fmt %2) %1) subtitles subtitle-spaces)) " |\n"
47
+ " |-" (join "-+-" (map (fn [s] (apply str (repeat s "-"))) subtitle-spaces)) "-|\n"
48
+ (join "\n" (for [[context results] (sort-by #(context-sort-fn (key %)) grouped)]
49
+ (let [times (map (fn [filename] (->> results (filter #(= (:source %) filename)) first :time))
50
+ filenames)
51
+ context-cells (map (fn [context-key col-width]
52
+ (let [context-val (get-in context (vec (rest (:path (context-key col-mapping)))) "")]
53
+ (format (str-fmt col-width)
54
+ (if (keyword? context-val)
55
+ (name context-val)
56
+ context-val))))
57
+ c/comparison-context-cell-order
58
+ unique-context-key-spaces)
59
+ measurement-cells (map (fn [measurements] (join " | " (map (fn [stat] (format dbl-fmt (stat measurements)))
60
+ time-stats)))
61
+ times)]
62
+ (str " | " (join " | " (concat context-cells measurement-cells)) " |"))))
63
+ "\n")))
64
+
65
+
66
+ (defn check-file-format [filename]
67
+ (when-not (.endsWith filename ".edn")
68
+ (throw (Exception. (str "File " filename "has an unsupported file type. Supported are only edn files.")))))
69
+
70
+ (defn report [benchmarks filenames time-stats]
71
+ (let [grouped-benchmarks (group-by #(get-in % [:context :function]) benchmarks)
72
+ output (str (when-let [conn-benchmarks (:connection grouped-benchmarks)]
73
+ (str "Connection Measurements (in s):\n"
74
+ (comparison-table conn-benchmarks filenames time-stats)
75
+ "\n"))
76
+ (when-let [tx-benchmarks (:transaction grouped-benchmarks)]
77
+ (str "Transaction Measurements (in s):\n"
78
+ (comparison-table tx-benchmarks filenames time-stats)
79
+ "\n"))
80
+ (when-let [query-benchmarks (->> (dissoc grouped-benchmarks :connection :transaction)
81
+ vals
82
+ (apply concat))]
83
+ (str "Query Measurements (in s):\n"
84
+ (comparison-table query-benchmarks filenames time-stats))))]
85
+ (println output)))
86
+
87
+ (defn create-plots [data] ;; 1 plot per function and context
88
+ (let [tags (join "," (distinct (map :tag data)))
89
+ colors [Color/red Color/blue Color/green Color/cyan Color/magenta Color/orange Color/yellow]
90
+ directory (str "plots-" tags)]
91
+
92
+ (doall (for [function (distinct (map #(get-in % [:context :function]) data))
93
+ config (distinct (map #(get-in % [:context :dh-config]) data))
94
+ execution-details (distinct (map #(get-in % [:context :execution]) data))]
95
+ (let [_ (log/debug (str "Processing " function " " config " " execution-details))
96
+ {:keys [tx-entities data-type data-in-db?]} execution-details
97
+ filename (str (name function)
98
+ "_config-" config
99
+ (when tx-entities
100
+ (str "_tx-ents-" tx-entities))
101
+ (when data-type
102
+ (str "_type-" (name data-type)))
103
+ (when data-in-db?
104
+ (str "_found-" data-in-db?))
105
+ "_tags-" tags
106
+ ".png")
107
+
108
+ plot-data (->> data
109
+ (filter #(and (= (get-in % [:context :function]) function)
110
+ (= (get-in % [:context :dh-config]) config)
111
+ (= (get-in % [:context :execution]) execution-details)))
112
+ (map #(assoc % :x (get-in % [:context :db-entities]))))]
113
+ (when (seq plot-data)
114
+ (let [filepath (str directory "/" filename)
115
+ all-y (apply concat (map #(get-in % [:time :observations]) plot-data))
116
+ ymin 0
117
+ ymax (apply max all-y)
118
+ ; ymax (quantile all-y :probs 0.9)
119
+ plot (charts/scatter-plot nil nil
120
+ :title (str "Execution time of function " function "\n"
121
+ "for configuration " (name config) " and\n"
122
+ "execution parameters " execution-details)
123
+ :y-label "Time (s)"
124
+ :x-label (str "Entities in database (1 entity = " (count c/schema) " datoms)")
125
+ :legend true
126
+ :series-label "")]
127
+ (charts/set-stroke-color plot (Color. 0 0 0 0) :dataset 0)
128
+ (charts/set-y-range plot ymin ymax)
129
+ (doall (map-indexed (fn [idx [tag group]]
130
+ (let [sorted (sort-by :x group)
131
+ entities (map :x sorted)
132
+ time (map :time sorted)
133
+ time-obs (apply concat (map :observations time))
134
+ entities-rep (apply concat (map #(repeat (count (:observations %2)) %1) entities time))]
135
+
136
+ (charts/add-points plot entities-rep time-obs :series-label tag)
137
+ (charts/set-stroke-color plot (get colors idx) :dataset (+ 1 (* idx 2)))
138
+ (charts/add-lines plot entities (map :median time) :series-label (str tag " median")))
139
+ (charts/set-stroke-color plot (get colors idx) :dataset (+ 2 (* idx 2))))
140
+ (group-by :tag plot-data)))
141
+ (when-not (.exists (io/file directory))
142
+ (.mkdir (io/file directory)))
143
+ (ic/save plot filepath
144
+ :width 800
145
+ :height 600))))))))
146
+
147
+ (defn compare-benchmarks [filenames plots? time-stats]
148
+ (run! check-file-format filenames)
149
+
150
+ (let [benchmarks (->> filenames
151
+ (map (fn [filename]
152
+ (map #(assoc % :source filename)
153
+ (edn/read-string (slurp filename)))))
154
+ (apply concat))]
155
+ (if plots?
156
+ (create-plots benchmarks)
157
+ (report benchmarks filenames time-stats))))