Good news everyone!
I have a working prototype of a preemptive scheduler:
https://codereview.appspot.com/9136045
It's not based on the design I described previously. Instead it
[ab]uses split stack machinery to preempt long running goroutines.
Sysmon thread watches for P's executing the same goroutine for more
than X ms. If finds a one it sets g->stackguard to a very large value,
so that on next split stack check the goroutine calls morestack() and
gets preempted
On Sun, May 12, 2013 at 11:19 PM, Dmitry Vyukov <dvy...@google.com> wrote:Good news everyone!Yeah, really. Thank you for working on that.
How do you handle busy loops that doesn't call any split-stack functions (or one
that calls no function at all)?
could we instruct gc to place a dummy call (e.g. runtime.emptyfunc) that onlychecks stack limit and return into every while-style loop that doesn't call any split-stack functions to handle this corner case? (of course, we can further optimize thissolution.)
I have a working prototype of a preemptive scheduler:
https://codereview.appspot.com/9136045
It's not based on the design I described previously. Instead it
[ab]uses split stack machinery to preempt long running goroutines.
Sysmon thread watches for P's executing the same goroutine for more
than X ms. If finds a one it sets g->stackguard to a very large value,
so that on next split stack check the goroutine calls morestack() and
gets preempted.
On Mon, May 13, 2013 at 5:56 PM, Ian Lance Taylor <ia...@golang.org> wrote:Ah, I see. The register spills will be around the function call on
> On Sun, May 12, 2013 at 11:14 PM, Dmitry Vyukov <dvy...@google.com> wrote:
>> On Mon, May 13, 2013 at 7:42 AM, Ian Lance Taylor <ia...@golang.org> wrote:
>>> We don't need to solve the halting problem here. It suffices for the
>>> compiler to add a function call (or other check for preemption) to
>>> every backward branch. We can optimize by examining the control flow
>>> graph: we only need to add a check if there is some path from the
>>> branch target to the branch that does not make any function calls. If
>>> we go this route we should be able to arrange for a preemption check
>>> to be two instructions: a load instruction and a conditional branch
>>> instruction, predicted not taken...
>>
>> ... and all register spill/restore. We can teach the compiler that
>> this call does not spoil registers, but that would require saving and
>> restoring whole context.
>
> On Intel we can use the test instruction, no registers required.
cold path, and should not affect hot path, right?
I just use g->stackguard. So not additional TLS variable is required.
> Note
> that I am assuming an additional TLS variable which is set to non-zero
> when preemption is required. I think that is clearly worth doing if
> we do decide to go this route.
Those aren't corner cases. They're broken cases. I don't think we should optimise for them.
--
---
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Wed, May 15, 2013 at 8:58 PM, Keith Randall <k...@google.com> wrote:Thanks!
> I looked through hashmap and I don't see anything that would break because
> of this change. But it is a bit dicey, for instance if the clearbucket()
> macro was a function call instead that could trigger a gc, it would break.
> In fact, the clearing code *will* break if we move to allowing gc at
> backedges (not a showstopper - it would be easy to fix).
I will add m->locks++/-- around hashmap functions.
After all it works perfectly to have a tight pure cpu loop without any IO as long as it finishes in a sensible amount of time.