1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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 */
15
16 #include <chrono>
17
18 #include "linker.h"
19 #include "linker_context.h"
20
21 namespace {
22
PrintTime(std::ostream & o,uint64_t micros)23 void PrintTime(std::ostream &o, uint64_t micros)
24 {
25 auto f = [µs, &o](uint64_t d, const auto suffix) {
26 if (d == 1 || micros >= d) {
27 auto full = micros / d;
28 auto rem = double(micros - full * d) / d;
29 o << double(full) + rem << " " << suffix;
30 return true;
31 }
32 return false;
33 };
34 constexpr uint64_t MICRO_IN_SEC = 1'000'000;
35 constexpr uint64_t MICRO_IN_MILLI = 1'000;
36 f(MICRO_IN_SEC, "seconds") || f(MICRO_IN_MILLI, "milli seconds") || f(1, "micro seconds");
37 }
38
39 } // namespace
40
41 namespace ark::static_linker {
DefaultConfig()42 Config DefaultConfig()
43 {
44 return Config {};
45 }
46
Link(const Config & conf,const std::string & output,const std::vector<std::string> & input)47 Result Link(const Config &conf, const std::string &output, const std::vector<std::string> &input)
48 {
49 auto ctx = Context(conf);
50
51 using Clock = std::chrono::high_resolution_clock;
52
53 auto tStart = Clock::now();
54
55 ctx.Read(input); // concurrent
56 if (ctx.HasErrors()) {
57 return ctx.GetResult();
58 }
59
60 auto tRead = Clock::now();
61
62 ctx.Merge(); // sync
63 if (ctx.HasErrors()) {
64 return ctx.GetResult();
65 }
66
67 auto tMerge = Clock::now();
68
69 ctx.Parse(); // could be semi concurrent
70 if (ctx.HasErrors()) {
71 return ctx.GetResult();
72 }
73
74 auto tParse = Clock::now();
75
76 ctx.ComputeLayout(); // sync
77 if (ctx.HasErrors()) {
78 return ctx.GetResult();
79 }
80
81 auto tLayout = Clock::now();
82
83 ctx.Patch(); // concurrent
84 if (ctx.HasErrors()) {
85 return ctx.GetResult();
86 }
87
88 auto tPatch = Clock::now();
89
90 ctx.Write(output); // sync
91
92 auto tEnd = std::chrono::high_resolution_clock::now();
93
94 auto res = ctx.GetResult();
95
96 auto delta = [](const auto &s, const auto &e) {
97 return std::chrono::duration_cast<std::chrono::microseconds>(e - s).count();
98 };
99
100 res.stats.elapsed.read = delta(tStart, tRead);
101 res.stats.elapsed.merge = delta(tRead, tMerge);
102 res.stats.elapsed.parse = delta(tMerge, tParse);
103 res.stats.elapsed.layout = delta(tParse, tLayout);
104 res.stats.elapsed.patch = delta(tLayout, tPatch);
105 res.stats.elapsed.write = delta(tPatch, tEnd);
106 res.stats.elapsed.total = delta(tStart, tEnd);
107
108 return res;
109 }
110
operator <<(std::ostream & o,const Result::Stats & s)111 std::ostream &operator<<(std::ostream &o, const Result::Stats &s)
112 {
113 o << "total: ";
114 PrintTime(o, s.elapsed.total);
115 o << "\n";
116 auto printTimeHist = [&o, &s](std::string_view name, const uint64_t t) {
117 constexpr size_t MAX_NAME_SIZE = 10;
118 o << std::left << std::setw(MAX_NAME_SIZE) << name << std::internal;
119
120 o << "|";
121
122 constexpr uint64_t PARTS = 30;
123 auto dots = s.elapsed.total == 0 ? 0 : t * PARTS / s.elapsed.total;
124 using CharType = std::remove_reference_t<decltype(o)>::char_type;
125 std::fill_n(std::ostream_iterator<CharType>(o), dots, '#');
126 std::fill_n(std::ostream_iterator<CharType>(o), PARTS - dots, ' ');
127
128 o << "| ";
129 PrintTime(o, t);
130 o << "\n";
131 };
132 printTimeHist("read", s.elapsed.read);
133 printTimeHist("merge", s.elapsed.merge);
134 printTimeHist("parse", s.elapsed.parse);
135 printTimeHist("layout", s.elapsed.layout);
136 printTimeHist("patch", s.elapsed.patch);
137 printTimeHist("write", s.elapsed.write);
138
139 o << "items: " << s.itemsCount << "\n";
140 o << "classes: " << s.classCount << "\n";
141
142 o << "code items: " << s.codeCount << "\n";
143 o << "debug data: " << s.debugCount << "\n";
144
145 return o;
146 }
147
148 } // namespace ark::static_linker
149