clj-commons / manifold

A compatibility layer for event-driven abstractions
1.02k stars 106 forks source link

Fixed-thread-executor always starts with one thread #152

Closed mishadoff closed 2 years ago

mishadoff commented 6 years ago

Hi, I'm not sure if it's actually a bug/inconsistency or I'm doing something wrong

Consider this snippet

(defn run-future-on-executor []
  (let [exec (me/fixed-thread-executor 2)]
    (md/future-with exec (Thread/sleep 2000) (println "1"))
    (md/future-with exec (Thread/sleep 1000) (println "2"))
    :ok))

I was expecting total run time for 2 seconds (first print 2, then 1) but in fact I got 1 first, and then 2, with a total run time of 3 seconds, so looks like it runs sequentially. Looks like it's not important how many threads you start with it will be always with initial-count 1. So if I change the snippets it runs as expected.

(defn run-future-on-executor []
  (let [exec (me/fixed-thread-executor 2 {:initial-thread-count 2})]
    (md/future-with exec (Thread/sleep 2000) (println "1"))
    (md/future-with exec (Thread/sleep 1000) (println "2"))
    :ok))

Is it bug or I missed something?

tanzoniteblack commented 5 years ago

@mishadoff Refer to the docs about instrumented executors for this. By default the fixed thread executor only updates the running thread count every 10 seconds, so if you run your example for a longer period of time you'll see it start to do more work in parallel. https://github.com/ztellman/manifold/blob/449d1c63e13d5735e704eba02ed949f862d02596/src/manifold/executor.clj#L91

In the following example, the first several iterations are printing Workers: 1, but after about 10 seconds it switches to Workers: 2

(let [exec (manifold.executor/fixed-thread-executor 2)
      simultaneous-action (atom 0)
      exec-function (fn [sleep]
                      (println "Workers: " (swap! simultaneous-action inc))
                      (Thread/sleep sleep)
                      (swap! simultaneous-action dec))]
  (dotimes [i 20]
    (manifold.deferred/future-with exec (exec-function (* 1000 i))))
  :ok)