2 * Copyright 2012 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "folly/Foreach.h"
19 #include "folly/Benchmark.h"
20 #include <gtest/gtest.h>
26 using namespace folly;
27 using namespace folly::detail;
29 TEST(Foreach, ForEachKV) {
30 std::map<std::string, int> testMap;
33 std::string keys = "";
36 FOR_EACH_KV (key, value, testMap) {
41 EXPECT_EQ("abcdef", keys);
43 EXPECT_EQ(2, numEntries);
46 TEST(Foreach, ForEachKVBreak) {
47 std::map<std::string, int> testMap;
50 std::string keys = "";
53 FOR_EACH_KV (key, value, testMap) {
59 EXPECT_EQ("abc", keys);
61 EXPECT_EQ(1, numEntries);
64 TEST(Foreach, ForEachKvWithMultiMap) {
65 std::multimap<std::string, int> testMap;
66 testMap.insert(std::make_pair("abc", 1));
67 testMap.insert(std::make_pair("abc", 2));
68 testMap.insert(std::make_pair("def", 3));
69 std::string keys = "";
72 FOR_EACH_KV (key, value, testMap) {
77 EXPECT_EQ("abcabcdef", keys);
79 EXPECT_EQ(3, numEntries);
82 TEST(Foreach, ForEachEnumerate) {
86 int numIterations = 0;
87 FOR_EACH_ENUMERATE(aa, iter, vv) {
93 EXPECT_EQ(sumIter, 0);
94 EXPECT_EQ(numIterations, 0);
99 FOR_EACH_ENUMERATE(aa, iter, vv) {
104 EXPECT_EQ(sumAA, 3); // 0 + 1 + 2
105 EXPECT_EQ(sumIter, 9); // 1 + 3 + 5
106 EXPECT_EQ(numIterations, 3);
109 TEST(Foreach, ForEachEnumerateBreak) {
113 int numIterations = 0;
118 FOR_EACH_ENUMERATE(aa, iter, vv) {
124 EXPECT_EQ(sumAA, 1); // 0 + 1
125 EXPECT_EQ(sumIter, 3); // 1 + 2
126 EXPECT_EQ(numIterations, 2);
129 TEST(Foreach, ForEachRangeR) {
132 FOR_EACH_RANGE_R (i, 0, 0) {
137 FOR_EACH_RANGE_R (i, 0, -1) {
142 FOR_EACH_RANGE_R (i, 0, 5) {
147 std::list<int> lst = { 0, 1, 2, 3, 4 };
149 FOR_EACH_RANGE_R (i, lst.begin(), lst.end()) {
156 // 1. Benchmark iterating through the man with FOR_EACH, and also assign
157 // iter->first and iter->second to local vars inside the FOR_EACH loop.
158 // 2. Benchmark iterating through the man with FOR_EACH, but use iter->first and
159 // iter->second as is, without assigning to local variables.
160 // 3. Use FOR_EACH_KV loop to iterate through the map.
162 std::map<int, std::string> bmMap; // For use in benchmarks below.
164 void setupBenchmark(int iters) {
166 for (int i = 0; i < iters; ++i) {
167 bmMap[i] = "teststring";
171 BENCHMARK(ForEachKVNoMacroAssign, iters) {
173 std::string sumValues;
176 setupBenchmark(iters);
178 std::string sumValues = "";
181 FOR_EACH (iter, bmMap) {
182 const int k = iter->first;
183 const std::string v = iter->second;
189 BENCHMARK(ForEachKVNoMacroNoAssign, iters) {
191 std::string sumValues;
194 setupBenchmark(iters);
197 FOR_EACH (iter, bmMap) {
198 sumKeys += iter->first;
199 sumValues += iter->second;
203 BENCHMARK(ManualLoopNoAssign, iters) {
205 setupBenchmark(iters);
208 std::string sumValues;
210 for (auto iter = bmMap.begin(); iter != bmMap.end(); ++iter) {
211 sumKeys += iter->first;
212 sumValues += iter->second;
216 BENCHMARK(ForEachKVMacro, iters) {
218 setupBenchmark(iters);
221 std::string sumValues;
223 FOR_EACH_KV (k, v, bmMap) {
229 BENCHMARK(ForEachManual, iters) {
231 for (auto i = 1; i < iters; ++i) {
234 doNotOptimizeAway(sum);
237 BENCHMARK(ForEachRange, iters) {
239 FOR_EACH_RANGE (i, 1, iters) {
242 doNotOptimizeAway(sum);
245 BENCHMARK(ForEachDescendingManual, iters) {
247 for (auto i = iters; i-- > 1; ) {
250 doNotOptimizeAway(sum);
253 BENCHMARK(ForEachRangeR, iters) {
255 FOR_EACH_RANGE_R (i, 1, iters) {
258 doNotOptimizeAway(sum);
261 int main(int argc, char** argv) {
262 testing::InitGoogleTest(&argc, argv);
263 auto r = RUN_ALL_TESTS();