Fork me on GitHub
#clojure
<
2020-05-20
>
kenny00:05:32

Is the thread group created by agents called "pool-1"?

dpsutton00:05:41

Not at a computer but you can look for the thread factory in agents.java I believe

kenny00:05:35

I see these: clojure-agent-send-pool-%d and clojure-agent-send-off-pool-%d. Something is creating a group of 50 threads in the group "pool-1" following the name "pool-1-thread-N".

potetm00:05:52

depends on how you send, I think

kenny01:05:30

That code implies it's not agents, right?

potetm01:05:40

I would agree

kenny01:05:28

I can find references to this naming scheme via google. Not sure where it's coming from though. e.g., https://groups.google.com/d/msg/clojure/2YGRfnZ9hvU/doYP6mjPUKgJ

potetm01:05:52

If you like, you can pull the classpath together and grep the jars

hiredman01:05:09

That is the default name used for threadpool threads

4
potetm01:05:40

static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

4
potetm01:05:06

(from Executors.java)

potetm01:05:46

(java 1.8)

potetm01:05:21

jar -tvf "$file" | egrep -i -- pool-

hiredman01:05:24

Which is why that old mailing list post shows those names, clojure uses to not set custom names

hiredman01:05:14

So you'll need to look at the stack traces of the threads in that pool to determine what is running there (the names won't help)

kenny01:05:01

Ah, got it. Yeah, the threaddump isn't very helpful. All the threads are WAITING.

hiredman01:05:48

The stacktraces will show you what they are waiting on

kenny01:05:51

priority:5 - threadId:pool-1-thread-1 - state:WAITING
stackTrace:
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
- parking to wait for <0x000000076bcffe48> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park([email protected]/LockSupport.java:194)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await([email protected]/AbstractQueuedSynchronizer.java:2081)
at java.util.concurrent.LinkedBlockingQueue.take([email protected]/LinkedBlockingQueue.java:433)
at java.util.concurrent.ThreadPoolExecutor.getTask([email protected]/ThreadPoolExecutor.java:1054)
at java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/ThreadPoolExecutor.java:1114)
at java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/ThreadPoolExecutor.java:628)
at java.lang.Thread.run([email protected]/Thread.java:834)
Locked ownable synchronizers:
- None
This is what you mean, right? It's not obvious who owns that lock from that info.

kenny01:05:08

There's another 49 of those identical messages haha.

hiredman01:05:44

I believe that is an idle threadpool thread, doing nothing waiting to pull work from a queue

kenny01:05:05

So the jvm just creates that pool by default?

hiredman01:05:29

Some library you are using is creating it

hiredman01:05:08

You may just need to search for 50 to look for someone creating a fixed threadpool of 50 threads

kenny01:05:05

Seems tough haha. Just search for "50"

potetm01:05:14

#!/usr/bin/env bash

while read f; do
  if [[ $f =~ *.jar ]]; then
    zipgrep '\bpool-' "$f"
  else
    egrep -Ir '\bpool-' "$f"
  fi
done < <(clj -Spath | tr ':' '\n')

potetm01:05:37

❤️ bash

kenny01:05:47

Won't that look for pool- though? This lib is using the default.

kenny01:05:58

Presumably there won't be a "pool-".

potetm01:05:59

it’s not quite the default, it would appear

potetm01:05:03

looks like the default for me is pool-$POOL_N-thread-$THREAD_N

kenny01:05:11

That's what I'm seeing.

hiredman01:05:20

Kenny just left out part if the name in the initial ask

✔️ 8
potetm01:05:07

welp, look for usages of Executors constructors?

potetm01:05:22

e.g. Executors/newFixedThreadPool

kenny01:05:44

Seems like a safe bet. Could also be in a Java lib. For some reason I'm thinking apache something.

potetm01:05:56

cursive will pick that up, I think

kenny01:05:13

Lots of places do something like Executors.newFixedThreadPool(poolsize) 😅

potetm01:05:55

grab a drink?

