Reading Hoare's paper, I notice core.async doesn't provide exactly the same semantics as the alternative command. What are your thoughts on this implementation as a general idea? I'm focusing here on emulating the semantics, not performance
Hello, i came across a bug recently with core.async's timeout channel
, In my web-server i create a timeout channel for each request and close it at the end of the request.. the problem is the timeout channel sometimes are created with the time-period already expired during high load... I know this has been reported before in the past (https://clojure.atlassian.net/browse/ASYNC-225) and the obvious explanation i saw was to not close the timeout channel and let the Garbage collection handle it for you. But that causes a LOT of memory usage.. so i'm not sure what is the best way ahead. Ideas will be much appreciated. Thanks guys in advance
You must not close timeout channels
It is best to consider timeout channels as a global resource. Your memory usage issues are likely because mutiple requests are getting the same timeout channel, and when you close a timeout channel for 1 request you are incorrectly also closing the timeout for other requests
So those other requests are prematurely cleaning up
Thank you for replying, Yes i agree 100% that is what is happening, but as i mentioned i create a new timeout channel each time a http request is made AND on the server runs where i don't close channels explicitly, i just end up with a lot of CPU/ram usage(which is probably because i create many channels and the GC is slow to collect the ones that are obsolete, leaving behind a lot of stuff in memory), which goes away with closing channels... but closing channels brings woes of its own as you've mentioned.. As a hack i thought to replicate the timeout channel by creating a new channel, and doing a sleep on it for the same time as the timeout would be and then dropping something on the said channel to signify timeout is complete... but that doesn't look too pretty and i was hoping you guys had some better alternatives 🙂
closing a channel doesn't usually release resources anyways
I'm not clear on what the objective is
sorry if i was unclear, But the gist of it is to be able to create a lot of new timeout channels for each http request.. (i find myself closing timeoutchannels at the end because if i don't, i see a significant increase in CPU use.).. But by closing timeout channels, i sometimes run into the problem where the new timeout channel i create is actually an older channel that is already exhausted.. I want each timeout channel to be a new resource so i'm not bitten by that behaviour... i searched around and see that this problem has been documented in the past https://clojure.atlassian.net/browse/ASYNC-225
this is an intentional behavior of core.async - by reusing / duplicating them it reduces overhead, by closing them you prevent other people from getting their timeouts
notice the issue tag on the issue you linked was literally edited from "bug" to "new feature"
Yes i did notice it , and was hoping if someone experienced this issue before and had a workaround for it 🙂
I'd take a closer look at what's using the CPU -- it could be that you were reducing load by dropping events on the floor, but that only adresses the symptom - maybe you need larger units of work between channel ops, maybe you need to move CPU intensive tasks out of go blocks into threads
and IO usage out of go blocks as well
you may just have a bit of a space leak
because the timeout is shared between requests it causes the callbacks on the channel to persist between requests
so introducing some level of indirection between the timeout and the callbacks may help
(defn my-timeout [ms] (async/go (async/<! (async/timeout ms))))
having high cpu usage without closing timeout channels sounds like a bug somewhere though
I loved the idea about having the indirection, not sure how succesful it would be , but i'm definitely gonna try it , thanks! 😄
closing a channel is very different than closing an InputStream
there's no file descriptors or heavyweight things that are relinquished
> new timeout channel i create is actually an older channel that is already exhausted.. I want each timeout channel to be a new resource so i'm not bitten by that behaviour. this sentence seems weird to me. an exhausted timeout channel. does this mean already elapsed?
what closing a channel tends to release is anyone waiting on the channel, which can be callbacks that close over just about anything
likely the timeout channel isn't closed (exchausted) because the timeout is elapsed in this scenario it is likely closed because some other request already closed it
yes i meant elapsed, sorry for the confusion
sorry for the confusion, by exhausted i mean elapsed. Since i create timeout channels for each request, at times i would come across newly created timeout channels that are already elapsed since i believe timeouts are shared in cljs.core.async