1 | /** |
2 | * Copyright (c) Glow Contributors. See CONTRIBUTORS file. |
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 | #include "glow/Runtime/StatsExporter.h" |
18 | #include "glow/Backends/DeviceManager.h" |
19 | #include "glow/Runtime/HostManager/HostManager.h" |
20 | |
21 | #include <gtest/gtest.h> |
22 | |
23 | #include <memory> |
24 | |
25 | using namespace glow; |
26 | |
27 | class MockStatsExporter : public StatsExporter { |
28 | std::shared_ptr<StatsExporterRegistry> statsExporterRegistry_; |
29 | |
30 | public: |
31 | MockStatsExporter() : statsExporterRegistry_(StatsExporterRegistry::Stats()) { |
32 | statsExporterRegistry_->registerStatsExporter(this); |
33 | } |
34 | |
35 | ~MockStatsExporter() override { |
36 | statsExporterRegistry_->revokeStatsExporter(this); |
37 | } |
38 | |
39 | void addTimeSeriesValue(llvm::StringRef key, double value) override { |
40 | timeSeries[key.str()].push_back(value); |
41 | } |
42 | |
43 | void incrementCounter(llvm::StringRef key, int64_t value) override { |
44 | counters[key.str()] += value; |
45 | } |
46 | |
47 | void setCounter(llvm::StringRef key, int64_t value) override { |
48 | counters[key.str()] = value; |
49 | } |
50 | |
51 | void clear() { |
52 | counters.clear(); |
53 | timeSeries.clear(); |
54 | } |
55 | |
56 | std::map<std::string, int64_t> counters; |
57 | std::map<std::string, std::vector<double>> timeSeries; |
58 | } MockStats; |
59 | |
60 | class StatsExporterTest : public ::testing::Test { |
61 | ~StatsExporterTest() { MockStats.clear(); } |
62 | }; |
63 | |
64 | TEST(StatsExporter, Counter) { |
65 | MockStats.setCounter("foo" , 1); |
66 | ASSERT_EQ(MockStats.counters["foo" ], 1); |
67 | MockStats.setCounter("foo" , 3); |
68 | ASSERT_EQ(MockStats.counters["foo" ], 3); |
69 | MockStats.incrementCounter("foo" , 1); |
70 | ASSERT_EQ(MockStats.counters["foo" ], 4); |
71 | MockStats.incrementCounter("foo" , -1); |
72 | ASSERT_EQ(MockStats.counters["foo" ], 3); |
73 | } |
74 | |
75 | TEST(StatsExporter, TimeSeries) { |
76 | MockStats.addTimeSeriesValue("bar" , 1); |
77 | MockStats.addTimeSeriesValue("bar" , 3.14); |
78 | MockStats.addTimeSeriesValue("bar" , 2.71); |
79 | auto it = MockStats.timeSeries.find("bar" ); |
80 | ASSERT_NE(it, MockStats.timeSeries.end()); |
81 | auto const &ts = it->second; |
82 | ASSERT_EQ(ts.size(), 3); |
83 | EXPECT_EQ(ts[0], 1); |
84 | EXPECT_EQ(ts[1], 3.14); |
85 | EXPECT_EQ(ts[2], 2.71); |
86 | } |
87 | |
88 | TEST(StatsExporter, Device) { |
89 | using namespace glow::runtime; |
90 | EXPECT_EQ(MockStats.counters.count("glow.devices_used.interpreter" ), 0); |
91 | EXPECT_EQ(MockStats.counters.count("glow.device.used_memory.device0" ), 0); |
92 | EXPECT_EQ(MockStats.counters.count("glow.device.available_memory.device0" ), |
93 | 0); |
94 | { |
95 | std::unique_ptr<DeviceManager> DM( |
96 | DeviceManager::createDeviceManager(DeviceConfig("Interpreter" ))); |
97 | EXPECT_EQ(MockStats.counters["glow.devices_used.interpreter" ], 1); |
98 | EXPECT_EQ(MockStats.counters["glow.device.used_memory.device0" ], 0); |
99 | EXPECT_EQ(MockStats.counters["glow.device.available_memory.device0" ], |
100 | 2000000000); |
101 | } |
102 | EXPECT_EQ(MockStats.counters["glow.devices_used.interpreter" ], 0); |
103 | } |
104 | |
105 | TEST(StatsExporter, HostManager) { |
106 | using namespace glow::runtime; |
107 | EXPECT_EQ(MockStats.counters.count("glow.devices.used_memory.total" ), 0); |
108 | EXPECT_EQ(MockStats.counters.count("glow.devices.available_memory.total" ), 0); |
109 | EXPECT_EQ(MockStats.counters.count("glow.devices.maximum_memory.total" ), 0); |
110 | { |
111 | auto deviceConfig = glow::make_unique<DeviceConfig>("Interpreter" ); |
112 | std::vector<std::unique_ptr<DeviceConfig>> configs; |
113 | configs.push_back(std::move(deviceConfig)); |
114 | std::unique_ptr<HostManager> HM = |
115 | glow::make_unique<HostManager>(std::move(configs), HostConfig()); |
116 | EXPECT_EQ(MockStats.counters["glow.devices.used_memory.total" ], 0); |
117 | EXPECT_EQ(MockStats.counters["glow.devices.available_memory.total" ], |
118 | 2000000000); |
119 | EXPECT_EQ(MockStats.counters["glow.devices.maximum_memory.total" ], |
120 | 2000000000); |
121 | |
122 | // Add a network so the memory used value is non-zero. |
123 | std::unique_ptr<Module> module = glow::make_unique<Module>(); |
124 | Function *F = module->createFunction("main" ); |
125 | auto *X = module->createConstant(ElemKind::FloatTy, {1024, 1024}, "X" ); |
126 | auto *pow = F->createPow("Pow" , X, 2.0); |
127 | F->createSave("save" , pow); |
128 | |
129 | const int64_t functionCost = X->getType()->getSizeInBytes(); |
130 | |
131 | CompilationContext cctx; |
132 | EXIT_ON_ERR(HM->addNetwork(std::move(module), cctx)); |
133 | // Currently the interpreter DM treats all added networks as size 1 byte so |
134 | // expect to see 1 byte used. |
135 | EXPECT_EQ(MockStats.counters["glow.devices.used_memory.total" ], |
136 | functionCost); |
137 | EXPECT_EQ(MockStats.counters["glow.devices.available_memory.total" ], |
138 | 2000000000 - functionCost); |
139 | } |
140 | EXPECT_EQ(MockStats.counters["glow.devices_used.interpreter" ], 0); |
141 | } |
142 | |