timingwheel

package module
v0.0.0-...-910852f Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2020 License: MIT Imports: 7 Imported by: 0

README

timingwheel

分层时间轮的Golang实现, 基于RussellLuo/timingwheel 改造

Installation

$ go get -u github.com/golearnku/timingwheel

Design

timingwheel is ported from Kafka's purgatory, which is designed based on Hierarchical Timing Wheels.

中文博客:层级时间轮的 Golang 实现

Documentation

For usage and examples see the Godoc.

AfterFunc

package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

func main()  {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	t := tw.AfterFunc("100",time.Second, func() {
		fmt.Println("The timer fires")
	})

	<-time.After(900 * time.Millisecond)
	// Stop the timer before it fires
	t.Stop()
}
package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

func main()  {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	exitC := make(chan time.Time, 1)
	tw.AfterFunc("100",time.Second * 2, func() {
		fmt.Println("The timer fires")
		exitC <- time.Now().UTC()
	})

	<-exitC
}

ScheduleFunc

package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

type EveryScheduler struct {
	Id       int
	Interval time.Duration
}

func (s *EveryScheduler) Next(prev time.Time) time.Time {
	return prev.Add(s.Interval)
}

func main() {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	i := 0

	tw.ScheduleFunc("100", &EveryScheduler{1, time.Second * 2}, func() {
		i++
		fmt.Println("The timer fires")
		fmt.Println(i)
		//exitC <- time.Now().UTC()
	})

	for {
		select {
		case <-time.After(time.Millisecond * 300):
			i += 100
		case <-time.After(time.Second * 5):
			tw.Remove("100")
			return
		}
	}
}

Benchmark

$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/golearnku/timingwheel
BenchmarkTimingWheel_StartStop/N-1m-8         	 2502430	       459 ns/op	     134 B/op	       4 allocs/op
BenchmarkTimingWheel_StartStop/N-5m-8         	 2732517	       522 ns/op	     147 B/op	       4 allocs/op
BenchmarkTimingWheel_StartStop/N-10m-8        	 2098280	       493 ns/op	      70 B/op	       1 allocs/op
BenchmarkStandardTimer_StartStop/N-1m-8       	 7412431	       232 ns/op	      81 B/op	       1 allocs/op
BenchmarkStandardTimer_StartStop/N-5m-8       	 4012328	       290 ns/op	      84 B/op	       1 allocs/op
BenchmarkStandardTimer_StartStop/N-10m-8      	 5873055	       280 ns/op	      86 B/op	       1 allocs/op
PASS
ok  	github.com/golearnku/timingwheel	80.234s

License

MIT

Documentation

Overview

Example (ScheduleTimer)
/**
* Author: JeffreyBool
* Date: 2020/4/22
* Time: 20:24
* Software: GoLand
 */

package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

type EveryScheduler struct {
	Interval time.Duration
}

func (s *EveryScheduler) Next(prev time.Time) time.Time {
	return prev.Add(s.Interval)
}

func main() {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	exitC := make(chan time.Time)
	t := tw.ScheduleFunc("100", &EveryScheduler{time.Second}, func() {
		fmt.Println("The timer fires")
		exitC <- time.Now().UTC()
	})

	<-exitC
	<-exitC

	// We need to stop the timer since it will be restarted again and again.
	for !t.Stop() {
	}

}
Output:

The timer fires
The timer fires
Example (StartTimer)
package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

func main() {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	exitC := make(chan time.Time, 1)
	tw.AfterFunc("102", time.Second, func() {
		fmt.Println("The timer fires")
		exitC <- time.Now().UTC()
	})

	<-exitC

}
Output:

The timer fires
Example (StopTimer)
package main

import (
	"fmt"
	"time"

	"github.com/golearnku/timingwheel"
)

func main() {
	tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
	tw.Start()
	defer tw.Stop()

	t := tw.AfterFunc("105", time.Second, func() {
		fmt.Println("The timer fires")
	})

	<-time.After(900 * time.Millisecond)
	// Stop the timer before it fires
	t.Stop()

}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Scheduler

type Scheduler interface {
	// Next returns the next execution time after the given (previous) time.
	// It will return a zero time if no next time is scheduled.
	//
	// All times must be UTC.
	Next(time.Time) time.Time
}

Scheduler determines the execution plan of a task.

type Timer

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

Timer represents a single event. When the Timer expires, the given task will be executed.

func (*Timer) Stop

func (t *Timer) Stop() bool

Stop prevents the Timer from firing. It returns true if the call stops the timer, false if the timer has already expired or been stopped.

If the timer t has already expired and the t.task has been started in its own goroutine; Stop does not wait for t.task to complete before returning. If the caller needs to know whether t.task is completed, it must coordinate with t.task explicitly.

type TimingWheel

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

TimingWheel is an implementation of Hierarchical Timing Wheels.

func NewTimingWheel

func NewTimingWheel(tick time.Duration, wheelSize int64) *TimingWheel

NewTimingWheel creates an instance of TimingWheel with the given tick and wheelSize.

func (*TimingWheel) AfterFunc

func (tw *TimingWheel) AfterFunc(key string, d time.Duration, f func()) *Timer

AfterFunc waits for the duration to elapse and then calls f in its own goroutine. It returns a Timer that can be used to cancel the call using its Stop method.

func (*TimingWheel) Remove

func (tw *TimingWheel) Remove(key string)

Remove.

func (*TimingWheel) ScheduleFunc

func (tw *TimingWheel) ScheduleFunc(key string, s Scheduler, f func()) (t *Timer)

ScheduleFunc calls f (in its own goroutine) according to the execution plan scheduled by s. It returns a Timer that can be used to cancel the call using its Stop method.

If the caller want to terminate the execution plan halfway, it must stop the timer and ensure that the timer is stopped actually, since in the current implementation, there is a gap between the expiring and the restarting of the timer. The wait time for ensuring is short since the gap is very small.

Internally, ScheduleFunc will ask the first execution time (by calling s.Next()) initially, and create a timer if the execution time is non-zero. Afterwards, it will ask the next execution time each time f is about to be executed, and f will be called at the next execution time if the time is non-zero.

func (*TimingWheel) Start

func (tw *TimingWheel) Start()

Start starts the current timing wheel.

func (*TimingWheel) Stop

func (tw *TimingWheel) Stop()

Stop stops the current timing wheel.

If there is any timer's task being running in its own goroutine, Stop does not wait for the task to complete before returning. If the caller needs to know whether the task is completed, it must coordinate with the task explicitly.

Jump to

Keyboard shortcuts

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