-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
content: update zero-alloc-call-sched
- Loading branch information
Showing
15 changed files
with
953 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package app | ||
|
||
import ( | ||
mainthread "x/mainthread-opt2" | ||
"x/thread" | ||
|
||
"github.com/go-gl/glfw/v3.3/glfw" | ||
) | ||
|
||
// Init initializes an app environment. | ||
func Init() (err error) { | ||
mainthread.Call(func() { err = glfw.Init() }) | ||
return | ||
} | ||
|
||
// Terminate terminates the entire application. | ||
func Terminate() { | ||
mainthread.Call(glfw.Terminate) | ||
} | ||
|
||
// Win is a window. | ||
type Win struct { | ||
win *glfw.Window | ||
th *thread.Thread | ||
} | ||
|
||
// NewWindow constructs a new graphical window. | ||
func NewWindow() (*Win, error) { | ||
var ( | ||
w = &Win{} | ||
err error | ||
) | ||
mainthread.Call(func() { | ||
w.win, err = glfw.CreateWindow(640, 480, "golang.design/research", nil, nil) | ||
if err != nil { | ||
return | ||
} | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
w.win.MakeContextCurrent() | ||
return w, nil | ||
} | ||
|
||
// Run runs the given window and blocks until it is destroied. | ||
func (w *Win) Run() { | ||
for !w.win.ShouldClose() { | ||
mainthread.Call(func() { | ||
w.win.SwapBuffers() | ||
// This function must be called from the main thread. | ||
glfw.WaitEventsTimeout(1.0 / 30) | ||
}) | ||
} | ||
// This function must be called from the mainthread. | ||
mainthread.Call(w.win.Destroy) | ||
} | ||
|
||
// Stop stops and closes the given window. | ||
func (w *Win) Stop() { | ||
w.win.SetShouldClose(true) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"os" | ||
"runtime/trace" | ||
"time" | ||
app "x/app-naive" | ||
mainthread "x/mainthread-opt2" | ||
) | ||
|
||
func main() { | ||
mainthread.Init(fn) | ||
} | ||
|
||
func fn() { | ||
d := parseArgs() | ||
|
||
err := app.Init() | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer app.Terminate() | ||
w, err := app.NewWindow() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
done := make(chan struct{}, 2) | ||
go func() { | ||
f, _ := os.Create(*traceF) | ||
defer f.Close() | ||
trace.Start(f) | ||
defer trace.Stop() | ||
time.Sleep(d) | ||
w.Stop() | ||
}() | ||
go func() { | ||
w.Run() | ||
done <- struct{}{} | ||
}() | ||
<-done | ||
} | ||
|
||
var ( | ||
run *bool | ||
traceF *string | ||
traceT *string | ||
) | ||
|
||
func parseArgs() time.Duration { | ||
run = flag.Bool("run", false, "start test") | ||
traceF = flag.String("trace", "trace.out", "trace file, default: trace.out") | ||
traceT = flag.String("d", "2s", "trace duration, default: 10s") | ||
flag.Usage = func() { | ||
fmt.Fprintf(os.Stderr, `usage: go run main.go -run [-trace FILENAME -d DURATION] | ||
options: | ||
`) | ||
flag.PrintDefaults() | ||
} | ||
flag.Parse() | ||
if !*run { | ||
flag.Usage() | ||
os.Exit(2) | ||
} | ||
|
||
d, err := time.ParseDuration(*traceT) | ||
if err != nil { | ||
flag.Usage() | ||
os.Exit(2) | ||
} | ||
return d | ||
} |
25 changes: 25 additions & 0 deletions
25
content/assets/zero-alloc-call-sched/mainthread-opt1/bench-2021-01-25-21:02:29.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
goos: darwin | ||
goarch: arm64 | ||
pkg: x/mainthread-opt1 | ||
BenchmarkDirectCall-8 1000000000 0.9476 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9479 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9567 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9528 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9468 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9480 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9538 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9506 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9607 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9489 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 2752809 439.6 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2750701 438.7 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2725908 440.3 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2723350 439.4 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2754843 439.0 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2733372 446.4 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2738767 440.6 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2741732 439.8 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2748228 439.6 ns/op 24 B/op 1 allocs/op | ||
BenchmarkMainThreadCall-8 2717796 439.7 ns/op 24 B/op 1 allocs/op | ||
PASS | ||
ok x/mainthread-opt1 28.462s |
57 changes: 57 additions & 0 deletions
57
content/assets/zero-alloc-call-sched/mainthread-opt1/mainthread.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package mainthread | ||
|
||
import ( | ||
"runtime" | ||
"sync" | ||
) | ||
|
||
func init() { | ||
runtime.LockOSThread() | ||
} | ||
|
||
var ( | ||
funcQ = make(chan func(), runtime.GOMAXPROCS(0)) | ||
donePool = sync.Pool{New: func() interface{} { | ||
return make(chan struct{}) | ||
}} | ||
) | ||
|
||
// Init initializes the functionality of running arbitrary subsequent | ||
// functions be called on the main system thread. | ||
// | ||
// Init must be called in the main.main function. | ||
func Init(main func()) { | ||
done := donePool.Get().(chan struct{}) | ||
defer donePool.Put(done) | ||
|
||
go func() { | ||
main() | ||
done <- struct{}{} | ||
}() | ||
|
||
for { | ||
select { | ||
case f := <-funcQ: | ||
f() | ||
case <-done: | ||
return | ||
} | ||
} | ||
} | ||
|
||
// Call calls f on the main thread and blocks until f finishes. | ||
func Call(f func()) { | ||
done := donePool.Get().(chan struct{}) | ||
defer donePool.Put(done) | ||
|
||
funcQ <- func() { | ||
f() | ||
done <- struct{}{} | ||
} | ||
<-done | ||
} |
31 changes: 31 additions & 0 deletions
31
content/assets/zero-alloc-call-sched/mainthread-opt1/mainthread_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package mainthread_test | ||
|
||
import ( | ||
"testing" | ||
mainthread "x/mainthread-opt1" | ||
) | ||
|
||
var f = func() {} | ||
|
||
func BenchmarkDirectCall(b *testing.B) { | ||
b.ReportAllocs() | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
f() | ||
} | ||
} | ||
|
||
func BenchmarkMainThreadCall(b *testing.B) { | ||
mainthread.Init(func() { | ||
b.ReportAllocs() | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
mainthread.Call(f) | ||
} | ||
}) | ||
} |
25 changes: 25 additions & 0 deletions
25
content/assets/zero-alloc-call-sched/mainthread-opt2/bench-2021-01-25-21:08:53.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
goos: darwin | ||
goarch: arm64 | ||
pkg: x/mainthread-opt2 | ||
BenchmarkDirectCall-8 1000000000 0.9449 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9478 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9559 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9471 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9576 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9493 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9468 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9581 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9493 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDirectCall-8 1000000000 0.9480 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3299989 364.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3277143 365.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3275292 371.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3293971 366.1 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3299977 364.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3024205 367.1 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3294015 375.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3288907 364.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3285415 366.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMainThreadCall-8 3081945 368.7 ns/op 0 B/op 0 allocs/op | ||
PASS | ||
ok x/mainthread-opt2 26.493s |
60 changes: 60 additions & 0 deletions
60
content/assets/zero-alloc-call-sched/mainthread-opt2/mainthread.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package mainthread | ||
|
||
import ( | ||
"runtime" | ||
"sync" | ||
) | ||
|
||
func init() { | ||
runtime.LockOSThread() | ||
} | ||
|
||
var ( | ||
funcQ = make(chan funcdata, runtime.GOMAXPROCS(0)) | ||
donePool = sync.Pool{New: func() interface{} { | ||
return make(chan struct{}) | ||
}} | ||
) | ||
|
||
type funcdata struct { | ||
fn func() | ||
done chan struct{} | ||
} | ||
|
||
// Init initializes the functionality of running arbitrary subsequent | ||
// functions be called on the main system thread. | ||
// | ||
// Init must be called in the main.main function. | ||
func Init(main func()) { | ||
done := donePool.Get().(chan struct{}) | ||
defer donePool.Put(done) | ||
|
||
go func() { | ||
main() | ||
done <- struct{}{} | ||
}() | ||
|
||
for { | ||
select { | ||
case fdata := <-funcQ: | ||
fdata.fn() | ||
fdata.done <- struct{}{} | ||
case <-done: | ||
return | ||
} | ||
} | ||
} | ||
|
||
// Call calls f on the main thread and blocks until f finishes. | ||
func Call(f func()) { | ||
done := donePool.Get().(chan struct{}) | ||
defer donePool.Put(done) | ||
|
||
funcQ <- funcdata{fn: f, done: done} | ||
<-done | ||
} |
31 changes: 31 additions & 0 deletions
31
content/assets/zero-alloc-call-sched/mainthread-opt2/mainthread_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) 2021 The golang.design Initiative Authors. | ||
// All rights reserved. | ||
// | ||
// The code below is produced by Changkun Ou <[email protected]>. | ||
|
||
package mainthread_test | ||
|
||
import ( | ||
"testing" | ||
mainthread "x/mainthread-opt2" | ||
) | ||
|
||
var f = func() {} | ||
|
||
func BenchmarkDirectCall(b *testing.B) { | ||
b.ReportAllocs() | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
f() | ||
} | ||
} | ||
|
||
func BenchmarkMainThreadCall(b *testing.B) { | ||
mainthread.Init(func() { | ||
b.ReportAllocs() | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
mainthread.Call(f) | ||
} | ||
}) | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.