|
rjmccall posted:so i can understand using a rope-like data structure for strings, and i can maybe understand optimizing the repeated-string case to avoid a trivial way to blow up memory usage, although i suspect that in reality you would be better served just making sure that reasonable repeat counts of space were handled <div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>
|
# ? Jul 26, 2017 23:12 |
|
|
# ? May 29, 2024 04:36 |
MALE SHOEGAZE posted:i just dont understand how a programming language can have 5 (five!) publicly available syntax highlighter (jai-lighting) but no compiler
|
|
# ? Jul 26, 2017 23:18 |
|
Powaqoatse posted:<strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>
|
# ? Jul 26, 2017 23:18 |
|
TOPS-420 posted:p sure coroutines and green threads go back a bit further than that but ok I don't know anything, but to be clear m:n threading is exactly what things like python's asyncio and greenlet and all the others are...right?
|
# ? Jul 26, 2017 23:20 |
|
coroutines aren't exactly what i would call m:n threading, they're more like closures. you can run them on threads and there are apis/patterns that are all about using them with threads but they're not inherently about threads at all m:n threading is when the language gives you an explicit thread abstraction but it's just not implemented 1-1 using lower-level threads. typically this is because the language believes, probably with good reason, that its threads are much more lightweight than the lower-level threads and so there are major advantages of doing context-switching in userspace. like maybe you only context switch at specific safe-points so you don't have to restore as much register state, or maybe something about your language/compiler makes it relatively cheap to dynamically grow the call stack so threads can be initially created with tiny stacks
|
# ? Jul 26, 2017 23:42 |
|
TOPS-420 posted:hey remember perl 6 so string internment?
|
# ? Jul 26, 2017 23:43 |
|
Thermopyle posted:I don't know anything, but to be clear m:n threading is exactly what things like python's asyncio and greenlet and all the others are...right? so looking at these examples i think asyncio is a library that provides a coroutine interfaces for moving work between threads and greenlet is a fork of cpython that uses a super-cheap m:n threads implementation. you could (i hope) reasonably combine them and what you'd be doing is just using the coroutine language feature to painlessly write code that is moved between threads that just happen to be implemented more cheaply than they are in standard cpython there's a bit of a conflict in the ideas because once you're writing async-style code, whether with coroutines or with a bunch of explicit callbacks, you aren't pinning threads anymore and so don't care so much about how cheap they are. one goal of m:n threading (at least for some implementations) is to make threads so lightweight that of course you just fork a thread to do whatever, and then if you need to wait for something you just block that thread because who cares, you're not pinning any major resources. so it addresses the limited-resources problems of "hard" threads but it's still fundamentally a multi-threaded synchronous interface. in an async api based on coroutines, if you truly blocked somehow you'd be wasting the capabilities of your current thread which might be a bigger deal but in practice all the things that look like they block are really asynchronous so you're really yielding and someone else can use that thread and eventually you'll get resumed on potentially a completely different thread. but on a deeper level the differences start to disappear again, especially in languages like python where i think the yielding is mostly all magic behind the scenes and there's nothing inherently different about a coroutine from an ordinary function rjmccall fucked around with this message at 00:04 on Jul 27, 2017 |
# ? Jul 26, 2017 23:46 |
|
fwiw, it might actually be something closer to this re: string copying, which gives a much better example of its usefulness: http://www.evanmiller.org/elixir-ram-and-the-template-of-doom.html
|
# ? Jul 27, 2017 00:05 |
|
TOPS-420 posted:hey remember perl 6 The only thing dumber than they're not having gievn up in shame ten years ago is the logo:
|
# ? Jul 27, 2017 00:14 |
|
cinci zoo sniper posted:its a decent game developer's idea of a system programming language didnt that guy post a couple rants on twitter about a c++ project he had trouble building and then it turned out he had checked out a four year old commit from the github
|
# ? Jul 27, 2017 00:45 |
|
i didn't like the witness
|
# ? Jul 27, 2017 03:01 |
|
Don't look at perl 6 you will go blind
|
# ? Jul 27, 2017 03:06 |
|
Gazpacho posted:Don't look at c++ you will go blind
|
# ? Jul 27, 2017 03:38 |
|
JewKiller 3000 posted:durrrr
|
# ? Jul 27, 2017 04:15 |
|
Gazpacho posted:Don't look at perl 6 you will go blind
|
# ? Jul 27, 2017 04:33 |
|
async/await style and m:n threading look kinda like they're similar to each other at a low level. fundamentally, you're using n threads to run m concurrent tasks of some sort. but I think async/await completely obsoletes m:n threading. async/await makes it visible when you're blocking: if you make an IO call that's synchronous and not something you 'await' for, then you're blocking the thread. with m:n threading who knows what happens. some IO calls will block the thread, while others are safe to use. who knows what other "light threads" the runtime put on your thread that are now blocked. often enough, who knows how to even make a blocking call safe to use, because it can get a bit complicated meanwhile, the desire to quickly and easily create small short-lived threads turns out to not exist. We're much happier with async/await which is pretty much all about concurrency within a single thread. That's what we actually wanted. As far as I can tell, always. And as a bonus, you can scale it out to multiple threads if you want to. the only language that I think did m:n threading well is erlang, and even that I think sometimes has problems with FFI calls to C doing IO and thus blocking threads (or am i wrong about that, mononcqc? iirc, there's an FFI thread you can use to keep that blocking calls off the erlang thread... but that memory is sketchy) IMO, async/await is one of those few recent huge innovations in PL design. I'm impressed.
|
# ? Jul 27, 2017 04:51 |
|
CommunistPancake posted:i didn't like the witness i like watching supergreatfriend playing it when i can't sleep but it looks tedious as gently caress to actually play.
|
# ? Jul 27, 2017 05:07 |
|
crazypenguin posted:async/await style and m:n threading look kinda like they're similar to each other at a low level. fundamentally, you're using n threads to run m concurrent tasks of some sort. yeah greenthreads that can block the underlying os threads and gently caress everything up seem sorta flaccid. the beam does have an issue with ffi where if you don't do it right long running calls can gently caress up the vm, but there's always been a way around that (ports) and a recent version introduced dirty schedulers to handle long running ffi calls, although it does so by starting up new os threads to my understanding so you probably still want to be careful with it (ie don't assume you can do usually Erlang thing of starting a million of them for nearly free)
|
# ? Jul 27, 2017 05:08 |
|
admit it: c++ is bad
|
# ? Jul 27, 2017 05:12 |
|
crazypenguin posted:with m:n threading who knows what happens. some IO calls will block the thread, while others are safe to use. who knows what other "light threads" the runtime put on your thread that are now blocked. often enough, who knows how to even make a blocking call safe to use, because it can get a bit complicated you can just have all io ops yield and use select to fix this async/await is neat if all you are concerned with is io, but userspace cooperative threads are way more powerful
|
# ? Jul 27, 2017 05:15 |
|
cis autodrag posted:i like watching supergreatfriend playing it when i can't sleep but it looks tedious as gently caress to actually play. it's pretty chill and very well done but you need to be into quiet exploration and puzzle games I guess.
|
# ? Jul 27, 2017 05:27 |
|
not really, it's a tradeoff of compiler vs runtime trickery. cooperative threads let you yield control anywhere, which can be a good or bad thing, whereas async/await only work in explicitly async contexts. the async magic breaks down if you try to mix it with generators or closures, but otoh all your await points are explicit, so its harder to do dumb things like accidentally take a mutex then yield control indefinitely, which tends to happen a lot in go code that mixes channels with other concurrency primitives
|
# ? Jul 27, 2017 05:31 |
|
cooperative threads are good, go is bad, fight me
|
# ? Jul 27, 2017 05:52 |
|
JewKiller 3000 posted:cooperative threads are good, go is bad, fight me like what is this amazing powerful thing that you can do with cooperative threads that is not ultimately kindof a bad idea to be relying on
|
# ? Jul 27, 2017 05:57 |
|
rjmccall posted:like what is this amazing powerful thing that you can do with cooperative threads that is not ultimately kindof a bad idea to be relying on i'm sure you already know what green threads are now imagine you're in a functional language (actually functional, not swift) where you allocate poo poo tons of small objects, and that includes poo poo tons of "threads"
|
# ? Jul 27, 2017 06:02 |
|
TOPS-420 posted:hey remember perl 6 Having the rope be a fingertree really makes this pretty much trivial. You've got the string, then fingertree nodes that point to that string three times, then nodes that point to the previous node 3 times, then nodes that point to that node three times, and so on. You can have everything be refcounted, because there are no cycles, and concatenation would be O(log n).
|
# ? Jul 27, 2017 06:02 |
|
JewKiller 3000 posted:i'm sure you already know what green threads are now imagine that language had prolog-like syntax e: although, I think the point he's making is that green threads are not the same as cooperative threads, which must explicitly yield
|
# ? Jul 27, 2017 06:09 |
fritz posted:didnt that guy post a couple rants on twitter about a c++ project he had trouble building and then it turned out he had checked out a four year old commit from the github im not sure how good of a programmer he is, braid is just a well made game is what im saying
|
|
# ? Jul 27, 2017 06:14 |
|
Ploft-shell crab posted:now imagine that language had prolog-like syntax yeah, i mean, i get why someone would like lightweight threads, although i tend to agree with crazypenguin that async/await is just a better design philosophy, but why specifically do you think cooperative threads are cool
|
# ? Jul 27, 2017 06:37 |
|
Having M:N cooperative threads reveal which operations can block and which can't is possible with the right programming language support. You could try naming all your blocking functions with B at the end and do a linting pass... I recently found out about the Seaside framework, which is a C++ futures/promises library (for running event loops on every core). It's actually relatively tolerable to use and makes all the expected use of C++14. The main problem is its I/O capabilities are relatively tied to the needs of ScyllaDB.
|
# ? Jul 27, 2017 07:09 |
|
sarehu posted:You could try naming all your blocking functions with B at the end and do a linting pass... like 90% of the problem with blocking functions is that people dont realize that theyre writing blocking functions.
|
# ? Jul 27, 2017 07:31 |
|
sarehu posted:You could try naming all your blocking functions with B at the end and do a linting pass... lol
|
# ? Jul 27, 2017 08:00 |
|
just run a static analyzer to see which functions block
|
# ? Jul 27, 2017 08:31 |
|
cis autodrag posted:like 90% of the problem with blocking functions is that people dont realize that theyre writing blocking functions.
|
# ? Jul 27, 2017 08:31 |
|
rjmccall posted:like maybe you only context switch at specific safe-points so you don't have to restore as much register state, from having implemented win32 fibers once, I can tell you that you only need to save/restore the stack pointer(s) and non-volatile registers (on x86, ebx esi edi ebp) e: oh, and fpu state
|
# ? Jul 27, 2017 09:37 |
|
sarehu posted:Having M:N cooperative threads reveal which operations can block and which can't is possible with the right programming language support. skimming your post i for a moment had the thrill of imagining that seaside, the smalltalk-for-the-web-project was back from the dead http://www.seaside.st/ always felt that the smalltalk development model, replacing the workspace with a webpage, was a pretty well suited way of doing web stuff, but it seems not to be~~
|
# ? Jul 27, 2017 10:20 |
|
rjmccall posted:m:n threading is when the language gives you an explicit thread abstraction but it's just not implemented 1-1 using lower-level threads. typically this is because the language believes, probably with good reason, that its threads are much more lightweight than the lower-level threads To be fair I'm mostly aware of m:n threading in the context of Unix and Posix threads. The theory here is that userspace thread switching is nice and fast (no system calls!) but it can only take advantage of one actual processor core; meanwhile kernel threads are expensive (context switches!) but can run on multiple cores. So the idea in e.g. Solaris and other commercial Unices and the very first attempts at proper Posix threading on Linux back in like the 90s was to have one 'real' thread per CPU more or less and schedule an arbitrary number of threads on the real threads using a user-space scheduler. Best of both worlds. Turns out doing this efficiently is way harder than people thought. Linux ended up just making kernel threads as lightweight as possible instead, and now even e.g. Solaris has followed suit in its latest versions; one Posix thread is just one kernel-level thread and it's all nice and simple.
|
# ? Jul 27, 2017 11:43 |
|
crazypenguin posted:async/await style and m:n threading look kinda like they're similar to each other at a low level. fundamentally, you're using n threads to run m concurrent tasks of some sort. The blocking of underlying threads happens if there is no preemption in the language currently running the code. For example, Erlang, Go, and Haskell all pre-empt the code they deal with. Go does it on function calls (which means you can lock up a thread by using an infinite loop doing nothing), Erlang on function calls as well (translated to 'reductions' -- but since it has no looping construct, you can't stall it direclty), and iirc Haskell does it on memory allocation. For all these languages, the scheduler is easy to consider essentially preemptive since you have to do a distinctly bad thing to lock the underlying threads. Non-preemptive environments (read: cooperatives) such as those using Akka actors and other M:N schemes ask you to be careful about long operations since yeah, scheduling is explicit. In the case of Erlang regarding FFI, there's 3 main ways to do it: - A VM driver, which is mostly on the way out. You'd get your own dedicated thread to do poo poo - A port program, where you use an OS program and stdio to communicate with it. Easiest way to go, external to the VM - NIFs, the equivalent to FFIs. NIFs have C code running within the thread of your Erlang code and therefore cannot be preempted. The idea for that C code is that you must ideally have it run under 1ms and manually bump its reduction count to prevent the process from never scheduling out. There are calls in the interface to let the C code split itself over many shorter schedulings if required. This has been the default state for the last 3-4 years. Starting in last year's release as an experimental feature, and from last June as a default VM option, Erlang introduced a dirty scheduler. The dirty scheduler runs in a distinct thread, and asks you classify your NIF as either I/O or CPU bound (and can be dynamically updated). When a process calls into a dirty NIF, it is suspended and only re-scheduled once the NIF has completed. That allows to call long-running (or IO-blocked) C code without interfering with the rest of the Erlang code on the system. The underlying assumption is that you will still run more Erlang than C code overall; the mechanism aims to protect your Erlang code from being impacted by C, not your C code from impacting your other bits of C code. Early benchmarks about that system in beta mentioned an overhead of ~10-15% for short-runnng dirty NIFs over short-running non-dirty NIFs, which translated to 2µs...10µs depending on configuration options. This is probably acceptable for most cases where you'd block the thread for over 1 milliseconds.
|
# ? Jul 27, 2017 13:57 |
|
Also async/await is a great fit when your program requires a natural "request/response" pattern or mechanism, or a kind of scatter-gather approach, but it is not nearly as adequate when it comes to modelling entities in your system. For example, the idea that you could model two users talking to each other, or implement any sort of master-master protocol that includes negotiations or exchange between entities is hardly doable with async/await unless you take a separate approach and implement a kind of set of channel/queue in there that acts as a data store you poll from and write to. It's doable, but certainly not the most optimal scheme, and who knows how it composes with additional entities joining the protocol. Most M:N schemes (with preemption), whether they use channels, mailboxes, or whatever, tend to be a superset of what async/await can do. Async/await just represents a really easy way to retrofit a huge chunk of the desirable semantics in a given language. Even then all not are equal; C#'s async/await is a million times nicer than any of Javascript's ungodly chain of calls.
|
# ? Jul 27, 2017 14:05 |
|
|
# ? May 29, 2024 04:36 |
|
cooperative is bad, pre-emptive is extremely good, because pre-emptive appears later in the textbook, unironically
|
# ? Jul 27, 2017 15:42 |