✔️ 4
potetm01:05:01

and a checklist?

kenny01:05:58

I mean, there's not that many places. I'm not totally sure how extensive Cursive's search is. Some statically declare the threadpool size and others pass it in as var. It may not have been constructed with this method.

cfleming02:05:00

I bet you find a bunch of the Executors constructors delegate to one main one. Put a breakpoint in there and see what hits it.

Alex Miller (Clojure team)02:05:47

just fyi, there is actually a default worker pool built into forkjoin these days. I don't think this is it, but in case that's useful knowledge to anyone in the future

tio08:05:29

if i pass in a list into this function, 1 is being added to the accumulator on every pass. what is happening to this list on every pass? where do those elements go that get reduced down?

(fn [seq]
  ;; passes seq into reduce func where accum starts at 0
  ;; each pass adds 1 to accum
  (reduce (fn [x y] (+ x 1)) 0 seq))

andy.fingerhut09:05:18

The elements of the sequence/list get passed as the values of the parameter y of the function, and the way that function is defined, it ignores the value of y.

andy.fingerhut09:05:02

That is, it gets the value of the elements, but does not do anything with them.

tio10:05:56

Ah, thank you!

Adianto Wibisono12:05:54

Seems to me elements is ignored and you ended up counting length of list.

jsyrjala13:05:22

What is the easiest way to read EDN data with reader literals, if you dont care about the reader literals. E.g reading a string`"{:foo {:store #cookie-store {:key \"123\"}}"` to clojure value {:foo {:store {:key "123"}

delaguardo13:05:22

(require '[clojure.edn :as edn])

  (edn/read-string
   {:default (fn [_ data] data)}
   "{:foo {:store #cookie-store {:key \"123\"}}}")

Alex Miller (Clojure team)14:05:30

or use the tagged-literal function in core

Alex Miller (Clojure team)14:05:56

that retains the tagged literal if you print it back out

Andreas Edvardsson14:05:42

How do I go about to call the java-provided mod operator % from within clojure? I know standard java interop but haven't figured out how to call the "core" java built-ins. Clojure's mod is not good enough since I need the exact behaviour of the java one for compatibility.

Andreas Edvardsson14:05:30

Maybe the easiest is to create a java class and just expose a wrapper method? I'll go with that for now but is curious for alternatives. Thanks!

ghadi14:05:41

rem is what you're looking for

🎉 4
Andreas Edvardsson14:05:13

Oh, that does indeed make the tests happy 🙂 Sometimes you just don't know what you are trying to accomplish, it seems. Thanks!

wombawomba14:05:02

So I want to release a library for use for both clj and cljs. The library has slightly different dependencies for running in cljs than in clj. What’s the correct way to handle this? Should I just include both the clj and cljs dependencies in my pom.xml?

wombawomba14:05:51

…and on a related note, should I be including Clojure/ClojureScript as dependencies in the released jar?

Ramon Rios14:05:01

Have you tried before to pass a thread-first as a argument for a function?

(defn- wrap-exception 
  [f info]
  (try
    f
    (catch Exception e
      (log/error "Exception was handled: " (.getClass e) ": " (.getMessage e))
      (throw (ex-info info {:status 500
                            :message (.getMessage e)})))))
I want to pass a thread-first function on it for avoid using try catch all the time

noisesmith15:05:41

surely that should be (try (f) ...)

noisesmith15:05:59

how would thread-first help here? how would you pass the macro as an argument?

Ramon Rios15:05:32

On the example, i update something in database and then handle the result. i use it for make it more readable.

(-> (persist/update-subcategory datasource body id)
        (handle-result id :update))

Ramon Rios15:05:00

(wrap-exception
    (-> (persist/update-subcategory datasource body id)
        (handle-result id :update))
    "Subcategory was not updated.")
The big picture of it

noisesmith15:05:18

that's a reasonable way to use try/catch but it doesn't really matter if what is inside is ->, or just a nested form, or a let block

noisesmith15:05:34

I asked because I didn't see the connection