• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 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 android
16
17import (
18	"io/ioutil"
19	"runtime"
20	"sort"
21
22	"github.com/google/blueprint/metrics"
23	"google.golang.org/protobuf/proto"
24
25	soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
26)
27
28var soongMetricsOnceKey = NewOnceKey("soong metrics")
29
30type SoongMetrics struct {
31	Modules  int
32	Variants int
33}
34
35func readSoongMetrics(config Config) (SoongMetrics, bool) {
36	soongMetrics, ok := config.Peek(soongMetricsOnceKey)
37	if ok {
38		return soongMetrics.(SoongMetrics), true
39	} else {
40		return SoongMetrics{}, false
41	}
42}
43
44func init() {
45	RegisterSingletonType("soong_metrics", soongMetricsSingletonFactory)
46}
47
48func soongMetricsSingletonFactory() Singleton { return soongMetricsSingleton{} }
49
50type soongMetricsSingleton struct{}
51
52func (soongMetricsSingleton) GenerateBuildActions(ctx SingletonContext) {
53	metrics := SoongMetrics{}
54	ctx.VisitAllModules(func(m Module) {
55		if ctx.PrimaryModule(m) == m {
56			metrics.Modules++
57		}
58		metrics.Variants++
59	})
60	ctx.Config().Once(soongMetricsOnceKey, func() interface{} {
61		return metrics
62	})
63}
64
65func collectMetrics(config Config, eventHandler *metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
66	metrics := &soong_metrics_proto.SoongBuildMetrics{}
67
68	soongMetrics, ok := readSoongMetrics(config)
69	if ok {
70		metrics.Modules = proto.Uint32(uint32(soongMetrics.Modules))
71		metrics.Variants = proto.Uint32(uint32(soongMetrics.Variants))
72	}
73
74	memStats := runtime.MemStats{}
75	runtime.ReadMemStats(&memStats)
76	metrics.MaxHeapSize = proto.Uint64(memStats.HeapSys)
77	metrics.TotalAllocCount = proto.Uint64(memStats.Mallocs)
78	metrics.TotalAllocSize = proto.Uint64(memStats.TotalAlloc)
79
80	for _, event := range eventHandler.CompletedEvents() {
81		perfInfo := soong_metrics_proto.PerfInfo{
82			Description: proto.String(event.Id),
83			Name:        proto.String("soong_build"),
84			StartTime:   proto.Uint64(uint64(event.Start.UnixNano())),
85			RealTime:    proto.Uint64(event.RuntimeNanoseconds()),
86		}
87		metrics.Events = append(metrics.Events, &perfInfo)
88	}
89	mixedBuildsInfo := soong_metrics_proto.MixedBuildsInfo{}
90	mixedBuildEnabledModules := make([]string, 0, len(config.mixedBuildEnabledModules))
91	for module, _ := range config.mixedBuildEnabledModules {
92		mixedBuildEnabledModules = append(mixedBuildEnabledModules, module)
93	}
94
95	mixedBuildDisabledModules := make([]string, 0, len(config.mixedBuildDisabledModules))
96	for module, _ := range config.mixedBuildDisabledModules {
97		mixedBuildDisabledModules = append(mixedBuildDisabledModules, module)
98	}
99	// Sorted for deterministic output.
100	sort.Strings(mixedBuildEnabledModules)
101	sort.Strings(mixedBuildDisabledModules)
102
103	mixedBuildsInfo.MixedBuildEnabledModules = mixedBuildEnabledModules
104	mixedBuildsInfo.MixedBuildDisabledModules = mixedBuildDisabledModules
105	metrics.MixedBuildsInfo = &mixedBuildsInfo
106
107	return metrics
108}
109
110func WriteMetrics(config Config, eventHandler *metrics.EventHandler, metricsFile string) error {
111	metrics := collectMetrics(config, eventHandler)
112
113	buf, err := proto.Marshal(metrics)
114	if err != nil {
115		return err
116	}
117	err = ioutil.WriteFile(absolutePath(metricsFile), buf, 0666)
118	if err != nil {
119		return err
120	}
121
122	return nil
123}
124