Fork me on GitHub

I have this overly complex method in a project for finding the next time it's 8:15 am. (the result is applied to a timezone later)

(defn the-next-8-15-am-localtime []
  (let [now (t/now)
        this-morning (t/date-time (t/year now) (t/month now) (t/day now) 8 15)
        tomorrow-morning (t/plus
                          (t/days 1))]
    (if (t/before? now this-morning)
using clj-time (java-time is not available in this project) I strongly suspect there is a more proper way to do this


i wouldnt say that it is too complex. im also curious about different ways to do it


perhaps i make both dates and filter by the ones in the past


I'm also curious if the new fancy java-time has an easier time of this


(let [this-morning (t/today-at 8 15)]
  (if (t/before? (t/now) this-morning)
    (t/plus this-morning (t/days 1))))


bit shorter 🙂


I have an idea - one moment


(defn the-next-8-15-am-localtime []
  (loop [now (t/now)]
    (if (and (= 8 (hour now))
             (= 15 (minute now)))
      (t/date-time now)
      (recur (t/plus now (t/seconds 1))))))

🙂 3

@arthur how does that look?


i haven't run it and might have fudged the types, but that i used loop recur so




@U11EL3P9U You laugh, but its runtime is O(172800)


technically still constant time


I could spell out the math as well in the initial date creation time. which feels like reinventing the library


and likely to mess up leap seconds


is there a conventient thing to ingest a deps.edn into a running repl and use pomegranate to add all the dependencies ?


@arthur You can use the add-lib3 branch of t.d.a for that -- see my dot-clojure file:


(I use this all the time to add new libs into my REPL started with clj)


ahh neet, i appreciate the name as well !

Ben Sless21:11:15

What are the effects of binding expressions in let on the JVM in terms of performance? I see they decompile to store and load instructions, but how significant are they? I'm guessing there are also differences between loading primitives and references, and how much throughput is going through the CPU's caches

Alex Miller (Clojure team)22:11:57

Effects as opposed to what?

Ben Sless22:11:36

let's take this contrived example:

(defn foo [^long a]
  (let [a (inc a)
        a (inc a)
        a (inc a)
        a (inc a)
        a (inc a)
        a (inc a)
        a (inc a)
        a (inc a)]

(defn bar [^long a]
  (-> a
      inc inc inc inc
      inc inc inc inc))
One stores and loads a long constantly, while the other only calls invokestatic

Ben Sless22:11:49

Just a snippet of the bytecode:

27: invokestatic    clojure/lang/
              30: lstore          a
              32: lload           a
                  linenumber      7
              34: invokestatic    clojure/lang/
16: invokestatic    clojure/lang/
                  linenumber      2
              19: invokestatic    clojure/lang/

Alex Miller (Clojure team)22:11:02

the important question for performance is what the bytecode compiles to


maybe the JVM could also optimize that bytecode internally?

Ben Sless22:11:06

I guess the JIT does that, but examining it is not trivial

Alex Miller (Clojure team)22:11:31

there are jvm options to dump the compiled (and recompiled) assembly as it works

Alex Miller (Clojure team)22:11:24

so examining it is actually not that hard (although I don't have that set of options at hand)

Ben Sless22:11:55

I'd have to examine assembly at that point?

Alex Miller (Clojure team)22:11:24

I mean, if you care about this level of performance, that's the part that matters

👍 3
Alex Miller (Clojure team)22:11:16

I've done this in the past for very specific questions and found it tractable to understand

Ben Sless22:11:27

There's also the question of how well that mixes with the JVM when it's under pressure

Ben Sless22:11:31

Thanks for the directions

Alex Miller (Clojure team)22:11:00

if you mean how well the printing works, you can filter to just what you care about

Ben Sless22:11:24

No, I meant load/store instructions when the caches are busy

Alex Miller (Clojure team)22:11:30

for example above that's all local so I'm not sure how much the cache would even be be involved?

Ben Sless22:11:05

That's the problem with a contrived example. But thinking of a more real-world example with references, I assume they would be

Ben Sless22:11:37

I won't waste more of your time with it, these are mostly idle thoughts for now

Alex Miller (Clojure team)22:11:00

generally, there are probably a lot more important things to care about wrt perf than this

Ben Sless22:11:25

But sometimes you find yourself decompiling functions at midnight out of curiosity


I'm trying to get assembly output for this simple example:

borkdude@MBA2015 /tmp $ cat
public class Foo {

    public static int foo(int i) {
        i = i + 1;
        i = i + 1;
        return i;

    public static void main(String [] args) {
borkdude@MBA2015 /tmp $ javac
borkdude@MBA2015 /tmp $ java  -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:CompileCommand="print"  Foo
CompileCommand: print
but somehow it doesn't work


The Midnight Train To De-Compliation City?


if the code doesn't run enough it never gets compiled


good point. if I make a loop around it, I get: Could not load hsdis-amd64.dylib; library not loadable; PrintAssembly is disabled


you may want -XX:+PrintCompilation


that is because -XX:CompileCommand depends on a java agent or something


(the missing dylib thing)


oh, hah, already been linked


I'm using the other option to restrict the output to one method. it works now


0x0000000119326418: je     0x0000000119326431  ;*iload_0
                                                ; - Example::foo@0 (line 4)

  0x000000011932641e: inc    %esi
  0x0000000119326420: inc    %esi
  0x0000000119326422: mov    %rsi,%rax


Speaking of, has anyone done any comparitive measurements of Clojure programs on arm64 vs x86-64? interested in workloads on Amazon Graviton2