From d6a2d0a9cfd25d1be563f8e1647f40270368fa68 Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Thu, 21 Jan 2021 18:58:20 +0100 Subject: [PATCH] content: draft zero-alloc-call-sched --- .../app/window.go | 0 .../go.mod | 0 .../go.sum | 0 .../main.go | 0 .../mainthread/mainthread.go | 0 .../mainthread/mainthread_test.go | 0 .../thread/bench_test.go | 16 +++++++ .../thread/thread.go | 13 +++-- .../thread/thread_test.go | 12 +---- content/posts/zero-alloc-call-sched.md | 48 +++++++++++++++++++ 10 files changed, 72 insertions(+), 17 deletions(-) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/app/window.go (100%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/go.mod (100%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/go.sum (100%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/main.go (100%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/mainthread/mainthread.go (100%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/mainthread/mainthread_test.go (100%) create mode 100644 content/assets/zero-alloc-call-sched/thread/bench_test.go rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/thread/thread.go (83%) rename content/assets/{zero-cost-thread-sched => zero-alloc-call-sched}/thread/thread_test.go (88%) create mode 100644 content/posts/zero-alloc-call-sched.md diff --git a/content/assets/zero-cost-thread-sched/app/window.go b/content/assets/zero-alloc-call-sched/app/window.go similarity index 100% rename from content/assets/zero-cost-thread-sched/app/window.go rename to content/assets/zero-alloc-call-sched/app/window.go diff --git a/content/assets/zero-cost-thread-sched/go.mod b/content/assets/zero-alloc-call-sched/go.mod similarity index 100% rename from content/assets/zero-cost-thread-sched/go.mod rename to content/assets/zero-alloc-call-sched/go.mod diff --git a/content/assets/zero-cost-thread-sched/go.sum b/content/assets/zero-alloc-call-sched/go.sum similarity index 100% rename from content/assets/zero-cost-thread-sched/go.sum rename to content/assets/zero-alloc-call-sched/go.sum diff --git a/content/assets/zero-cost-thread-sched/main.go b/content/assets/zero-alloc-call-sched/main.go similarity index 100% rename from content/assets/zero-cost-thread-sched/main.go rename to content/assets/zero-alloc-call-sched/main.go diff --git a/content/assets/zero-cost-thread-sched/mainthread/mainthread.go b/content/assets/zero-alloc-call-sched/mainthread/mainthread.go similarity index 100% rename from content/assets/zero-cost-thread-sched/mainthread/mainthread.go rename to content/assets/zero-alloc-call-sched/mainthread/mainthread.go diff --git a/content/assets/zero-cost-thread-sched/mainthread/mainthread_test.go b/content/assets/zero-alloc-call-sched/mainthread/mainthread_test.go similarity index 100% rename from content/assets/zero-cost-thread-sched/mainthread/mainthread_test.go rename to content/assets/zero-alloc-call-sched/mainthread/mainthread_test.go diff --git a/content/assets/zero-alloc-call-sched/thread/bench_test.go b/content/assets/zero-alloc-call-sched/thread/bench_test.go new file mode 100644 index 0000000..c187e5a --- /dev/null +++ b/content/assets/zero-alloc-call-sched/thread/bench_test.go @@ -0,0 +1,16 @@ +package thread_test + +import ( + "testing" + "x/thread" +) + +func BenchmarkThreadCall(b *testing.B) { + th := thread.New() + f := func() {} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + th.Call(f) + } +} diff --git a/content/assets/zero-cost-thread-sched/thread/thread.go b/content/assets/zero-alloc-call-sched/thread/thread.go similarity index 83% rename from content/assets/zero-cost-thread-sched/thread/thread.go rename to content/assets/zero-alloc-call-sched/thread/thread.go index b4fdd63..e457128 100644 --- a/content/assets/zero-cost-thread-sched/thread/thread.go +++ b/content/assets/zero-alloc-call-sched/thread/thread.go @@ -25,14 +25,15 @@ type funcData struct { done chan struct{} } -// Thread offers facilities to schedule function calls to run -// on a same thread. +// Thread offers facilities to schedule function calls to run on a +// specific thread. type Thread struct { f chan funcData terminate chan struct{} } -// Call calls f on the given thread. +// Call calls f on the given thread and returns true if the call is +// complete or false if failed. func (t *Thread) Call(f func()) bool { if f == nil { return false @@ -43,9 +44,7 @@ func (t *Thread) Call(f func()) bool { default: done := donePool.Get().(chan struct{}) defer donePool.Put(done) - defer func() { - <-done - }() + defer func() { <-done }() t.f <- funcData{fn: f, done: done} } @@ -62,7 +61,7 @@ func (t *Thread) Terminate() { } } -// New creates +// New creates a thread. func New() *Thread { t := Thread{ f: make(chan funcData), diff --git a/content/assets/zero-cost-thread-sched/thread/thread_test.go b/content/assets/zero-alloc-call-sched/thread/thread_test.go similarity index 88% rename from content/assets/zero-cost-thread-sched/thread/thread_test.go rename to content/assets/zero-alloc-call-sched/thread/thread_test.go index 3e96660..cb2a514 100644 --- a/content/assets/zero-cost-thread-sched/thread/thread_test.go +++ b/content/assets/zero-alloc-call-sched/thread/thread_test.go @@ -3,6 +3,8 @@ // // The code below is produced by Changkun Ou . +// +build linux + package thread_test import ( @@ -63,13 +65,3 @@ func TestThread(t *testing.T) { t.Fatalf("failed to schedule function on the same thread.") } } - -func BenchmarkThreadCall(b *testing.B) { - th := thread.New() - f := func() {} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - th.Call(f) - } -} diff --git a/content/posts/zero-alloc-call-sched.md b/content/posts/zero-alloc-call-sched.md new file mode 100644 index 0000000..dda275b --- /dev/null +++ b/content/posts/zero-alloc-call-sched.md @@ -0,0 +1,48 @@ +--- +date: 2021-01-21T10:57:59+01:00 +toc: true +slug: /zero-alloc-call-sched +tags: + - Channel + - EscapeAnalysis + - GUI + - MainThread + - Thread +title: Scheduling Calls with Zero Allocation +draft: true +--- + +Author(s): [Changkun Ou](https://changkun.de) + +GUI programming in Go is a little bit tricky. The infamous issue regarding interacting with the legacy GUI frameworks is that most of the graphics related APIs must be called from the main thread. This basically violates the concurrent nature of Go: A goroutine may be arbitrarily and randomly scheduled or rescheduled on different running threads, i.e., the same pice of code will be called from different threads over time, even without evolving the `go` keyword. + + + + +## Background + +TODO: + +## The Main Thread + +TODO: + +## Cost Analysis and Optimization + +TODO: + +## Optimal Threading Control + +TODO: + +## Verification and Discussion + +TODO: + +## Conclusion + +TODO: + +## References + +TODO: \ No newline at end of file