code: func (sc *StatementContext) CopTasksDetails() *CopTasksDetails {
  	sc.mu.Lock()
  	defer sc.mu.Unlock()
  	n := len(sc.mu.allExecDetails)
  	d := &CopTasksDetails{NumCopTasks: n}
  	if n == 0 {
  		return d
  	}
  	d.AvgProcessTime = sc.mu.execDetails.ProcessTime / time.Duration(n)
  	d.AvgWaitTime = sc.mu.execDetails.WaitTime / time.Duration(n)
  
  	sort.Slice(sc.mu.allExecDetails, func(i, j int) bool {
  		return sc.mu.allExecDetails[i].ProcessTime < sc.mu.allExecDetails[j].ProcessTime
  	})
  	d.P90ProcessTime = sc.mu.allExecDetails[n*9/10].ProcessTime
  	d.MaxProcessTime = sc.mu.allExecDetails[n-1].ProcessTime
  	d.MaxProcessAddress = sc.mu.allExecDetails[n-1].CalleeAddress
  
  	sort.Slice(sc.mu.allExecDetails, func(i, j int) bool {
  		return sc.mu.allExecDetails[i].WaitTime < sc.mu.allExecDetails[j].WaitTime
  	})
  	d.P90WaitTime = sc.mu.allExecDetails[n*9/10].WaitTime
  	d.MaxWaitTime = sc.mu.allExecDetails[n-1].WaitTime
  	d.MaxWaitAddress = sc.mu.allExecDetails[n-1].CalleeAddress
  	return d
  }
docs: // CopTasksDetails returns some useful information of cop-tasks during execution.