Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solve concurrency #174

Closed
6 of 8 tasks
andrewrk opened this issue Aug 25, 2016 · 20 comments
Closed
6 of 8 tasks

solve concurrency #174

andrewrk opened this issue Aug 25, 2016 · 20 comments
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Aug 25, 2016

On top of the ability to create a kernel thread, Zig should have an abstraction that allows code to express concurrency.

@andrewrk andrewrk added the enhancement Solving this issue will likely involve adding new logic or components to the codebase. label Aug 25, 2016
@andrewrk andrewrk added this to the 0.1.0 milestone Aug 25, 2016
@winksaville
Copy link
Contributor

Are you able to use Atomic code generation natively in Zig? If not that would be a great place to start.

@andrewrk
Copy link
Member Author

andrewrk commented Sep 3, 2016

We have some built-in functions for this currently with plans to for many more atomic primitives.

In addition this issue is calling to research M:N threading and perhaps some kind of promise abstraction and/or cooperative multithreading.

@winksaville
Copy link
Contributor

Nice to hear atomics are supported. I'd like to caution on keeping things simple, one thing I really like about C is that I have very good control on how big programs are. You can create programs which don't use any "std" libraries and create code that are just a few bytes in size. Another words the programmer is in complete control.

So I suggest, if you want to have features like M:N threading or whatever, there should be no cost in speed or size in programs that don't use them.

@andrewrk
Copy link
Member Author

andrewrk commented Sep 5, 2016

Your comments are in complete alignment with Zig's philosophy. Whatever concurrency features we have, they will be built on top of the kernel thread abstraction that will be provided in the standard library, and they will not depend on a black box runtime or hide errors such as memory allocation failure.

@pavildon
Copy link
Contributor

Just my opinion: i think LibUV has an excellent and industry proven abstraction for tasks and sockets/filesystem IO, and sits just in the middle of ASIO/STDC++ and threads in C11, I'm familiarising with zig trying to port parts of the async loop of that library using BSD's kqueue, but first I have to finish an allocator using mmap.

@andrewrk
Copy link
Member Author

but first I have to finish an allocator using mmap.

ahh, very exciting. How do you plan to handle the problem of different threads allocating and deallocating memory?

@pavildon
Copy link
Contributor

pavildon commented Sep 22, 2016

Im currently reading the malloc related source code in http://opensource.apple.com//source/Libc/Libc-583/gen/malloc.c it seems that it take pages with mmap, the expensive syscall ( it seems mmap is thread safe) is done less frequently and in the actual malloc call that subdivides the page for allocations just lock a mutex releasing it when it finish (macros MALLOC_LOCK and MALLOC_UNLOCK) , note : osx deprecated the use of sbrk and brk.

edit: good reading on the subject : Mac OS X Internals: A Systems Approach (memory chapter)

@andrewrk andrewrk modified the milestones: 0.1.0, 0.2.0 Apr 20, 2017
@kyle-github
Copy link

Very belated comment.

I strongly suggest not supporting M:N threading.

TL;DR: nearly every system that did use it in the past has abandoned it including Java, Solaris, Linux...

Some light reading. Dan Kegel has some good links in his C10k web pages:

Dan Kegel's C10k notes

There was an interesting discussion on the Rust lists a few years ago about this (a bit of a slog to read):

The future of M:N threading

@kyle-github
Copy link

In view of systems selling now with 32+ cores on the desktop, it seems like the benefits of M:N threading are less and less obvious. At the same time, there seems to have been little progress made on the problems with it.

@andrewrk
Copy link
Member Author

andrewrk commented Mar 3, 2018

We're one step closer to having solved concurrency now that we have coroutines.

Next steps:

  • Kernel threads in the standard library. Thread local variables?
  • Proof of concept M:N threading. (multiplex coroutines onto a thread pool)
  • Static call graph analysis to determine worst case stack upper bound.

After this, concurrency will be solved.

andrewrk added a commit that referenced this issue Apr 14, 2018
this adds kernel thread support to the standard library for
linux.

See #174
andrewrk added a commit that referenced this issue Apr 15, 2018
@binary132
Copy link

binary132 commented May 5, 2018

I hope you don't substitute a serial event loop and callbacks for concurrency. I think the Rust experimental RFC for adding yield / generator-style coroutines is a pretty good read. Here it is: https://github.com/rust-lang/rfcs/blob/master/text/2033-experimental-coroutines.md

@pjz
Copy link
Contributor

pjz commented Jun 11, 2018

Someone else's recent thoughts on concurrency are at https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/ ; I tend to agree philosophically, though I think in Zig the right answer might be handing in Nurseries much like Allocators.

