architecture

Zaymon 2021-07-10T04:19:17.005500Z

Where does core.async fit in with web applications? At what point would you decide to use it? Where has it helped solve a problem in your application?

➕ 1
Linus Ericsson 2021-07-10T17:33:03.009600Z

Pushing out changes to various clients via websockets using a mult-channel, and quite a lot logic handling websockets.

donaldball 2021-07-10T18:08:54.013100Z

Anytime you want to wait for a message across a set of channels, you’re in the core.async sweet spot.

donaldball 2021-07-10T18:11:38.015800Z

I have used them to good effect in managing work pools especially where I need to be able to insert priority messages like config changes and shutdown events, and moreover guarantee bounded graceful termination.

Ben Sless 2021-07-10T18:35:45.016800Z

@donaldball that's a very good use case, can you elaborate more on it?

fabrao 2021-07-10T12:29:42.006500Z

Mauricio from Chlorine said you should use promise instead of core.async

Zaymon 2021-07-11T02:12:43.032900Z

Why?

Jakub Holý (HolyJak) 2021-07-22T19:10:38.055900Z

I would say, as always, it depends. Promise is simple. Core.async is powerful.

Ben Sless 2021-07-10T13:08:01.006600Z

I don't think we've found the right abstraction to mix the two. Regular old async might be better, focus on simple design instead

2021-07-10T14:37:25.007600Z

core.async is fundamentally a tool for scaling. There’s very little core.async can do that you cannot accomplish with java threads and queues.

2021-07-10T14:38:14.008500Z

But core.async handles coordination in the JVM instead of passing it off to the OS, so it’s less memory/cpu intensive.

Ben Sless 2021-07-10T14:53:25.009300Z

I wonder how much overhead is added by allocation and locking. core.async isn't lockless, it's just a good abstraction. Still leaks color if you mix it with business logic

2021-07-10T17:50:21.010500Z

My understanding is the bulk of the overhead of threads is 1) stack allocation for each thread, and 2) context switches between userland and kernalland.

2021-07-10T17:50:33.010900Z

Could be wrong. It’s not exactly my realm of expertise.

2021-07-10T17:51:48.011600Z

But if that’s the case, then locking is only problematic when it involves a context switch.

emccue 2021-07-10T19:03:45.018500Z

@zaymon.a.fc Realistically, watching the buglist die down on Project loom my impression is you can expect more scaleable non-async code in probably 3 years

emccue 2021-07-10T19:04:29.019400Z

if your app won't be netflix big by that point its a probably smarter buisiness decision to save developer time and just write sync code thats slower than it needs to be

emccue 2021-07-10T19:06:33.020900Z

core.async is still a good tool, but the tradeoff of faster code for worse stack traces, limited syntax, etc isn't great

emccue 2021-07-10T19:07:11.021500Z

core.async did it better than most, but the era of that tradeoff is near its end

emccue 2021-07-10T19:08:08.022Z

at the least for the jvm - <!! and <! could be the same

lukasz 2021-07-10T19:10:14.024100Z

I keep thinking if I'm missing out on not using core.async - all services used in our product rely on threads/threadpools/futures/some of the j.u.concurrent stuff - maybe because we have to ensure that any given service always has at least 2 instances, I'm not sure what is the actual benefit of using core.async

emccue 2021-07-10T19:14:54.024200Z

Just like every other async thing, its basically library level green threads

emccue 2021-07-10T19:15:33.024400Z

your machine can wait on way more IO connections than you can make OS threads for

emccue 2021-07-10T19:16:19.024600Z

so if your threadpool is size 50, the most concurrent requests you can handle on a machine is 50

emccue 2021-07-10T19:16:51.024800Z

core.async lets you make each thread juggle between different tasks with explicit yield points (cooperative concurrency)

emccue 2021-07-10T19:17:20.025Z

and that in turn lets you handle more than 50 tasks on 50 OS threads

emccue 2021-07-10T19:17:53.025200Z

something something littles law

lukasz 2021-07-10T19:18:48.025400Z

Right, I see that. I guess it's the nature of what we're building: a lot of slow outbound network requests to external services, which are heavily rate limited, having up 50 concurrent requests doesn't really speed up anything

emccue 2021-07-10T19:21:04.025600Z

yeah - and thats fine. A huge problem with async stuff existing is that it scratches the itch in our brains that tells us to be fast and do fast thing

emccue 2021-07-10T19:22:00.025800Z

and very few of us are netflix scale, but if you buy into async you start making all your libraries follow async patterns and split the ecosystem

lukasz 2021-07-10T19:22:44.026Z

Yeah, exactly, I might as well just spin up more service instances than squeeze more performance out of a single app

emccue 2021-07-10T19:23:55.026200Z

but you have to admit that knowing that - that your time and effort is worth more than 5 extra machines or whatever - isn't obvious to everyone

emccue 2021-07-10T19:25:00.026400Z

so as an ecosystem and a community we will be a lot better off with loom even if its not absolutely perfect

👆 1
emccue 2021-07-10T19:25:34.026800Z

^example

emccue 2021-07-10T19:29:52.027100Z

One thing I want to see tried is the whole suggestion by the JVM team that you should handle rate limiting stuff with semaphores instead of just having 10 threads

emccue 2021-07-10T19:30:22.027300Z

since im not exactly convinced that works for everyone

lukasz 2021-07-10T19:33:44.027500Z

I wonder if this kind of bias comes from folks having primarily software eng background, once you get into operations and how things actually run and have to serve customers, a lot of assumptions are invalidated because of practical reasons. Regardless, project Loom is really exciting and even if it delivers 80% of it's promises it's going to be a massive step forward

2021-07-10T19:37:15.027700Z

@emccue why wouldn’t that work for someone?

2021-07-10T19:38:20.027900Z

2 semaphores: 1 for rate limiting (so you block on this one for a time), 1 for backpressure (so you immediately reject)

2021-07-10T19:38:39.028100Z

I’ve been thinking about this lately, so I’m curious your thoughts

emccue 2021-07-10T19:39:22.028300Z

It works conceptually - you can always write new code that does it that way

emccue 2021-07-10T19:39:34.028500Z

but i'm concerned about

emccue 2021-07-10T19:41:35.028800Z

1. The java api for it. In clojure we can make (with-semaphore semaphore ...) so we will be fine, but the java api might be permanently clunky (ecosystem level)

emccue 2021-07-10T19:43:06.029Z

2. Refactoring existing code might not be straight forward. Its all kosher if your api accesses are "well designed" and in a single namespace, but I doubt thats all code that implicitly relies on assumptions of max N parallelism

emccue 2021-07-10T19:45:55.029300Z

3. I never even thought of 2 semaphores. Education on this is bad and I am actively interested and still basically an idiot

emccue 2021-07-10T19:47:19.030200Z

4. Locks be hard to get right or remember to do. Esp on a team - might get pointless deadlock (i think)

emccue 2021-07-10T19:47:37.030500Z

5. just a general vibe of uncertainty that lives rent free in my brain

2021-07-10T22:17:43.032500Z

yeah semaphores aren’t quite like a regular lock

2021-07-10T22:18:09.032700Z

it’s fairly easy to avoid deadlock

Ben Sless 2021-07-10T20:04:52.031100Z

There's some caveats to that. vthreads aren't free

emccue 2021-07-10T20:05:39.031300Z

neither are go blocks

emccue 2021-07-10T20:07:09.032Z

it would make the cooperative concurrency use cases a lot more narrow even if it isn't perfect for every use

Ben Sless 2021-07-10T20:08:37.032300Z

True, it's just there are always surprises on that end of the spectrum, whatever implementation you go with