• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = [&micros, &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