1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <SkTraceMemoryDump.h>
20 
21 #include <string>
22 #include <unordered_map>
23 #include <vector>
24 
25 namespace android {
26 namespace renderengine {
27 namespace skia {
28 
29 // Mapping of resource substrings (1st element) that if found within a trace "dumpName"
30 // should be mapped to the category name (2nd element). All char* used in a resourcePair
31 // are expected to have a lifetime longer than the SkiaMemoryReporter in which they are used.
32 typedef std::pair<const char*, const char*> ResourcePair;
33 
34 /*
35  * Utility class for logging the CPU/GPU usage of Skia caches in a format that is specific
36  * to RenderEngine.  HWUI has a similar logging class, but the data collected and the way
37  * it is formatted and reported on are intended to be unique to each use case.
38  */
39 class SkiaMemoryReporter : public SkTraceMemoryDump {
40 public:
41     /**
42      * Creates the reporter class that can be populated by various Skia entry points, like
43      * SkGraphics and GrContext, as well as format and log the results.
44      * @param resourceMap An array of values that maps a Skia dumpName into a user defined category.
45      *                    The first vector entry that matches the dumpName is used for the mapping.
46      * @param itemize if true when logging the categories the individual elements will be printed
47      *                directly after the category details are printed.  Otherwise, only the category
48      *                totals will be printed.
49      */
50     SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize);
~SkiaMemoryReporter()51     ~SkiaMemoryReporter() override {}
52 
53     void logOutput(std::string& log, bool wrappedResources = false);
54     void logTotals(std::string& log);
55 
56     void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
57                           uint64_t value) override;
58 
dumpStringValue(const char * dumpName,const char * valueName,const char * value)59     void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
60         // for convenience we just store this in the same format as numerical values
61         dumpNumericValue(dumpName, valueName, value, 0);
62     }
63     void dumpWrappedState(const char* dumpName, bool isWrappedObject) override;
64 
getRequestedDetails()65     LevelOfDetail getRequestedDetails() const override {
66         return SkTraceMemoryDump::kLight_LevelOfDetail;
67     }
68 
shouldDumpWrappedObjects()69     bool shouldDumpWrappedObjects() const override { return true; }
setMemoryBacking(const char *,const char *,const char *)70     void setMemoryBacking(const char*, const char*, const char*) override {}
setDiscardableMemoryBacking(const char *,const SkDiscardableMemory &)71     void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {}
72 
73 private:
74     struct TraceValue {
TraceValueTraceValue75         TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
TraceValueTraceValue76         TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
77 
78         const char* units;
79         float value;
80         int count;
81     };
82 
83     const char* mapName(const char* resourceName);
84     void processCurrentElement();
85     void resetCurrentElement();
86     TraceValue convertUnits(const TraceValue& value);
87 
88     const std::vector<ResourcePair>& mResourceMap;
89     const bool mItemize;
90 
91     // variables storing the size of all non-wrapped elements being dumped
92     TraceValue mTotalSize;
93     TraceValue mPurgeableSize;
94 
95     // variables storing information on the current node being dumped
96     std::string mCurrentElement;
97     std::unordered_map<const char*, TraceValue> mCurrentValues;
98     bool mIsCurrentValueWrapped = false;
99 
100     // variable that stores the final format of the data after the individual elements are processed
101     std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
102     std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mWrappedResults;
103 };
104 
105 } /* namespace skia */
106 } /* namespace renderengine */
107 } /* namespace android */