Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



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

but why would you bother seriously optimizing the string algorithms for that case

<div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>

Adbot
ADBOT LOVES YOU

cinci zoo sniper
Mar 15, 2013




MALE SHOEGAZE posted:

i just dont understand how a programming language can have 5 (five!) publicly available syntax highlighter (jai-lighting) but no compiler
because jai is interoperable with c, you can just extend c sytax highlighter with new things

gonadic io
Feb 16, 2011

>>=

Powaqoatse posted:

<strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

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?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
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

Bloody
Mar 3, 2013

TOPS-420 posted:

hey remember perl 6

http://www.evanmiller.org/why-im-learning-perl-6.html


p sure coroutines and green threads go back a bit further than that but ok


i too do most of my processing on repeated copies of a string. this is an important thing to optimize

so string internment?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

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

Arcsech
Aug 5, 2008
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

Ellie Crabcakes
Feb 1, 2008

Stop emailing my boyfriend Gay Crungus

TOPS-420 posted:

hey remember perl 6
The Chinese Democracy of programming languages.

The only thing dumber than they're not having gievn up in shame ten years ago is the logo:

fritz
Jul 26, 2003

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

aardvaard
Mar 4, 2013

you belong in the bog of eternal stench

i didn't like the witness

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
Don't look at perl 6 you will go blind

JewKiller 3000
Nov 28, 2006

by Lowtax

Gazpacho posted:

Don't look at c++ you will go blind

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde

Ellie Crabcakes
Feb 1, 2008

Stop emailing my boyfriend Gay Crungus

Gazpacho posted:

Don't look at perl 6 you will go blind
You'll be fine if you strengthen your eyes by attempting to find the point of perl 6.

crazypenguin
Mar 9, 2005
nothing witty here, move along
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.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

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.

Arcsech
Aug 5, 2008

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.

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.

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)

JewKiller 3000
Nov 28, 2006

by Lowtax

admit it: c++ is bad

the talent deficit
Dec 20, 2003

self-deprecation is a very british trait, and problems can arise when the british attempt to do so with a foreign culture





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

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

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.

TOPS-420
Feb 13, 2012

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

JewKiller 3000
Nov 28, 2006

by Lowtax
cooperative threads are good, go is bad, fight me

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

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

JewKiller 3000
Nov 28, 2006

by Lowtax

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"

Zemyla
Aug 6, 2008

I'll take her off your hands. Pleasure doing business with you!

TOPS-420 posted:

hey remember perl 6

http://www.evanmiller.org/why-im-learning-perl-6.html


p sure coroutines and green threads go back a bit further than that but ok


i too do most of my processing on repeated copies of a string. this is an important thing to optimize

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).

my homie dhall
Dec 9, 2010

honey, oh please, it's just a machine

JewKiller 3000 posted:

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"

now imagine that language had prolog-like syntax :getin:

e: although, I think the point he's making is that green threads are not the same as cooperative threads, which must explicitly yield

cinci zoo sniper
Mar 15, 2013




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

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ploft-shell crab posted:

now imagine that language had prolog-like syntax :getin:

e: although, I think the point he's making is that green threads are not the same as cooperative threads, which must explicitly yield

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

sarehu
Apr 20, 2007

(call/cc call/cc)
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.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

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.

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

sarehu posted:

You could try naming all your blocking functions with B at the end and do a linting pass...

lol

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



just run a static analyzer to see which functions block

Ellie Crabcakes
Feb 1, 2008

Stop emailing my boyfriend Gay Crungus

cis autodrag posted:

like 90% of the problem with blocking functions is that people dont realize that theyre writing blocking functions.
That's why I write everything in Node.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

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 :eng101: (on x86, ebx esi edi ebp)

e: oh, and fpu state :sweatdrop:

Cybernetic Vermin
Apr 18, 2005

sarehu posted:

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.

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~~

feedmegin
Jul 30, 2008

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.

MononcQc
May 29, 2007

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.

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.

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.

MononcQc
May 29, 2007

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.

Adbot
ADBOT LOVES YOU

Convoolio
Oct 31, 2005

cooperative is bad, pre-emptive is extremely good, because pre-emptive appears later in the textbook, unironically

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply