Closed arnaudgeiser closed 2 years ago
Hmm, I'm concerned about breaking things.
enumerating-thread-factory
doesn't promise to be anything more than a ThreadFactory based on its type hint, so I don't think swapping concrete classes will be the issue. The thread names will not be exactly the same (DefaultThreadFactory adds pool IDs), but hopefully nobody's got mission-critical logging regexes on thread names.
No, the only thing I'm actually concerned about is losing the classloader behavior @kachayev added to m.executor/thread-factory
in https://github.com/clj-commons/manifold/commit/26038e03642ff8b0e125a7e35b333153b295c46f. See https://github.com/clj-commons/aleph/pull/425 and https://github.com/clj-commons/manifold/pull/161 for more background, but IIUC, Netty threads won't have the Clojure classloader set, so if a Clojure class has to be loaded for the first time on a Netty thread, it fails.
The fix would then be one of:
m.executor/thread-factory
to Aleph and replace Thread.
with FastThreadLocalThread.
thread-class
param to m.executor/thread-factory
that allows us to override Thread with FastThreadLocalThreadI like option 2 the most. I hoped there might be a way to globally tell Netty to use the Clojure classloader for its threads, but given how much it messes with classloaders itself, I think that's risky.
Thoughts?
The thread names will not be exactly the same (DefaultThreadFactory adds pool IDs), but hopefully nobody's got mission-critical logging regexes on thread names.
Good catch, I didn't notice the pool-id on the name
No, the only thing I'm actually concerned about is losing the classloader behavior @kachayev added to m.executor/thread-factory in https://github.com/clj-commons/manifold/commit/26038e03642ff8b0e125a7e35b333153b295c46f. See https://github.com/clj-commons/aleph/pull/425 and https://github.com/clj-commons/manifold/pull/161 for more background, but IIUC, Netty threads won't have the Clojure classloader set, so if a Clojure class has to be loaded for the first time on a Netty thread, it fails.
I was not able to reproduce the issue with my changes while it's reproducible with Aleph 0.4.6.
(defn handler [req]
{:status 200
:headers {"content-type" "text/plain"}
:body "hello!"})
(def foo (http/start-server handler {:port 8080}))
;; after a sec
(.close foo)
Anyway, you are right, I think @kachayev poured a lot of thought on this change.
I like option 2 the most. I hoped there might be a way to globally tell Netty to use the Clojure classloader for its threads, but given how much it messes with classloaders itself, I think that's risky.
All for it. I will work on a PR on manifold
to be able to pass a classname
as the last argument of manifold.executor/thread-factory
.
At some point, we should consider destructuring maps, possibly with some fast destructuring lib. A lot of Aleph/Manifold fns have way too many params already.
Description
~This PR makes use of the
io.netty.util.concurrent.DefaultThreadFactory
from Netty instead of using the implementation ofmanifold.executor
. The reason for this is thatDefaultThreadFactory
is creatingFastThreadLocalThread
instead of JDKThread
[1]. As demonstrated on the following code, it's supposed to be faster (fastGet
) [2].~This PR ensures we are using
io.netty.util.concurrent.FastThreadLocalThread
when creating the Aleph executor.Here are some (interesting?) links on Netty:
[1] : https://github.com/netty/netty/blob/f17b5fe3cd7155a0281d081edabe223e131ba332/common/src/main/java/io/netty/util/concurrent/DefaultThreadFactory.java#L121 [2] : https://github.com/netty/netty/blob/69e1d36cb19c034dcdcaaa1085c0387435c06975/common/src/main/java/io/netty/util/internal/InternalThreadLocalMap.java#L100-L124
Testing done
Exercised code
Before
After