mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
新增性能分析器
This commit is contained in:
@@ -69,8 +69,8 @@ func (slf *Cluster) Init(currentNodeId int) error{
|
|||||||
rpcinfo.nodeinfo = nodeinfo
|
rpcinfo.nodeinfo = nodeinfo
|
||||||
rpcinfo.client = &rpc.Client{}
|
rpcinfo.client = &rpc.Client{}
|
||||||
if nodeinfo.NodeId == currentNodeId {
|
if nodeinfo.NodeId == currentNodeId {
|
||||||
rpcinfo.client.Connect("localhost")
|
//rpcinfo.client.Connect("localhost")
|
||||||
//rpcinfo.client.Connect(nodeinfo.ListenAddr)
|
rpcinfo.client.Connect(nodeinfo.ListenAddr)
|
||||||
}else{
|
}else{
|
||||||
rpcinfo.client.Connect(nodeinfo.ListenAddr)
|
rpcinfo.client.Connect(nodeinfo.ListenAddr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ func (slf *Module4) OnRelease() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (slf *TestServiceCall) OnInit() error {
|
func (slf *TestServiceCall) OnInit() error {
|
||||||
|
slf.OpenProfiler()
|
||||||
|
|
||||||
//slf.AfterFunc(time.Second*1,slf.Run)
|
//slf.AfterFunc(time.Second*1,slf.Run)
|
||||||
slf.AfterFunc(time.Second*1,slf.Test)
|
slf.AfterFunc(time.Second*1,slf.Test)
|
||||||
moduleid1,_ = slf.AddModule(&Module1{})
|
moduleid1,_ = slf.AddModule(&Module1{})
|
||||||
@@ -182,6 +184,7 @@ func (slf *TestService1) RPC_Test(a *Param,b *Param) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (slf *TestService1) OnInit() error {
|
func (slf *TestService1) OnInit() error {
|
||||||
|
slf.OpenProfiler()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -213,6 +216,7 @@ func (slf *TestServiceCall) TestDB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (slf *TestService2) OnInit() error {
|
func (slf *TestService2) OnInit() error {
|
||||||
|
slf.OpenProfiler()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +225,7 @@ func main(){
|
|||||||
gateService := &GateService.GateService{}
|
gateService := &GateService.GateService{}
|
||||||
tcpService.SetEventReciver(gateService)
|
tcpService.SetEventReciver(gateService)
|
||||||
node.Setup(tcpService,gateService)
|
node.Setup(tcpService,gateService)
|
||||||
|
node.OpenProfilerReport(time.Second*10)
|
||||||
node.Start()
|
node.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
node/node.go
13
node/node.go
@@ -5,18 +5,21 @@ import (
|
|||||||
"github.com/duanhf2012/origin/cluster"
|
"github.com/duanhf2012/origin/cluster"
|
||||||
"github.com/duanhf2012/origin/console"
|
"github.com/duanhf2012/origin/console"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"github.com/duanhf2012/origin/profiler"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/service"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var closeSig chan bool
|
var closeSig chan bool
|
||||||
var sigs chan os.Signal
|
var sigs chan os.Signal
|
||||||
var nodeId int
|
var nodeId int
|
||||||
var preSetupService []service.IService //预安装
|
var preSetupService []service.IService //预安装
|
||||||
|
var profilerInterval time.Duration
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
closeSig = make(chan bool,1)
|
closeSig = make(chan bool,1)
|
||||||
@@ -111,12 +114,18 @@ func startNode(paramNodeId interface{}) error {
|
|||||||
service.Start()
|
service.Start()
|
||||||
writeProcessPid()
|
writeProcessPid()
|
||||||
bRun := true
|
bRun := true
|
||||||
|
var pProfilerTicker *time.Ticker = &time.Ticker{}
|
||||||
|
if profilerInterval>0 {
|
||||||
|
pProfilerTicker = time.NewTicker(profilerInterval)
|
||||||
|
}
|
||||||
|
|
||||||
for bRun {
|
for bRun {
|
||||||
select {
|
select {
|
||||||
case <-sigs:
|
case <-sigs:
|
||||||
log.Debug("receipt stop signal.")
|
log.Debug("receipt stop signal.")
|
||||||
bRun = false
|
bRun = false
|
||||||
|
case <- pProfilerTicker.C:
|
||||||
|
profiler.Report()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,3 +156,7 @@ func SetSysLog(strLevel string, pathname string, flag int){
|
|||||||
logs,_:= log.New(strLevel,pathname,flag)
|
logs,_:= log.New(strLevel,pathname,flag)
|
||||||
log.Export(logs)
|
log.Export(logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenProfilerReport(interval time.Duration){
|
||||||
|
profilerInterval = interval
|
||||||
|
}
|
||||||
|
|||||||
180
profiler/profiler.go
Normal file
180
profiler/profiler.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package profiler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//最大超长时间,一般可以认为是死锁或者死循环,或者极差的性能问题
|
||||||
|
var Default_MaxOverTime time.Duration = 5*time.Second
|
||||||
|
//超过该时间将会监控报告
|
||||||
|
var Default_OverTime time.Duration = 10*time.Millisecond
|
||||||
|
var Default_MaxRecordNum int = 100 //最大记录条数
|
||||||
|
|
||||||
|
type Element struct {
|
||||||
|
tagName string
|
||||||
|
pushTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecordType int
|
||||||
|
const (
|
||||||
|
MaxOverTime_Type = 1
|
||||||
|
OverTime_Type =2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
RType RecordType
|
||||||
|
CostTime time.Duration
|
||||||
|
RecordName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Profiler struct {
|
||||||
|
stack *list.List //Element
|
||||||
|
stackLocker sync.RWMutex
|
||||||
|
|
||||||
|
record *list.List //Record
|
||||||
|
|
||||||
|
callNum int //调用次数
|
||||||
|
totalCostTime time.Duration //总消费时间长
|
||||||
|
|
||||||
|
maxOverTime time.Duration
|
||||||
|
overTime time.Duration
|
||||||
|
maxRecordNum int
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapProfiler map[string]*Profiler
|
||||||
|
|
||||||
|
func init(){
|
||||||
|
mapProfiler = map[string]*Profiler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegProfiler(profilerName string) *Profiler {
|
||||||
|
if _,ok :=mapProfiler[profilerName];ok==true {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pProfiler := &Profiler{stack:list.New(),record:list.New(),maxOverTime:Default_MaxOverTime,overTime:Default_OverTime}
|
||||||
|
mapProfiler[profilerName] =pProfiler
|
||||||
|
return pProfiler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Profiler) Push(tag string) {
|
||||||
|
slf.stackLocker.Lock()
|
||||||
|
slf.stack.PushBack(&Element{tagName:tag,pushTime:time.Now()})
|
||||||
|
slf.stackLocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Profiler) pushRecordLog(record *Record){
|
||||||
|
if slf.record.Len()>=Default_MaxRecordNum{
|
||||||
|
front := slf.stack.Front()
|
||||||
|
if front!=nil {
|
||||||
|
slf.stack.Remove(front)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slf.record.PushBack(record)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Profiler) check(pElem *Element) (*Record,time.Duration) {
|
||||||
|
if pElem == nil {
|
||||||
|
return nil,0
|
||||||
|
}
|
||||||
|
|
||||||
|
subTm := time.Now().Sub(pElem.pushTime)
|
||||||
|
if subTm < slf.overTime {
|
||||||
|
return nil,subTm
|
||||||
|
}
|
||||||
|
|
||||||
|
record := Record{
|
||||||
|
RType: OverTime_Type,
|
||||||
|
CostTime: subTm,
|
||||||
|
RecordName: pElem.tagName,
|
||||||
|
}
|
||||||
|
|
||||||
|
if subTm>slf.maxOverTime {
|
||||||
|
record.RType = MaxOverTime_Type
|
||||||
|
}
|
||||||
|
|
||||||
|
return &record,subTm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Profiler) Pop() {
|
||||||
|
slf.stackLocker.Lock()
|
||||||
|
|
||||||
|
front := slf.stack.Front()
|
||||||
|
if front!=nil && front.Value!=nil {
|
||||||
|
pElement := front.Value.(*Element)
|
||||||
|
pElem,subTm := slf.check(pElement)
|
||||||
|
slf.callNum+=1
|
||||||
|
slf.totalCostTime += subTm
|
||||||
|
if pElem != nil {
|
||||||
|
slf.pushRecordLog(pElem)
|
||||||
|
}
|
||||||
|
slf.stack.Remove(front)
|
||||||
|
}
|
||||||
|
|
||||||
|
slf.stackLocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReportFunType func(name string,callNum int,costTime time.Duration,record *list.List)
|
||||||
|
|
||||||
|
var reportFunc ReportFunType =DefaultReportFunction
|
||||||
|
|
||||||
|
func SetReportFunction(reportFun ReportFunType) {
|
||||||
|
reportFunc = reportFun
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultReportFunction(name string,callNum int,costTime time.Duration,record *list.List){
|
||||||
|
if record.Len()<=0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var strReport string
|
||||||
|
strReport = "Profiler report tag "+name+":\n"
|
||||||
|
strReport += fmt.Sprintf("process count %d,take time %d Milliseconds,average %d Milliseconds/per.\n",callNum,costTime.Milliseconds(),costTime.Milliseconds()/int64(callNum))
|
||||||
|
elem := record.Front()
|
||||||
|
var strTypes string
|
||||||
|
for elem!=nil {
|
||||||
|
pRecord := elem.Value.(*Record)
|
||||||
|
if pRecord.RType == MaxOverTime_Type {
|
||||||
|
strTypes = "very slow process"
|
||||||
|
}else{
|
||||||
|
strTypes = "slow process"
|
||||||
|
}
|
||||||
|
|
||||||
|
strReport += fmt.Sprintf("%s:%s is take %d Milliseconds\n",strTypes,pRecord.RecordName,pRecord.CostTime.Milliseconds())
|
||||||
|
elem = elem.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Release(strReport)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Report() {
|
||||||
|
var record *list.List
|
||||||
|
for name,prof := range mapProfiler{
|
||||||
|
prof.stackLocker.RLock()
|
||||||
|
if prof.record.Len() == 0 {
|
||||||
|
prof.stackLocker.RUnlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//取栈的队首,是否存在异常MaxOverTime数据
|
||||||
|
pElem := prof.stack.Front()
|
||||||
|
if pElem!=nil && pElem.Value!=nil{
|
||||||
|
pRecord,_ := prof.check(pElem.Value.(*Element))
|
||||||
|
if pRecord!=nil {
|
||||||
|
prof.pushRecordLog(pRecord)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
record = prof.record
|
||||||
|
prof.record = list.New()
|
||||||
|
prof.stackLocker.RUnlock()
|
||||||
|
|
||||||
|
DefaultReportFunction(name,prof.callNum,prof.totalCostTime,record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ func (slf *Client) AsycGo(rpcHandler IRpcHandler,serviceMethod string,callback r
|
|||||||
call.Reply = replyParam
|
call.Reply = replyParam
|
||||||
call.callback = &callback
|
call.callback = &callback
|
||||||
call.rpcHandler = rpcHandler
|
call.rpcHandler = rpcHandler
|
||||||
|
call.ServiceMethod = serviceMethod
|
||||||
|
|
||||||
request := &RpcRequest{}
|
request := &RpcRequest{}
|
||||||
request.NoReply = false
|
request.NoReply = false
|
||||||
@@ -95,7 +96,7 @@ func (slf *Client) Go(noReply bool,serviceMethod string, args interface{},reply
|
|||||||
call := new(Call)
|
call := new(Call)
|
||||||
call.done = make(chan *Call,1)
|
call.done = make(chan *Call,1)
|
||||||
call.Reply = reply
|
call.Reply = reply
|
||||||
|
call.ServiceMethod = serviceMethod
|
||||||
request := &RpcRequest{}
|
request := &RpcRequest{}
|
||||||
request.NoReply = noReply
|
request.NoReply = noReply
|
||||||
call.Arg = args
|
call.Arg = args
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ var LittleEndian bool
|
|||||||
|
|
||||||
type Call struct {
|
type Call struct {
|
||||||
Seq uint64
|
Seq uint64
|
||||||
//ServiceMethod string
|
ServiceMethod string
|
||||||
Arg interface{}
|
Arg interface{}
|
||||||
Reply interface{}
|
Reply interface{}
|
||||||
Respone *RpcResponse
|
Respone *RpcResponse
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/util/timer"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -170,7 +171,8 @@ func (slf *Module) AfterFunc(d time.Duration, cb func()) *timer.Timer {
|
|||||||
slf.mapActiveTimer =map[*timer.Timer]interface{}{}
|
slf.mapActiveTimer =map[*timer.Timer]interface{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
tm := slf.dispatcher.AfterFuncEx(d,func(t *timer.Timer){
|
funName := runtime.FuncForPC(reflect.ValueOf(cb).Pointer()).Name()
|
||||||
|
tm := slf.dispatcher.AfterFuncEx(funName,d,func(t *timer.Timer){
|
||||||
cb()
|
cb()
|
||||||
delete(slf.mapActiveTimer,t)
|
delete(slf.mapActiveTimer,t)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/event"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"github.com/duanhf2012/origin/profiler"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/rpc"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/util/timer"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -27,6 +28,8 @@ type IService interface {
|
|||||||
Start()
|
Start()
|
||||||
GetRpcHandler() rpc.IRpcHandler
|
GetRpcHandler() rpc.IRpcHandler
|
||||||
GetServiceCfg()interface{}
|
GetServiceCfg()interface{}
|
||||||
|
OpenProfiler()
|
||||||
|
GetProfiler() *profiler.Profiler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +44,7 @@ type Service struct {
|
|||||||
gorouterNum int32
|
gorouterNum int32
|
||||||
startStatus bool
|
startStatus bool
|
||||||
|
|
||||||
|
profiler *profiler.Profiler //性能分析器
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *Service) OnSetup(iservice IService){
|
func (slf *Service) OnSetup(iservice IService){
|
||||||
@@ -49,8 +53,14 @@ func (slf *Service) OnSetup(iservice IService){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *Service) Init(iservice IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) {
|
func (slf *Service) OpenProfiler(){
|
||||||
|
slf.profiler = profiler.RegProfiler(slf.GetName())
|
||||||
|
if slf.profiler==nil {
|
||||||
|
log.Fatal("rofiler.RegProfiler %s fail.",slf.GetName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Service) Init(iservice IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) {
|
||||||
slf.dispatcher =timer.NewDispatcher(timerDispatcherLen)
|
slf.dispatcher =timer.NewDispatcher(timerDispatcherLen)
|
||||||
slf.this = iservice
|
slf.this = iservice
|
||||||
slf.InitRpcHandler(iservice.(rpc.IRpcHandler),getClientFun,getServerFun)
|
slf.InitRpcHandler(iservice.(rpc.IRpcHandler),getClientFun,getServerFun)
|
||||||
@@ -96,13 +106,38 @@ func (slf *Service) Run() {
|
|||||||
case <- closeSig:
|
case <- closeSig:
|
||||||
bStop = true
|
bStop = true
|
||||||
case rpcRequest :=<- rpcRequestChan:
|
case rpcRequest :=<- rpcRequestChan:
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Push("Req_"+rpcRequest.ServiceMethod)
|
||||||
|
}
|
||||||
|
|
||||||
slf.GetRpcHandler().HandlerRpcRequest(rpcRequest)
|
slf.GetRpcHandler().HandlerRpcRequest(rpcRequest)
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Pop()
|
||||||
|
}
|
||||||
case rpcResponeCB := <- rpcResponeCallBack:
|
case rpcResponeCB := <- rpcResponeCallBack:
|
||||||
slf.GetRpcHandler().HandlerRpcResponeCB(rpcResponeCB)
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Push("Res_" + rpcResponeCB.ServiceMethod)
|
||||||
|
}
|
||||||
|
slf.GetRpcHandler().HandlerRpcResponeCB(rpcResponeCB)
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Pop()
|
||||||
|
}
|
||||||
case ev := <- eventChan:
|
case ev := <- eventChan:
|
||||||
slf.EventHandler(slf.this.(event.IEventProcessor),ev)
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Push(fmt.Sprintf("Event_%d", int(ev.Type)))
|
||||||
|
}
|
||||||
|
slf.EventHandler(slf.this.(event.IEventProcessor),ev)
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Pop()
|
||||||
|
}
|
||||||
case t := <- slf.dispatcher.ChanTimer:
|
case t := <- slf.dispatcher.ChanTimer:
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Push(fmt.Sprintf("Timer_%s", t.GetFunctionName()))
|
||||||
|
}
|
||||||
t.Cb()
|
t.Cb()
|
||||||
|
if slf.profiler!=nil {
|
||||||
|
slf.profiler.Pop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if bStop == true {
|
if bStop == true {
|
||||||
@@ -114,7 +149,6 @@ func (slf *Service) Run() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *Service) GetName() string{
|
func (slf *Service) GetName() string{
|
||||||
@@ -149,3 +183,9 @@ func (slf *Service) Wait(){
|
|||||||
func (slf *Service) GetServiceCfg()interface{}{
|
func (slf *Service) GetServiceCfg()interface{}{
|
||||||
return slf.serviceCfg
|
return slf.serviceCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (slf *Service) GetProfiler() *profiler.Profiler{
|
||||||
|
return slf.profiler
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package timer
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -23,6 +24,7 @@ type Timer struct {
|
|||||||
t *time.Timer
|
t *time.Timer
|
||||||
cb func()
|
cb func()
|
||||||
cbex func(*Timer)
|
cbex func(*Timer)
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) Stop() {
|
func (t *Timer) Stop() {
|
||||||
@@ -30,6 +32,10 @@ func (t *Timer) Stop() {
|
|||||||
t.cb = nil
|
t.cb = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Timer) GetFunctionName() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Timer) Cb() {
|
func (t *Timer) Cb() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -51,15 +57,20 @@ func (t *Timer) Cb() {
|
|||||||
func (disp *Dispatcher) AfterFunc(d time.Duration, cb func()) *Timer {
|
func (disp *Dispatcher) AfterFunc(d time.Duration, cb func()) *Timer {
|
||||||
t := new(Timer)
|
t := new(Timer)
|
||||||
t.cb = cb
|
t.cb = cb
|
||||||
|
t.name = reflect.TypeOf(cb).Name()
|
||||||
|
|
||||||
t.t = time.AfterFunc(d, func() {
|
t.t = time.AfterFunc(d, func() {
|
||||||
disp.ChanTimer <- t
|
disp.ChanTimer <- t
|
||||||
})
|
})
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (disp *Dispatcher) AfterFuncEx(d time.Duration, cbex func(timer *Timer)) *Timer {
|
func (disp *Dispatcher) AfterFuncEx(funName string,d time.Duration, cbex func(timer *Timer)) *Timer {
|
||||||
t := new(Timer)
|
t := new(Timer)
|
||||||
t.cbex = cbex
|
t.cbex = cbex
|
||||||
|
t.name = funName//reflect.TypeOf(cbex).Name()
|
||||||
|
//t.name = runtime.FuncForPC(reflect.ValueOf(cbex).Pointer()).Name()
|
||||||
t.t = time.AfterFunc(d, func() {
|
t.t = time.AfterFunc(d, func() {
|
||||||
disp.ChanTimer <- t
|
disp.ChanTimer <- t
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user