Fair point, thanks a lot for the insight. Any pointers to a significant data-flow oriented clojure codebase would be awesome, because that's not something I see a lot in the wild, and I'm still trying to wrap my head around how to implement this on a very complex system.
Le jeudi 30 juillet 2015 08:37:18 UTC-7, tbc++ a écrit : > > My advice is to treat channel ops (<! and >!) as IO, which they are. In > functional programming we try to stay away from doing IO deep down inside a > call stack. So don't do that. Instead use async/pipeline functions and > channel transducers to create pipelines and flow the data through them. > > A sort of anti-pattern I see a lot is creating a lot of one-shot channels > and go blocks inside every function. The problem, as you see is that this > creates a lot of garbage. A much more efficient plan is to stop using > core.async as a RPC-like system, and start using it more like a dataflow > language: Identity data sources and sinks, and then transform and flow the > data between them via core.async. > > It's interesting to note that core.async started as something that looked > a lot like C#'s Async/Await, but that was dropped in favor of CSP pretty > quickly. So there's reasons why the language isn't optimized for this sort > of programming style. > > Timothy > > On Thu, Jul 30, 2015 at 9:17 AM, Martin Raison <martin...@gmail.com > <javascript:>> wrote: > >> Hey Thomas, >> >> Thanks for the great feedback! A few clarifications below. >> >> >>> It should be noted that your async macro does in fact use the dispatcher >>> just like a normal go would, the only difference is that it will start >>> executing immediately in the current thread until the first "pause" instead >>> of dispatching. After the "pause" the dispatcher will run it though which >>> is not guaranteed to be the same thread. >>> >> >> I agree that the dispatcher will eventually be used, but the idea is that >> if your code is deeply nested, this will only happen at the deepest level >> (when an actual go block is used). So the dispatcher will only be run >> there, instead of running for every single wrapping function call. The idea >> is for the codebase to look like this (across multiple functions): >> >> (async ... (<! (async ... (<! (async ... (<! (async ... (<! (async ... >> (<! (go <long-running stuff, run in a different thread>))))))))))) >> >> Here the dispatcher is only run once, instead of 6 times. All the "glue >> code" is run in the calling thread. >> >> >>> Therefore I'm not actually sure a ThreadLocal will work. Did you test >>> that you get the actual correct result? >>> >> >> I do get the correct result, although your concern is valid. I think it >> works because the generated state machine calls ioc/return-chan in the >> curent thread. If part of the computation has been dispatched to an other >> thread, then the result of that dispatched computation will be brought back >> into the current thread with an actual channel before being fed to >> ioc/return-chan. I would love to know if there are situations where >> return-chan would be called directly from another thread, since I haven't >> observed that so far and I'm not familiar enough with the state machine >> internals. >> >> >>> Your benchmark is also not very useful, you are basically just measuring >>> the frameworks overhead which is tiny to what it provides. In actual >>> programs most of the time will not be spent in core.async internals, at >>> least not from what I have observed so far. go blocks are actually pretty >>> cheap. >>> >> >> Measuring the framework overhead was in fact my intention, but I agree it >> would be useful to know if the core.async overhead can actually be >> significant in a real-world application. Typically an IO-bound application >> passing lots of requests to other servers and doing very light >> transformation on the results. >> >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > “One of the main causes of the fall of the Roman Empire was that–lacking > zero–they had no way to indicate successful termination of their C > programs.” > (Robert Firth) > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.