announcements

Niki 2026-02-05T17:17:19.048559Z

https://github.com/tonsky/clj-simple-stats, simple statistics for Clojure+Ring webapps, has reached v1.2.0 This update removes all the potential issues with GDPR related to cookies and IP addresses

👍 6
💯 4
❤️ 9
🙏 4
🎉 6
igrishaev 2026-02-06T16:43:09.683609Z

We use duckdb at work, the same issue: the jar holds binaries for all architectures. We made our own internal package which keeps only linux/arch64

igrishaev 2026-02-06T16:44:15.505519Z

btw: sqilte-jdbc is only 13 megs or something

Niki 2026-02-06T20:53:28.677959Z

DuckDB does compression on DB file though. For example, stats for grumpy.websites weight 600 MB in DuckDB and 3 GB in SQLite. By paying more upfront, you are actually saving in the long run! Also queries are way more efficient in DuckDB. Didn’t really had a choice.

🔥 1
mike_ananev 2026-02-05T18:21:03.783119Z

Hi, Niki! Thanks for sharing this. My jar is increased from 31M up to 108M. Statistics is a heavy thing! 🤣

Niki 2026-02-05T18:26:02.090719Z

that's duckdb

mike_ananev 2026-02-05T18:50:38.806599Z

I manually removed binaries for windows and macosx from ubejar and now it is 49M.

Niki 2026-02-05T19:47:34.713939Z

Now that I think about it I don't like it too but… duckdb is really good at what it does

Niki 2026-02-05T19:48:14.895049Z

pretend it's a very compact electron app :)

👍 1
2026-02-05T20:33:45.033329Z

--- clj-uuid 0.2.5 released https://github.com/danlentz/clj-uuid Just announcing a new release of clj-uuid -- Thanks for 3,000,000 downloads! What’s new:New UUID versions — v6 (reordered time-based, sortable), v7 (unix time + crypto random, sortable), and v8 (custom/user-defined). And, introducing v7nc for when you need v7's structure, you need it fast, and don’t need cryptographic randomness. • Performance work — Rewrote the internals around ByteBuffer primitives and JVM intrinsics. Serialization-heavy workloads see 3-19x improvement. Generation is now competitive with JUG and uuid-creator across the board, with faster v7nc, and v5 (SHA1) at parity with JUG. • v7nc — At ~39ns, this may be the fastest UUID generator on the JVM — 1.26x faster than JUG’s TimeBasedEpochGenerator. Useful when you want sortable time-based UUIDs without the overhead of SecureRandom. [danlentz/clj-uuid “0.2.5”] If you’re curious about the optimization approach, I wrote up some notes: - https://github.com/danlentz/clj-uuid/blob/master/doc/perf-analysis.md — ByteBuffer vs shift/mask loops, JVM intrinsics - https://github.com/danlentz/clj-uuid/blob/master/doc/uuid-generation-benchmarks.md — per-version timings - https://github.com/danlentz/clj-uuid/blob/master/doc/apples.md — Comparisons with other libraries Feedback welcome! ---

13
🚀 2
🎉 24
2026-02-06T23:56:07.699929Z

i have a new “ordered collections” library i hope you’ll also look at. just waiting on approval from mgmt to release its glacial

😜 1
2026-02-05T20:38:22.899779Z

that performance increase is incredible

Joe Lane 2026-02-05T20:38:24.579669Z

39ns is no joke. Great work

2026-02-05T20:43:56.327779Z

🎉

oyakushev 2026-02-05T21:40:35.037079Z

Uh oh. Your optimization work is stellar, but your benchmarking approach is unfortunately invalid. You MUST use a proper benchmarking framework like JMH for microoptimizations like this one. You MUST consume computation results, otherwise you may just be reading DCE noise. I'm pretty sure you will still come up ahead when you redo the benchmarks, but it's still important to do. You can start with Criterium, at least.

2026-02-05T21:45:07.454709Z

i like criterium and use it a lot. i am not sure how to publish benchmarks correctly (its all bs at some level) my goal was to just give a sense of the improvements. but i’m definitely open to increasing the rigor of the benchmarks if you want to open a new PR?

oyakushev 2026-02-05T21:47:25.968969Z

I don't mean that you have to include all the quartiles and stdevs from Criterium/JMH, it's fluff, average is fine. I mean that you can't dotimes an operation that takes 40ns to run without somehow consuming the output and trust the resulting number. Both Criterium and JMH do that (consume the output and thus prevent dead code elimination). 40ns may become 100ns when measured properly, so you can't get the sense of improvement in this way.

2026-02-05T21:49:03.647679Z

thats a reasonable objection

2026-02-05T21:53:54.111819Z

im not sure i can address it immediately. but my feeling is that we’re in the ballpark. i’m very happy to work with you on improving the benchmark (and who knows, maybe overall performance)

oyakushev 2026-02-05T21:55:06.703329Z

Again, I'm sure that re-benchmarking will demonstrate that you still achieved significant improvement, but given how much effort you already put into this, and that you have a dedicated benchmarking scripts/docs, it is a waste to have the "wrong" methodology there.