@binary132
Copy link

binary132 commented Jun 11, 2018

go is nice because it's an extremely simple API.

I think go is not aligned with Zig design principles (it hides complexity and runtime cost, and lacks a sane error-handling or panic/unwind approach) and neither is a "concurrency framework" (framework is a dirty word for similar reasons.) I think a Zig-aligned solution is to offer a small and simple set of orthogonal APIs that users can build abstractions on, such as go or spawn, in a safe and zero-cost way, if they would like to.

Here is another good article on problems intrinsic to "concurrency" where the goroutine model falls short:
NUMA-aware scheduler for Go (and HN discussion)

@pjz
Copy link
Contributor

pjz commented Jun 13, 2018

The point of that article is that error handling in the context of concurrency can be difficult using traditional primitives, and wrapping them up in something like a Nursery (see the paper) helps by having a concurrency manager (much like an Allocator is an 'allocation manager') to deal with catching/handling errors and... managing concurrency.

@isaachier
Copy link
Contributor

I think people misunderstand the mission of Zig. The idea of "perfect software" is not to say that Zig wants to make errors impossible (which seems to be more of a Rust goal). What it means is that only Zig and C enable local handling of out of memory errors. C++, Rust, Java, Go, Python, Ruby, etc. all handle OOM through exceptions (or crashing), which leads to unsafe code that isn't handled at the call site. No one writes C++ with every std::vector::push wrapped in a try/catch to check for OOM. Zig is a modern flavor of the C approach without some of C's undefined behavior.

TL;DR IMO Zig is not in the business of forbidding unsafe practices. In fact, Zig should encourage low-level, unsafe code and keep opinions to itself. Zig's only axiom is that error values are better than exceptions. I think the ideas put forward here are interesting and might be worth putting in an external library, but not fundamental to the language in any way.

@andrewrk andrewrk mentioned this issue Jul 5, 2018
3 tasks
andrewrk added a commit that referenced this issue Jul 7, 2018
 * add std.atomic.QueueMpsc.isEmpty
 * make std.debug.global_allocator thread-safe
 * std.event.Loop: now you have to choose between
   - initSingleThreaded
   - initMultiThreaded
 * std.event.Loop multiplexes coroutines onto kernel threads
 * Remove std.event.Loop.stop. Instead the event loop run() function
   returns once there are no pending coroutines.
 * fix crash in ir.cpp for calling methods under some conditions
 * small progress self-hosted compiler, analyzing top level declarations
 * Introduce std.event.Lock for synchronizing coroutines
 * introduce std.event.Locked(T) for data that only 1 coroutine should
   modify at once.
 * make the self hosted compiler use multi threaded event loop
 * make std.heap.DirectAllocator thread-safe

See #174

TODO:
 * call sched_getaffinity instead of hard coding thread pool size 4
 * support for Windows and MacOS
 * #1194
 * #1197
@andrewrk
Copy link
Member Author

Concurrency is solved. We have the ability to create kernel threads on all supported targets using std.os.spawnThread. On top of that we have M:N threading implemented in userland with coroutines using async/await syntax. For example:

  • std.event.Loop
  • std.event.Lock
  • std.event.Channel
  • std.event.Group
  • std.event.Future

The self-hosted compiler is underway using these abstractions.

The @atomicRmw issue mentioned above is a separate issue: #1220
Also stack upper bound determination is a separate issue: #157

@ghost
Copy link

ghost commented Jul 11, 2018

I would like to suggest that issues should only be marked as done once documentation is added because without documentation any feature is about as good as if it would not exist in the fist place.

Maybe this is too much to ask at this point but nevertheless wanted to express this opinion because at this point (seeing the issue is closed) I would love to read into some nice examples.

Thanks for your work 👍

@andrewrk
Copy link
Member Author

I agree with you about how important docs are. Here are my priorities:

  1. stabilize the language
  2. document everything about the language
  3. stabilize the standard library
  4. document everything about the standard library
  5. 1.0.0

So far we're still on (1).

@ghost
Copy link

ghost commented Jul 11, 2018

ok I was just too eager to read on, but I'll wait, no problem 👍

@ghost
Copy link

ghost commented Sep 22, 2018

@andrewrk have User-Level-Threads on windows been considered?
https://docs.microsoft.com/en-us/windows/desktop/procthread/user-mode-scheduling

google apparently implemented the same thing on linux in a proprietary way and got speedups from it

@andrewrk andrewrk modified the milestones: 0.4.0, 0.3.0 Sep 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Projects
None yet
Development

No branches or pull requests

7 participants