Fork me on GitHub
#clojure
<
2020-11-05
>
arthur16:11:22

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
                          this-morning
                          (t/days 1))]
    (if (t/before? now this-morning)
      this-morning
      tomorrow-morning)))
using clj-time (java-time is not available in this project) I strongly suspect there is a more proper way to do this

tugh16:11:52

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

arthur16:11:01

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

arthur16:11:23

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

dharrigan18:11:08

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

dharrigan18:11:11

bit shorter 🙂

emccue21:11:53

I have an idea - one moment

emccue21:11:35

(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
emccue21:11:49

@arthur how does that look?

emccue21:11:26

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

dharrigan22:11:50

:shocked_face_with_exploding_head:

emccue23:11:05

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

emccue23:11:17

technically still constant time

arthur00:11:07

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

arthur00:11:17

and likely to mess up leap seconds

arthur16:11:49

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

seancorfield17:11:33

@arthur You can use the add-lib3 branch of t.d.a for that -- see my dot-clojure file: https://github.com/seancorfield/dot-clojure/blob/develop/deps.edn#L167-L190

seancorfield17:11:02

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

arthur18:11:52

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)]
    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/Numbers.inc:(J)J
              30: lstore          a
              32: lload           a
                  linenumber      7
              34: invokestatic    clojure/lang/Numbers.inc:(J)J
vs
16: invokestatic    clojure/lang/Numbers.inc:(J)J
                  linenumber      2
              19: invokestatic    clojure/lang/Numbers.inc:(J)J

Alex Miller (Clojure team)22:11:02

the important question for performance is what the bytecode compiles to

borkdude22:11:44

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

borkdude22:11:53

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

[email protected] /tmp $ cat Foo.java
public class Foo {

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

    public static void main(String [] args) {
        System.out.println(foo(1));
    }
}
[email protected] /tmp $ javac Foo.java
[email protected] /tmp $ java  -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:CompileCommand="print Foo.foo"  Foo
CompileCommand: print Foo.foo
3
but somehow it doesn't work

dharrigan22:11:54

The Midnight Train To De-Compliation City?

hiredman22:11:18

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

borkdude22:11:09

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

hiredman22:11:10

you may want -XX:+PrintCompilation

hiredman22:11:32

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

hiredman22:11:54

(the missing dylib thing)

hiredman22:11:12

oh, hah, already been linked

borkdude22:11:03

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

borkdude22:11:16

0x0000000119326418: je     0x0000000119326431  ;*iload_0
                                                ; - Example::[email protected] (line 4)

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

ghadi23:11:44

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