1 /**
2 * Copyright (c) 2021-2025 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.TryDelete();
77 if (ctx.HasErrors()) {
78 return ctx.GetResult();
79 }
80
81 auto tDelete = Clock::now();
82
83 ctx.ComputeLayout(); // sync
84 if (ctx.HasErrors()) {
85 return ctx.GetResult();
86 }
87
88 auto tLayout = Clock::now();
89
90 ctx.Patch(); // concurrent
91 if (ctx.HasErrors()) {
92 return ctx.GetResult();
93 }
94
95 auto tPatch = Clock::now();
96
97 ctx.Write(output); // sync
98
99 auto tEnd = std::chrono::high_resolution_clock::now();
100
101 auto res = ctx.GetResult();
102
103 auto delta = [](const auto &s, const auto &e) {
104 return std::chrono::duration_cast<std::chrono::microseconds>(e - s).count();
105 };
106
107 res.stats.elapsed.read = static_cast<uint64_t>(delta(tStart, tRead));
108 res.stats.elapsed.merge = static_cast<uint64_t>(delta(tRead, tMerge));
109 res.stats.elapsed.parse = static_cast<uint64_t>(delta(tMerge, tParse));
110 res.stats.elapsed.trydelete = static_cast<uint64_t>(delta(tParse, tDelete));
111 res.stats.elapsed.layout = static_cast<uint64_t>(delta(tDelete, tLayout));
112 res.stats.elapsed.patch = static_cast<uint64_t>(delta(tLayout, tPatch));
113 res.stats.elapsed.write = static_cast<uint64_t>(delta(tPatch, tEnd));
114 res.stats.elapsed.total = static_cast<uint64_t>(delta(tStart, tEnd));
115
116 return res;
117 }
118
operator <<(std::ostream & o,const Result::Stats & s)119 std::ostream &operator<<(std::ostream &o, const Result::Stats &s)
120 {
121 o << "total: ";
122 PrintTime(o, s.elapsed.total);
123 o << "\n";
124 auto printTimeHist = [&o, &s](std::string_view name, const uint64_t t) {
125 constexpr size_t MAX_NAME_SIZE = 10;
126 o << std::left << std::setw(MAX_NAME_SIZE) << name << std::internal;
127
128 o << "|";
129
130 constexpr uint64_t PARTS = 30;
131 auto dots = s.elapsed.total == 0 ? 0 : t * PARTS / s.elapsed.total;
132 using CharType = std::remove_reference_t<decltype(o)>::char_type;
133 std::fill_n(std::ostream_iterator<CharType>(o), dots, '#');
134 std::fill_n(std::ostream_iterator<CharType>(o), PARTS - dots, ' ');
135
136 o << "| ";
137 PrintTime(o, t);
138 o << "\n";
139 };
140 printTimeHist("read", s.elapsed.read);
141 printTimeHist("merge", s.elapsed.merge);
142 printTimeHist("parse", s.elapsed.parse);
143 printTimeHist("delete", s.elapsed.trydelete);
144 printTimeHist("layout", s.elapsed.layout);
145 printTimeHist("patch", s.elapsed.patch);
146 printTimeHist("write", s.elapsed.write);
147
148 o << "items: " << s.itemsCount << "\n";
149 o << "classes: " << s.classCount << "\n";
150
151 o << "code items: " << s.codeCount << "\n";
152 o << "debug data: " << s.debugCount << "\n";
153
154 return o;
155 }
156
157 } // namespace ark::static_linker
158