oyakushev 2026-02-05T21:56:52.554719Z

You could at least double-check with Criterium that it gives you the same ballpark timings as your dotimes scripts. If it does, then at least the results are correct, even if the measuring approach isn't.

2026-02-05T21:56:53.024199Z

make a PR?

2026-02-05T21:57:07.905509Z

y thats fair

oyakushev 2026-02-05T21:57:17.924149Z

Sometime in next life, maybe, sorry 😅 Swamped

2026-02-05T21:57:54.249279Z

lol i get it. but i appreciatye this feedback

❤️ 1
2026-02-05T22:06:43.094809Z

i will address this. you’re right. gah. but it will have to wait until the next release / my next vacation lol 🫤

👍 1
oyakushev 2026-02-05T22:09:23.769309Z

That's why I never get invited to parties

😂 3
2026-02-05T22:09:34.053059Z

that said. my measuring approach was consistent across all libraries

Joe Lane 2026-02-05T22:10:04.098179Z

@alexyakushev If you host a party, I'll definitely come 🥳

🫂 2
2026-02-05T22:10:21.535659Z

so, in relative terms, might be reasonable

2026-02-05T22:10:56.821389Z

lol youre invited my friend you just need to talk me into hosting one

oyakushev 2026-02-05T22:13:11.635139Z

I have some examples of what can go wrong here: https://clojure-goes-fast.com/blog/using-jmh-with-clojure-part1/

2026-02-05T22:15:56.660269Z

oh wow thanks for this link

2026-02-05T22:27:07.469629Z

gold

🙏 1
2026-02-05T22:59:53.124629Z

off topic, but dunno where to go with it: @alexyakushev awesome writeup. I'm curious if you found any problems with jmh-clojure, or if you just found it unintuitive/unwieldy?

❤️ 1
oyakushev 2026-02-05T23:05:19.829529Z

Excellent question. I've encountered jmh-clojure back in those days and experimented with it for a little bit. While it indeed seems like a thought-out project with very solid engineering behind it (its author also developed https://github.com/jgpc42/insn), I couldn't immediately build a mental picture of what's going on there, and thus I didn't trust my results I obtained with it. Micro/nano-benchmarking is such a sensitive act that you'd want to understand what you are doing because it is so easy to get wrong results. I keep jmh-clojure in the back of my mind to return to it someday and properly figure it out and add to my toolset, but I haven't yet in these 7 years I've known about it 😅.

Joe Lane 2026-02-05T23:07:48.871939Z

Welp, there goes my weekend 🤷

2026-02-05T23:08:51.978629Z

yeah my hand-wavy assumption is that it gens classes with the proper annotations and runs JMH, but, yeah, if I were staking my career on it, I would need more info 😄

2026-02-05T23:09:01.358999Z

@joe.lane let me know what you find.

oyakushev 2026-02-05T23:09:46.506469Z

This is the same reason why I gave up on home-grown attempts to drive JMH from the REPL. I just feel better knowing that I'm launching JMH as a standalone process, like as Shipilev intended, and not injecting entropy into measurements.

2026-02-05T23:10:22.552899Z

As Shipilev Intended™

🙏 1
2026-02-05T23:12:04.688769Z

oh god now i need to google shipilev i felt so good about this release earlier

😂 1
oyakushev 2026-02-05T23:13:34.006989Z

This topic is a certified org.openjdk.jmh.infra.Blackhole, enjoy your trip!

oyakushev 2026-02-05T23:14:43.527579Z

@danlentz I pray you actually don't, in your case I'm 99.9% sure Criterium will be enough to verify that your dotimes measurements are in fact fine.

🤣 1
2026-02-05T23:15:42.397919Z

I honestly cannot claim that I enjoyed my dive into jmh either. But what's done is done.

2026-02-05T23:16:14.688389Z

yeah criterium is almost certainly enough for a single fn call

oyakushev 2026-02-05T23:16:42.453559Z

But JMH is a must when you do disassembly diving, case in point: https://clojure-goes-fast.com/blog/performance-tidbit-instanceof/

2026-02-05T23:19:54.114129Z

yeah I'm not actually sure it was necessary in my case, but I wanted to see the impact of threading contention on certain operations. not sure whether that's in criterium's wheelhouse, but I saw other resilience libs setting up jmh harnesses, so that's what I went with.

👍 1
oyakushev 2026-02-05T23:23:53.859249Z

Data-driven configuration that jmh-clojure offers is heaps more pleasant than JMH's annotation vomit, for sure.

2026-02-05T23:26:16.110769Z

yeah I'ma just cross my fingers that Joe comes back with the all clear on Monday

2026-02-05T23:44:17.189639Z

I started this in 2013 as an exercise to learn Clojure … and it continues to be.

Joe Lane 2026-02-06T00:14:47.224299Z

I've always had a project on my personal backlog to store jmh-clojure's datastructures in Datomic to create a performance testing and regression prevention tool. Always just out of reach...