diff --git a/profiler/profiler.go b/profiler/profiler.go index 471abf0..7ce2a58 100644 --- a/profiler/profiler.go +++ b/profiler/profiler.go @@ -32,10 +32,17 @@ type Record struct { RecordName string } + +type Analyzer struct { + elem *list.Element + profiler *Profiler +} + + type Profiler struct { stack *list.List //Element stackLocker sync.RWMutex - + mapAnalyzer map[*list.Element]Analyzer record *list.List //Record callNum int //调用次数 @@ -62,22 +69,15 @@ func RegProfiler(profilerName string) *Profiler { return pProfiler } -func (slf *Profiler) Push(tag string) { +func (slf *Profiler) Push(tag string) *Analyzer{ slf.stackLocker.Lock() - slf.stack.PushBack(&Element{tagName:tag,pushTime:time.Now()}) - slf.stackLocker.Unlock() + defer slf.stackLocker.Unlock() + + pElem := slf.stack.PushBack(&Element{tagName:tag,pushTime:time.Now()}) + + return &Analyzer{elem:pElem,profiler:slf} } -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 { @@ -102,24 +102,33 @@ func (slf *Profiler) check(pElem *Element) (*Record,time.Duration) { return &record,subTm } -func (slf *Profiler) Pop() { - slf.stackLocker.Lock() +func (slf *Analyzer) Pop(){ + slf.profiler.stackLocker.Lock() + defer slf.profiler.stackLocker.Unlock() - back := slf.stack.Back() - if back!=nil && back.Value!=nil { - pElement := back.Value.(*Element) - pElem,subTm := slf.check(pElement) - slf.callNum+=1 - slf.totalCostTime += subTm - if pElem != nil { - slf.pushRecordLog(pElem) + pElement := slf.elem.Value.(*Element) + pElem,subTm := slf.profiler.check(pElement) + slf.profiler.callNum+=1 + slf.profiler.totalCostTime += subTm + if pElem != nil { + slf.profiler.pushRecordLog(pElem) + } + slf.profiler.stack.Remove(slf.elem) +} + +func (slf *Profiler) pushRecordLog(record *Record){ + if slf.record.Len()>=Default_MaxRecordNum{ + front := slf.stack.Front() + if front!=nil { + slf.stack.Remove(front) } - slf.stack.Remove(back) } - slf.stackLocker.Unlock() + slf.record.PushBack(record) } + + type ReportFunType func(name string,callNum int,costTime time.Duration,record *list.List) var reportFunc ReportFunType =DefaultReportFunction @@ -165,11 +174,13 @@ func Report() { //取栈顶,是否存在异常MaxOverTime数据 pElem := prof.stack.Back() - if pElem!=nil && pElem.Value!=nil{ - pRecord,_ := prof.check(pElem.Value.(*Element)) - if pRecord!=nil { - prof.pushRecordLog(pRecord) + for pElem!=nil { + pElement := pElem.Value.(*Element) + pExceptionElem,_ := prof.check(pElement) + if pExceptionElem!=nil { + prof.pushRecordLog(pExceptionElem) } + pElem = pElem.Prev() } if prof.record.Len() == 0 { diff --git a/service/service.go b/service/service.go index ae88db6..a8d2dbd 100644 --- a/service/service.go +++ b/service/service.go @@ -53,7 +53,7 @@ func (slf *Service) OnSetup(iservice IService){ } } -func (slf *Service) OpenProfiler(){ +func (slf *Service) OpenProfiler() { slf.profiler = profiler.RegProfiler(slf.GetName()) if slf.profiler==nil { log.Fatal("rofiler.RegProfiler %s fail.",slf.GetName()) @@ -75,8 +75,9 @@ func (slf *Service) Init(iservice IService,getClientFun rpc.FuncRpcClient,getSer } func (slf *Service) SetGoRouterNum(gorouterNum int32) bool { - //已经开始状态不允许修改协程数量 - if slf.startStatus == true { + //已经开始状态不允许修改协程数量,打开性能分析器不允许开多线程 + if slf.startStatus == true || slf.profiler!=nil { + log.Error("open profiler mode is not allowed to set Multi-coroutine.") return false } @@ -102,41 +103,46 @@ func (slf *Service) Run() { rpcRequestChan := slf.GetRpcRequestChan() rpcResponeCallBack := slf.GetRpcResponeChan() eventChan := slf.GetEventChan() + var analyzer *profiler.Analyzer select { case <- closeSig: bStop = true case rpcRequest :=<- rpcRequestChan: if slf.profiler!=nil { - slf.profiler.Push("Req_"+rpcRequest.ServiceMethod) + analyzer = slf.profiler.Push("Req_"+rpcRequest.ServiceMethod) } slf.GetRpcHandler().HandlerRpcRequest(rpcRequest) - if slf.profiler!=nil { - slf.profiler.Pop() + if analyzer!=nil { + analyzer.Pop() + analyzer = nil } case rpcResponeCB := <- rpcResponeCallBack: if slf.profiler!=nil { - slf.profiler.Push("Res_" + rpcResponeCB.ServiceMethod) + analyzer = slf.profiler.Push("Res_" + rpcResponeCB.ServiceMethod) } slf.GetRpcHandler().HandlerRpcResponeCB(rpcResponeCB) - if slf.profiler!=nil { - slf.profiler.Pop() + if analyzer!=nil { + analyzer.Pop() + analyzer = nil } case ev := <- eventChan: if slf.profiler!=nil { - slf.profiler.Push(fmt.Sprintf("Event_%d", int(ev.Type))) + analyzer = slf.profiler.Push(fmt.Sprintf("Event_%d", int(ev.Type))) } slf.EventHandler(slf.this.(event.IEventProcessor),ev) - if slf.profiler!=nil { - slf.profiler.Pop() + if analyzer!=nil { + analyzer.Pop() + analyzer = nil } case t := <- slf.dispatcher.ChanTimer: if slf.profiler!=nil { - slf.profiler.Push(fmt.Sprintf("Timer_%s", t.GetFunctionName())) + analyzer = slf.profiler.Push(fmt.Sprintf("Timer_%s", t.GetFunctionName())) } t.Cb() - if slf.profiler!=nil { - slf.profiler.Pop() + if analyzer!=nil { + analyzer.Pop() + analyzer = nil } }