datalevin

Bastian 2026-03-10T12:32:54.464659Z

Hi, I'm running into what appears to be a native memory leak when repeatedly creating and closing databases in a loop. I'm using Datalevin in a test.check generative test that creates thousands of short-lived DBs during shrinking. more in thread

Bastian 2026-03-10T12:36:37.163489Z

i then tried to imitate how datalevin does the tests internally but just executing the following loop lets memory grow linearly (not the heap):

(future
 (binding [datalevin.constants/*db-background-sampling?* false]
 (loop []
  (let [db-file (str "test-dbs/datalevin-leak-test/" (java.util.UUID/randomUUID))
        db (d/empty-db db-file db/schema {:wal? false})]
                         (d/close-db db)
                         (delete-files db-file)
                         (System/gc))
                       (recur)))))

Bastian 2026-03-10T12:38:48.924049Z

also: in the tests, i would need to use the connections-api to be able to do transactions, however, i observed that the connection cache conn/connections is never cleared. what would be the best approach - reusing connections?, clearing the atom manually or working with a single db/connection and clearing all entities each time?

Bastian 2026-03-10T13:04:51.623299Z

I also noticed sporadic SIGSEGVs in mdb_env_reader_dest though setting datalevin.constants/*db-background-sampling?* to false seems to prevent them

# JRE version: OpenJDK Runtime Environment (21.0.10+7) (build 21.0.10+7-Ubuntu-124.04)
# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-Ubuntu-124.04, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C  [libdtlv.so+0x2b399]  mdb_env_reader_dest+0x19
#
---------------  S U M M A R Y ------------

Command Line: -XX:-OmitStackTraceInFastThrow --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED -Djdk.attach.allowAttachSelf -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:+HeapDumpOnOutOfMemoryError -Djdk.attach.allowAttachSelf -Dclojure.basis=.cpcache/1361635699.basis clojure.main -m nrepl.cmdline --middleware [cider.nrepl/cider-middleware] -p 12345

Host: Intel Xeon Processor (Skylake, IBRS, no TSX), 2 cores, 3G, Ubuntu 24.04.4 LTS
Time: Tue Mar 10 13:58:11 2026 CET elapsed time: 640.021945 seconds (0d 0h 10m 40s)

Huahai 2026-03-11T07:43:50.461539Z

The fix will be in the next release.

🙏 3
phronmophobic 2026-03-10T23:46:07.313029Z

I couldn't find any specific documentation around the specific behavior for :db/id. Per the datalevin docs, I was trying an example based on the datomic docs, https://docs.datomic.com/schema/schema-reference.html#db-id > :db/id is not an attribute; rather, it is syntactic sugar for specifying the https://docs.datomic.com/transactions/transaction-data-reference.html#entity-identifiers in a map form. For example, the following two forms are equivalent: However, datalevin seems to treat string :db/id values as temp ids which is surprising. I also could not find any documentation that explained this behavior:

> (-> (db/transact! @db-conn
                  [[:db/add "s1" :name "s1"]])
    (select-keys [:tempids :tx-data]))
;; {:tempids {"s1" 105, :db/current-tx 39},
;;  :tx-data [#datalevin/Datom [105 :name "s1"]]}
> (-> (db/transact! @db-conn
                  [{:db/id "s1"
                    :name "s1"}])
    (select-keys [:tempids :tx-data]))
;; {:tempids {"s1" 107, :db/current-tx 41},
;;  :tx-data [#datalevin/Datom [107 :name "s1"]]}

phronmophobic 2026-03-10T23:50:20.590909Z

ah ok. It seems like this can inferred from the datomic Entity Identifier docs, https://docs.datomic.com/transactions/transaction-data-reference.html#entity-identifiers.