sched

package module
v0.0.0-...-025ce6f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2023 License: Apache-2.0 Imports: 9 Imported by: 0

README

Why?

Go runtime has no priority-based scheduling (barely FIFO), the scheduling latency is a big problem for some real-time task.

See a blog post (Chinese) https://www.zenlife.tk/go-manual-scheduler.md

Prerequisites

Need to patch the Go https://github.com/golang/go/pull/51347

Watch the Demo

asciicast

Run it yourself

Run the demo/main.go.

cd demo
go build -tags sched
GOMAXPROCS=9 ./demo
# feel free to tune the parameters below if you like
# you may need to change the `GOMAXPROCS=9` and `-c 10` with machine's CPU < 10 to see the effect.

# cmd 1
while true; do sleep 1;ab -s10000000 -c 10 -n 60 http://127.0.0.1:8080/delay1ms; done

# cmd 2
while true; do sleep 1;ab -s10000000 -c 10 -n 60 http://127.0.0.1:8080/checksumWithoutScheduling; done

# cmd 3
while true; do sleep 1;ab -s10000000 -c 10 -n 60 http://127.0.0.1:8080/checksumWithScheduling; done

# cmd 4
while true; do sleep 1;ab -s10000000 -c 10 -n 60 http://127.0.0.1:8080/checksumSmallTaskWithScheduling; done

Step 1: Killall already existing cmd x, then run the cmd 1.

Step 2: Killall already existing cmd x, then run the cmd 1 and cmd 2 simultaneously.

Step 3: Killall already existing cmd x, then run the cmd 1 and cmd 3 simultaneously.

Step 4: Killall already existing cmd x, then run the cmd 1, cmd 3 and cmd 4 simultaneously.

Please watch the latency which cmd 1 and cmd 4 yields carefully at every step and then you would catch the difference :-D

The point is, with scheduling, the CPU dense task would not affect the latency of the others

Acknowledgments

  • Inspired by cpuworker with better API and improving usability.
  • Inspired by cockroachdb's awesome blog

Thanks to their pioneering work, I am convinced that manually scheduling over the Go runtime is possible.

Documentation

Index

Constants

View Source
const (
	Stable feedbackPhase = iota
	Idle
	Busy
	GC
)

Variables

View Source
var Debug = "schedTest"

Functions

func CheckPoint

func CheckPoint(ctx context.Context)

CheckPoint should be called manually to check whether the goroutine (task group) run out of its time slice. If so, the goroutine is yielded for scheduling. The scheduler will wake up it according to the scheduling algorithm.

func Disable

func Disable()

Disable is provided for debugging.

func Enable

func Enable()

Enable is provided for debugging.

func Scheduler

func Scheduler(opts ...Option)

Scheduler should run in a separate goroutine, and typically be called at the beginning of the process.

func WithSchedInfo

func WithSchedInfo(ctx context.Context) context.Context

WithSchedInfo returns a new context with scheduling information attached. When creating running a new goroutine from a task group, use this:

go f(sched.WithSchedInfo(ctx))

Types

type Option

type Option func(*config)

Option overrides the default scheduling parameters.

func CapacityOption

func CapacityOption(v time.Duration) Option

CapacityOption controls the token bucket capacity, which controls the burst behaviour. Default value is GOMAXPROCS * time slice, DONOT SET IT TO 0

func LoadOption

func LoadOption(v float64) Option

LoadOption controls the `load` of the CPU usage, default to 1

func TimeSliceOption

func TimeSliceOption(v time.Duration) Option

TimeSliceOption controls the time-slice of a task group. It's default to 20ms

func WeightedOption

func WeightedOption(v bool) Option

WeightedOption make the scheduling support weighted task group, rather than regarding as all equal.

type PriorityQueue

type PriorityQueue struct {
	// contains filtered or unexported fields
}

func (*PriorityQueue) Dequeue

func (pq *PriorityQueue) Dequeue() *TaskGroup

func (*PriorityQueue) Empty

func (pq *PriorityQueue) Empty() bool

func (*PriorityQueue) Enqueue

func (pq *PriorityQueue) Enqueue(x *TaskGroup)

func (*PriorityQueue) Full

func (pq *PriorityQueue) Full() bool

func (*PriorityQueue) Len

func (pq *PriorityQueue) Len() int

func (*PriorityQueue) Less

func (pq *PriorityQueue) Less(i, j int) bool

func (*PriorityQueue) Pop

func (pq *PriorityQueue) Pop() interface{}

func (*PriorityQueue) Push

func (pq *PriorityQueue) Push(x interface{})

func (*PriorityQueue) Swap

func (pq *PriorityQueue) Swap(i, j int)

type TaskContext

type TaskContext struct {
	// contains filtered or unexported fields
}

type TaskGroup

type TaskGroup struct {
	// contains filtered or unexported fields
}

func NewTaskGroup

func NewTaskGroup(ctx context.Context) (context.Context, *TaskGroup)

NewTaskGroup returns a new context with TaskGroup attached using context.WithValue. A task group is a scheduling unit consist of a group of goroutines. The necessary information for scheduling is embeded in the context.Context.

func (*TaskGroup) SetWeight

func (tg *TaskGroup) SetWeight(w float64)

SetWeight can set the weight of this task group if the scheduler is configured to weighted.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL