1 // Copyright (C) 2021 The Android Open Source Project
2 //
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 #include <ditto/instruction_set.h>
16
17 #include <variant>
18
19 #include <ditto/logger.h>
20 #include <ditto/shared_variables.h>
21
22 namespace dittosuite {
23
24 template <class... Ts>
25 struct overloaded : Ts... {
26 using Ts::operator()...;
27 };
28 template <class... Ts>
29 overloaded(Ts...) -> overloaded<Ts...>;
30
InstructionSet(const Params & params,std::vector<std::unique_ptr<Instruction>> instructions,int list_key,int item_key,Order access_order,Reseeding reseeding,uint32_t seed)31 InstructionSet::InstructionSet(const Params& params,
32 std::vector<std::unique_ptr<Instruction>> instructions, int list_key,
33 int item_key, Order access_order, Reseeding reseeding, uint32_t seed)
34 : Instruction(kName, params),
35 instructions_(std::move(instructions)),
36 list_key_(list_key),
37 item_key_(item_key),
38 access_order_(access_order),
39 reseeding_(reseeding),
40 seed_(seed),
41 gen_(seed) {}
42
InstructionSet(const Params & params,std::vector<std::unique_ptr<Instruction>> instructions)43 InstructionSet::InstructionSet(const Params& params,
44 std::vector<std::unique_ptr<Instruction>> instructions)
45 : Instruction(kName, params),
46 instructions_(std::move(instructions)),
47 list_key_(-1),
48 item_key_(-1) {}
49
SetUp()50 void InstructionSet::SetUp() {
51 if (reseeding_ == Reseeding::kEachRoundOfCycles) {
52 gen_.seed(seed_);
53 }
54 Instruction::SetUp();
55 }
56
SetUpSingle()57 void InstructionSet::SetUpSingle() {
58 if (reseeding_ == Reseeding::kEachCycle) {
59 gen_.seed(seed_);
60 }
61 Instruction::SetUpSingle();
62 }
63
RunSingle()64 void InstructionSet::RunSingle() {
65 if (list_key_ != -1 && item_key_ != -1) {
66 std::visit(overloaded{[&](const std::vector<std::string>& list) {
67 std::uniform_int_distribution<> uniform_distribution(0,
68 list.size() - 1);
69 for (std::size_t i = 0; i < list.size(); ++i) {
70 switch (access_order_) {
71 case Order::kSequential: {
72 SharedVariables::Set(item_key_, list[i]);
73 break;
74 }
75 case Order::kRandom: {
76 SharedVariables::Set(item_key_, list[uniform_distribution(gen_)]);
77 break;
78 }
79 }
80 RunInstructions();
81 }
82 },
83 [](int) {
84 LOGE("Input for InstructionSet is not iterable.");
85 exit(EXIT_FAILURE);
86 },
87 [](const std::string&) {
88 LOGE("Input for InstructionSet is not iterable.");
89 exit(EXIT_FAILURE);
90 }},
91 SharedVariables::Get(list_key_));
92 } else {
93 RunInstructions();
94 }
95 }
96
RunInstructions()97 void InstructionSet::RunInstructions() {
98 for (const auto& instruction : instructions_) {
99 instruction->SetUp();
100 instruction->Run();
101 instruction->TearDown();
102 }
103 }
104
105 // The duration for an instruction set is a sum of its child instruction durations.
CollectResults(const std::string & prefix)106 std::unique_ptr<Result> InstructionSet::CollectResults(const std::string& prefix) {
107 auto result = std::make_unique<Result>(prefix + name_, repeat_);
108 std::vector<double> duration;
109 for (const auto& instruction : instructions_) {
110 auto sub_result = instruction->CollectResults("");
111 auto samples = sub_result->GetSamples("duration");
112 auto repeat = sub_result->GetRepeat();
113
114 if (duration.empty()) {
115 duration.resize(samples.size() / repeat);
116 }
117
118 for (std::size_t i = 0; i < samples.size() / repeat; ++i) {
119 for (int j = 0; j < repeat; ++j) {
120 duration[i] += samples[i * repeat + j];
121 }
122 }
123
124 result->AddSubResult(std::move(sub_result));
125 }
126 result->AddMeasurement("duration", duration);
127 return result;
128 }
129
130 } // namespace dittosuite
131