1// Copyright 2018 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package tracer 16 17import ( 18 "android/soong/ui/status" 19 "time" 20) 21 22func (t *tracerImpl) StatusTracer() status.StatusOutput { 23 return &statusOutput{ 24 tracer: t, 25 26 running: map[*status.Action]actionStatus{}, 27 } 28} 29 30type actionStatus struct { 31 cpu int 32 start time.Time 33} 34 35type statusOutput struct { 36 tracer *tracerImpl 37 38 cpus []bool 39 running map[*status.Action]actionStatus 40} 41 42func (s *statusOutput) StartAction(action *status.Action, counts status.Counts) { 43 cpu := -1 44 for i, busy := range s.cpus { 45 if !busy { 46 cpu = i 47 s.cpus[i] = true 48 break 49 } 50 } 51 52 if cpu == -1 { 53 cpu = len(s.cpus) 54 s.cpus = append(s.cpus, true) 55 } 56 57 s.running[action] = actionStatus{ 58 cpu: cpu, 59 start: time.Now(), 60 } 61} 62 63func (s *statusOutput) FinishAction(result status.ActionResult, counts status.Counts) { 64 start, ok := s.running[result.Action] 65 if !ok { 66 return 67 } 68 delete(s.running, result.Action) 69 s.cpus[start.cpu] = false 70 71 str := result.Action.Description 72 if len(result.Action.Outputs) > 0 { 73 str = result.Action.Outputs[0] 74 } 75 76 s.tracer.writeEvent(&viewerEvent{ 77 Name: str, 78 Phase: "X", 79 Time: uint64(start.start.UnixNano()) / 1000, 80 Dur: uint64(time.Since(start.start).Nanoseconds()) / 1000, 81 Pid: 1, 82 Tid: uint64(start.cpu), 83 Arg: &statsArg{ 84 UserTime: result.Stats.UserTime, 85 SystemTime: result.Stats.SystemTime, 86 MaxRssKB: result.Stats.MaxRssKB, 87 MinorPageFaults: result.Stats.MinorPageFaults, 88 MajorPageFaults: result.Stats.MajorPageFaults, 89 IOInputKB: result.Stats.IOInputKB, 90 IOOutputKB: result.Stats.IOOutputKB, 91 VoluntaryContextSwitches: result.Stats.VoluntaryContextSwitches, 92 InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches, 93 }, 94 }) 95} 96 97type statsArg struct { 98 UserTime uint32 `json:"user_time"` 99 SystemTime uint32 `json:"system_time_ms"` 100 MaxRssKB uint64 `json:"max_rss_kb"` 101 MinorPageFaults uint64 `json:"minor_page_faults"` 102 MajorPageFaults uint64 `json:"major_page_faults"` 103 IOInputKB uint64 `json:"io_input_kb"` 104 IOOutputKB uint64 `json:"io_output_kb"` 105 VoluntaryContextSwitches uint64 `json:"voluntary_context_switches"` 106 InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"` 107} 108 109func (s *statusOutput) Flush() {} 110func (s *statusOutput) Message(level status.MsgLevel, message string) {} 111 112func (s *statusOutput) Write(p []byte) (int, error) { 113 // Discard writes 114 return len(p), nil 115} 116