Split tests into test and benchmarks.
[folly.git] / folly / test / CacheLocalityTest.cpp
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/detail/CacheLocality.h>
18
19 #include <sched.h>
20 #include <memory>
21 #include <thread>
22 #include <type_traits>
23 #include <unordered_map>
24 #include <glog/logging.h>
25 #include <gtest/gtest.h>
26
27 using namespace folly::detail;
28
29 /// This is the relevant nodes from a production box's sysfs tree.  If you
30 /// think this map is ugly you should see the version of this test that
31 /// used a real directory tree.  To reduce the chance of testing error
32 /// I haven't tried to remove the common prefix
33 static std::unordered_map<std::string, std::string> fakeSysfsTree = {
34     {"/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list", "0,17"},
35     {"/sys/devices/system/cpu/cpu0/cache/index0/type", "Data"},
36     {"/sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_list", "0,17"},
37     {"/sys/devices/system/cpu/cpu0/cache/index1/type", "Instruction"},
38     {"/sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_list", "0,17"},
39     {"/sys/devices/system/cpu/cpu0/cache/index2/type", "Unified"},
40     {"/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_list", "0-8,17-23"},
41     {"/sys/devices/system/cpu/cpu0/cache/index3/type", "Unified"},
42     {"/sys/devices/system/cpu/cpu1/cache/index0/shared_cpu_list", "1,18"},
43     {"/sys/devices/system/cpu/cpu1/cache/index0/type", "Data"},
44     {"/sys/devices/system/cpu/cpu1/cache/index1/shared_cpu_list", "1,18"},
45     {"/sys/devices/system/cpu/cpu1/cache/index1/type", "Instruction"},
46     {"/sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_list", "1,18"},
47     {"/sys/devices/system/cpu/cpu1/cache/index2/type", "Unified"},
48     {"/sys/devices/system/cpu/cpu1/cache/index3/shared_cpu_list", "0-8,17-23"},
49     {"/sys/devices/system/cpu/cpu1/cache/index3/type", "Unified"},
50     {"/sys/devices/system/cpu/cpu2/cache/index0/shared_cpu_list", "2,19"},
51     {"/sys/devices/system/cpu/cpu2/cache/index0/type", "Data"},
52     {"/sys/devices/system/cpu/cpu2/cache/index1/shared_cpu_list", "2,19"},
53     {"/sys/devices/system/cpu/cpu2/cache/index1/type", "Instruction"},
54     {"/sys/devices/system/cpu/cpu2/cache/index2/shared_cpu_list", "2,19"},
55     {"/sys/devices/system/cpu/cpu2/cache/index2/type", "Unified"},
56     {"/sys/devices/system/cpu/cpu2/cache/index3/shared_cpu_list", "0-8,17-23"},
57     {"/sys/devices/system/cpu/cpu2/cache/index3/type", "Unified"},
58     {"/sys/devices/system/cpu/cpu3/cache/index0/shared_cpu_list", "3,20"},
59     {"/sys/devices/system/cpu/cpu3/cache/index0/type", "Data"},
60     {"/sys/devices/system/cpu/cpu3/cache/index1/shared_cpu_list", "3,20"},
61     {"/sys/devices/system/cpu/cpu3/cache/index1/type", "Instruction"},
62     {"/sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_list", "3,20"},
63     {"/sys/devices/system/cpu/cpu3/cache/index2/type", "Unified"},
64     {"/sys/devices/system/cpu/cpu3/cache/index3/shared_cpu_list", "0-8,17-23"},
65     {"/sys/devices/system/cpu/cpu3/cache/index3/type", "Unified"},
66     {"/sys/devices/system/cpu/cpu4/cache/index0/shared_cpu_list", "4,21"},
67     {"/sys/devices/system/cpu/cpu4/cache/index0/type", "Data"},
68     {"/sys/devices/system/cpu/cpu4/cache/index1/shared_cpu_list", "4,21"},
69     {"/sys/devices/system/cpu/cpu4/cache/index1/type", "Instruction"},
70     {"/sys/devices/system/cpu/cpu4/cache/index2/shared_cpu_list", "4,21"},
71     {"/sys/devices/system/cpu/cpu4/cache/index2/type", "Unified"},
72     {"/sys/devices/system/cpu/cpu4/cache/index3/shared_cpu_list", "0-8,17-23"},
73     {"/sys/devices/system/cpu/cpu4/cache/index3/type", "Unified"},
74     {"/sys/devices/system/cpu/cpu5/cache/index0/shared_cpu_list", "5-6"},
75     {"/sys/devices/system/cpu/cpu5/cache/index0/type", "Data"},
76     {"/sys/devices/system/cpu/cpu5/cache/index1/shared_cpu_list", "5-6"},
77     {"/sys/devices/system/cpu/cpu5/cache/index1/type", "Instruction"},
78     {"/sys/devices/system/cpu/cpu5/cache/index2/shared_cpu_list", "5-6"},
79     {"/sys/devices/system/cpu/cpu5/cache/index2/type", "Unified"},
80     {"/sys/devices/system/cpu/cpu5/cache/index3/shared_cpu_list", "0-8,17-23"},
81     {"/sys/devices/system/cpu/cpu5/cache/index3/type", "Unified"},
82     {"/sys/devices/system/cpu/cpu6/cache/index0/shared_cpu_list", "5-6"},
83     {"/sys/devices/system/cpu/cpu6/cache/index0/type", "Data"},
84     {"/sys/devices/system/cpu/cpu6/cache/index1/shared_cpu_list", "5-6"},
85     {"/sys/devices/system/cpu/cpu6/cache/index1/type", "Instruction"},
86     {"/sys/devices/system/cpu/cpu6/cache/index2/shared_cpu_list", "5-6"},
87     {"/sys/devices/system/cpu/cpu6/cache/index2/type", "Unified"},
88     {"/sys/devices/system/cpu/cpu6/cache/index3/shared_cpu_list", "0-8,17-23"},
89     {"/sys/devices/system/cpu/cpu6/cache/index3/type", "Unified"},
90     {"/sys/devices/system/cpu/cpu7/cache/index0/shared_cpu_list", "7,22"},
91     {"/sys/devices/system/cpu/cpu7/cache/index0/type", "Data"},
92     {"/sys/devices/system/cpu/cpu7/cache/index1/shared_cpu_list", "7,22"},
93     {"/sys/devices/system/cpu/cpu7/cache/index1/type", "Instruction"},
94     {"/sys/devices/system/cpu/cpu7/cache/index2/shared_cpu_list", "7,22"},
95     {"/sys/devices/system/cpu/cpu7/cache/index2/type", "Unified"},
96     {"/sys/devices/system/cpu/cpu7/cache/index3/shared_cpu_list", "0-8,17-23"},
97     {"/sys/devices/system/cpu/cpu7/cache/index3/type", "Unified"},
98     {"/sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_list", "8,23"},
99     {"/sys/devices/system/cpu/cpu8/cache/index0/type", "Data"},
100     {"/sys/devices/system/cpu/cpu8/cache/index1/shared_cpu_list", "8,23"},
101     {"/sys/devices/system/cpu/cpu8/cache/index1/type", "Instruction"},
102     {"/sys/devices/system/cpu/cpu8/cache/index2/shared_cpu_list", "8,23"},
103     {"/sys/devices/system/cpu/cpu8/cache/index2/type", "Unified"},
104     {"/sys/devices/system/cpu/cpu8/cache/index3/shared_cpu_list", "0-8,17-23"},
105     {"/sys/devices/system/cpu/cpu8/cache/index3/type", "Unified"},
106     {"/sys/devices/system/cpu/cpu9/cache/index0/shared_cpu_list", "9,24"},
107     {"/sys/devices/system/cpu/cpu9/cache/index0/type", "Data"},
108     {"/sys/devices/system/cpu/cpu9/cache/index1/shared_cpu_list", "9,24"},
109     {"/sys/devices/system/cpu/cpu9/cache/index1/type", "Instruction"},
110     {"/sys/devices/system/cpu/cpu9/cache/index2/shared_cpu_list", "9,24"},
111     {"/sys/devices/system/cpu/cpu9/cache/index2/type", "Unified"},
112     {"/sys/devices/system/cpu/cpu9/cache/index3/shared_cpu_list", "9-16,24-31"},
113     {"/sys/devices/system/cpu/cpu9/cache/index3/type", "Unified"},
114     {"/sys/devices/system/cpu/cpu10/cache/index0/shared_cpu_list", "10,25"},
115     {"/sys/devices/system/cpu/cpu10/cache/index0/type", "Data"},
116     {"/sys/devices/system/cpu/cpu10/cache/index1/shared_cpu_list", "10,25"},
117     {"/sys/devices/system/cpu/cpu10/cache/index1/type", "Instruction"},
118     {"/sys/devices/system/cpu/cpu10/cache/index2/shared_cpu_list", "10,25"},
119     {"/sys/devices/system/cpu/cpu10/cache/index2/type", "Unified"},
120     {"/sys/devices/system/cpu/cpu10/cache/index3/shared_cpu_list",
121      "9-16,24-31"},
122     {"/sys/devices/system/cpu/cpu10/cache/index3/type", "Unified"},
123     {"/sys/devices/system/cpu/cpu11/cache/index0/shared_cpu_list", "11,26"},
124     {"/sys/devices/system/cpu/cpu11/cache/index0/type", "Data"},
125     {"/sys/devices/system/cpu/cpu11/cache/index1/shared_cpu_list", "11,26"},
126     {"/sys/devices/system/cpu/cpu11/cache/index1/type", "Instruction"},
127     {"/sys/devices/system/cpu/cpu11/cache/index2/shared_cpu_list", "11,26"},
128     {"/sys/devices/system/cpu/cpu11/cache/index2/type", "Unified"},
129     {"/sys/devices/system/cpu/cpu11/cache/index3/shared_cpu_list",
130      "9-16,24-31"},
131     {"/sys/devices/system/cpu/cpu11/cache/index3/type", "Unified"},
132     {"/sys/devices/system/cpu/cpu12/cache/index0/shared_cpu_list", "12,27"},
133     {"/sys/devices/system/cpu/cpu12/cache/index0/type", "Data"},
134     {"/sys/devices/system/cpu/cpu12/cache/index1/shared_cpu_list", "12,27"},
135     {"/sys/devices/system/cpu/cpu12/cache/index1/type", "Instruction"},
136     {"/sys/devices/system/cpu/cpu12/cache/index2/shared_cpu_list", "12,27"},
137     {"/sys/devices/system/cpu/cpu12/cache/index2/type", "Unified"},
138     {"/sys/devices/system/cpu/cpu12/cache/index3/shared_cpu_list",
139      "9-16,24-31"},
140     {"/sys/devices/system/cpu/cpu12/cache/index3/type", "Unified"},
141     {"/sys/devices/system/cpu/cpu13/cache/index0/shared_cpu_list", "13,28"},
142     {"/sys/devices/system/cpu/cpu13/cache/index0/type", "Data"},
143     {"/sys/devices/system/cpu/cpu13/cache/index1/shared_cpu_list", "13,28"},
144     {"/sys/devices/system/cpu/cpu13/cache/index1/type", "Instruction"},
145     {"/sys/devices/system/cpu/cpu13/cache/index2/shared_cpu_list", "13,28"},
146     {"/sys/devices/system/cpu/cpu13/cache/index2/type", "Unified"},
147     {"/sys/devices/system/cpu/cpu13/cache/index3/shared_cpu_list",
148      "9-16,24-31"},
149     {"/sys/devices/system/cpu/cpu13/cache/index3/type", "Unified"},
150     {"/sys/devices/system/cpu/cpu14/cache/index0/shared_cpu_list", "14,29"},
151     {"/sys/devices/system/cpu/cpu14/cache/index0/type", "Data"},
152     {"/sys/devices/system/cpu/cpu14/cache/index1/shared_cpu_list", "14,29"},
153     {"/sys/devices/system/cpu/cpu14/cache/index1/type", "Instruction"},
154     {"/sys/devices/system/cpu/cpu14/cache/index2/shared_cpu_list", "14,29"},
155     {"/sys/devices/system/cpu/cpu14/cache/index2/type", "Unified"},
156     {"/sys/devices/system/cpu/cpu14/cache/index3/shared_cpu_list",
157      "9-16,24-31"},
158     {"/sys/devices/system/cpu/cpu14/cache/index3/type", "Unified"},
159     {"/sys/devices/system/cpu/cpu15/cache/index0/shared_cpu_list", "15,30"},
160     {"/sys/devices/system/cpu/cpu15/cache/index0/type", "Data"},
161     {"/sys/devices/system/cpu/cpu15/cache/index1/shared_cpu_list", "15,30"},
162     {"/sys/devices/system/cpu/cpu15/cache/index1/type", "Instruction"},
163     {"/sys/devices/system/cpu/cpu15/cache/index2/shared_cpu_list", "15,30"},
164     {"/sys/devices/system/cpu/cpu15/cache/index2/type", "Unified"},
165     {"/sys/devices/system/cpu/cpu15/cache/index3/shared_cpu_list",
166      "9-16,24-31"},
167     {"/sys/devices/system/cpu/cpu15/cache/index3/type", "Unified"},
168     {"/sys/devices/system/cpu/cpu16/cache/index0/shared_cpu_list", "16,31"},
169     {"/sys/devices/system/cpu/cpu16/cache/index0/type", "Data"},
170     {"/sys/devices/system/cpu/cpu16/cache/index1/shared_cpu_list", "16,31"},
171     {"/sys/devices/system/cpu/cpu16/cache/index1/type", "Instruction"},
172     {"/sys/devices/system/cpu/cpu16/cache/index2/shared_cpu_list", "16,31"},
173     {"/sys/devices/system/cpu/cpu16/cache/index2/type", "Unified"},
174     {"/sys/devices/system/cpu/cpu16/cache/index3/shared_cpu_list",
175      "9-16,24-31"},
176     {"/sys/devices/system/cpu/cpu16/cache/index3/type", "Unified"},
177     {"/sys/devices/system/cpu/cpu17/cache/index0/shared_cpu_list", "0,17"},
178     {"/sys/devices/system/cpu/cpu17/cache/index0/type", "Data"},
179     {"/sys/devices/system/cpu/cpu17/cache/index1/shared_cpu_list", "0,17"},
180     {"/sys/devices/system/cpu/cpu17/cache/index1/type", "Instruction"},
181     {"/sys/devices/system/cpu/cpu17/cache/index2/shared_cpu_list", "0,17"},
182     {"/sys/devices/system/cpu/cpu17/cache/index2/type", "Unified"},
183     {"/sys/devices/system/cpu/cpu17/cache/index3/shared_cpu_list", "0-8,17-23"},
184     {"/sys/devices/system/cpu/cpu17/cache/index3/type", "Unified"},
185     {"/sys/devices/system/cpu/cpu18/cache/index0/shared_cpu_list", "1,18"},
186     {"/sys/devices/system/cpu/cpu18/cache/index0/type", "Data"},
187     {"/sys/devices/system/cpu/cpu18/cache/index1/shared_cpu_list", "1,18"},
188     {"/sys/devices/system/cpu/cpu18/cache/index1/type", "Instruction"},
189     {"/sys/devices/system/cpu/cpu18/cache/index2/shared_cpu_list", "1,18"},
190     {"/sys/devices/system/cpu/cpu18/cache/index2/type", "Unified"},
191     {"/sys/devices/system/cpu/cpu18/cache/index3/shared_cpu_list", "0-8,17-23"},
192     {"/sys/devices/system/cpu/cpu18/cache/index3/type", "Unified"},
193     {"/sys/devices/system/cpu/cpu19/cache/index0/shared_cpu_list", "2,19"},
194     {"/sys/devices/system/cpu/cpu19/cache/index0/type", "Data"},
195     {"/sys/devices/system/cpu/cpu19/cache/index1/shared_cpu_list", "2,19"},
196     {"/sys/devices/system/cpu/cpu19/cache/index1/type", "Instruction"},
197     {"/sys/devices/system/cpu/cpu19/cache/index2/shared_cpu_list", "2,19"},
198     {"/sys/devices/system/cpu/cpu19/cache/index2/type", "Unified"},
199     {"/sys/devices/system/cpu/cpu19/cache/index3/shared_cpu_list", "0-8,17-23"},
200     {"/sys/devices/system/cpu/cpu19/cache/index3/type", "Unified"},
201     {"/sys/devices/system/cpu/cpu20/cache/index0/shared_cpu_list", "3,20"},
202     {"/sys/devices/system/cpu/cpu20/cache/index0/type", "Data"},
203     {"/sys/devices/system/cpu/cpu20/cache/index1/shared_cpu_list", "3,20"},
204     {"/sys/devices/system/cpu/cpu20/cache/index1/type", "Instruction"},
205     {"/sys/devices/system/cpu/cpu20/cache/index2/shared_cpu_list", "3,20"},
206     {"/sys/devices/system/cpu/cpu20/cache/index2/type", "Unified"},
207     {"/sys/devices/system/cpu/cpu20/cache/index3/shared_cpu_list", "0-8,17-23"},
208     {"/sys/devices/system/cpu/cpu20/cache/index3/type", "Unified"},
209     {"/sys/devices/system/cpu/cpu21/cache/index0/shared_cpu_list", "4,21"},
210     {"/sys/devices/system/cpu/cpu21/cache/index0/type", "Data"},
211     {"/sys/devices/system/cpu/cpu21/cache/index1/shared_cpu_list", "4,21"},
212     {"/sys/devices/system/cpu/cpu21/cache/index1/type", "Instruction"},
213     {"/sys/devices/system/cpu/cpu21/cache/index2/shared_cpu_list", "4,21"},
214     {"/sys/devices/system/cpu/cpu21/cache/index2/type", "Unified"},
215     {"/sys/devices/system/cpu/cpu21/cache/index3/shared_cpu_list", "0-8,17-23"},
216     {"/sys/devices/system/cpu/cpu21/cache/index3/type", "Unified"},
217     {"/sys/devices/system/cpu/cpu22/cache/index0/shared_cpu_list", "7,22"},
218     {"/sys/devices/system/cpu/cpu22/cache/index0/type", "Data"},
219     {"/sys/devices/system/cpu/cpu22/cache/index1/shared_cpu_list", "7,22"},
220     {"/sys/devices/system/cpu/cpu22/cache/index1/type", "Instruction"},
221     {"/sys/devices/system/cpu/cpu22/cache/index2/shared_cpu_list", "7,22"},
222     {"/sys/devices/system/cpu/cpu22/cache/index2/type", "Unified"},
223     {"/sys/devices/system/cpu/cpu22/cache/index3/shared_cpu_list", "0-8,17-23"},
224     {"/sys/devices/system/cpu/cpu22/cache/index3/type", "Unified"},
225     {"/sys/devices/system/cpu/cpu23/cache/index0/shared_cpu_list", "8,23"},
226     {"/sys/devices/system/cpu/cpu23/cache/index0/type", "Data"},
227     {"/sys/devices/system/cpu/cpu23/cache/index1/shared_cpu_list", "8,23"},
228     {"/sys/devices/system/cpu/cpu23/cache/index1/type", "Instruction"},
229     {"/sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_list", "8,23"},
230     {"/sys/devices/system/cpu/cpu23/cache/index2/type", "Unified"},
231     {"/sys/devices/system/cpu/cpu23/cache/index3/shared_cpu_list", "0-8,17-23"},
232     {"/sys/devices/system/cpu/cpu23/cache/index3/type", "Unified"},
233     {"/sys/devices/system/cpu/cpu24/cache/index0/shared_cpu_list", "9,24"},
234     {"/sys/devices/system/cpu/cpu24/cache/index0/type", "Data"},
235     {"/sys/devices/system/cpu/cpu24/cache/index1/shared_cpu_list", "9,24"},
236     {"/sys/devices/system/cpu/cpu24/cache/index1/type", "Instruction"},
237     {"/sys/devices/system/cpu/cpu24/cache/index2/shared_cpu_list", "9,24"},
238     {"/sys/devices/system/cpu/cpu24/cache/index2/type", "Unified"},
239     {"/sys/devices/system/cpu/cpu24/cache/index3/shared_cpu_list",
240      "9-16,24-31"},
241     {"/sys/devices/system/cpu/cpu24/cache/index3/type", "Unified"},
242     {"/sys/devices/system/cpu/cpu25/cache/index0/shared_cpu_list", "10,25"},
243     {"/sys/devices/system/cpu/cpu25/cache/index0/type", "Data"},
244     {"/sys/devices/system/cpu/cpu25/cache/index1/shared_cpu_list", "10,25"},
245     {"/sys/devices/system/cpu/cpu25/cache/index1/type", "Instruction"},
246     {"/sys/devices/system/cpu/cpu25/cache/index2/shared_cpu_list", "10,25"},
247     {"/sys/devices/system/cpu/cpu25/cache/index2/type", "Unified"},
248     {"/sys/devices/system/cpu/cpu25/cache/index3/shared_cpu_list",
249      "9-16,24-31"},
250     {"/sys/devices/system/cpu/cpu25/cache/index3/type", "Unified"},
251     {"/sys/devices/system/cpu/cpu26/cache/index0/shared_cpu_list", "11,26"},
252     {"/sys/devices/system/cpu/cpu26/cache/index0/type", "Data"},
253     {"/sys/devices/system/cpu/cpu26/cache/index1/shared_cpu_list", "11,26"},
254     {"/sys/devices/system/cpu/cpu26/cache/index1/type", "Instruction"},
255     {"/sys/devices/system/cpu/cpu26/cache/index2/shared_cpu_list", "11,26"},
256     {"/sys/devices/system/cpu/cpu26/cache/index2/type", "Unified"},
257     {"/sys/devices/system/cpu/cpu26/cache/index3/shared_cpu_list",
258      "9-16,24-31"},
259     {"/sys/devices/system/cpu/cpu26/cache/index3/type", "Unified"},
260     {"/sys/devices/system/cpu/cpu27/cache/index0/shared_cpu_list", "12,27"},
261     {"/sys/devices/system/cpu/cpu27/cache/index0/type", "Data"},
262     {"/sys/devices/system/cpu/cpu27/cache/index1/shared_cpu_list", "12,27"},
263     {"/sys/devices/system/cpu/cpu27/cache/index1/type", "Instruction"},
264     {"/sys/devices/system/cpu/cpu27/cache/index2/shared_cpu_list", "12,27"},
265     {"/sys/devices/system/cpu/cpu27/cache/index2/type", "Unified"},
266     {"/sys/devices/system/cpu/cpu27/cache/index3/shared_cpu_list",
267      "9-16,24-31"},
268     {"/sys/devices/system/cpu/cpu27/cache/index3/type", "Unified"},
269     {"/sys/devices/system/cpu/cpu28/cache/index0/shared_cpu_list", "13,28"},
270     {"/sys/devices/system/cpu/cpu28/cache/index0/type", "Data"},
271     {"/sys/devices/system/cpu/cpu28/cache/index1/shared_cpu_list", "13,28"},
272     {"/sys/devices/system/cpu/cpu28/cache/index1/type", "Instruction"},
273     {"/sys/devices/system/cpu/cpu28/cache/index2/shared_cpu_list", "13,28"},
274     {"/sys/devices/system/cpu/cpu28/cache/index2/type", "Unified"},
275     {"/sys/devices/system/cpu/cpu28/cache/index3/shared_cpu_list",
276      "9-16,24-31"},
277     {"/sys/devices/system/cpu/cpu28/cache/index3/type", "Unified"},
278     {"/sys/devices/system/cpu/cpu29/cache/index0/shared_cpu_list", "14,29"},
279     {"/sys/devices/system/cpu/cpu29/cache/index0/type", "Data"},
280     {"/sys/devices/system/cpu/cpu29/cache/index1/shared_cpu_list", "14,29"},
281     {"/sys/devices/system/cpu/cpu29/cache/index1/type", "Instruction"},
282     {"/sys/devices/system/cpu/cpu29/cache/index2/shared_cpu_list", "14,29"},
283     {"/sys/devices/system/cpu/cpu29/cache/index2/type", "Unified"},
284     {"/sys/devices/system/cpu/cpu29/cache/index3/shared_cpu_list",
285      "9-16,24-31"},
286     {"/sys/devices/system/cpu/cpu29/cache/index3/type", "Unified"},
287     {"/sys/devices/system/cpu/cpu30/cache/index0/shared_cpu_list", "15,30"},
288     {"/sys/devices/system/cpu/cpu30/cache/index0/type", "Data"},
289     {"/sys/devices/system/cpu/cpu30/cache/index1/shared_cpu_list", "15,30"},
290     {"/sys/devices/system/cpu/cpu30/cache/index1/type", "Instruction"},
291     {"/sys/devices/system/cpu/cpu30/cache/index2/shared_cpu_list", "15,30"},
292     {"/sys/devices/system/cpu/cpu30/cache/index2/type", "Unified"},
293     {"/sys/devices/system/cpu/cpu30/cache/index3/shared_cpu_list",
294      "9-16,24-31"},
295     {"/sys/devices/system/cpu/cpu30/cache/index3/type", "Unified"},
296     {"/sys/devices/system/cpu/cpu31/cache/index0/shared_cpu_list", "16,31"},
297     {"/sys/devices/system/cpu/cpu31/cache/index0/type", "Data"},
298     {"/sys/devices/system/cpu/cpu31/cache/index1/shared_cpu_list", "16,31"},
299     {"/sys/devices/system/cpu/cpu31/cache/index1/type", "Instruction"},
300     {"/sys/devices/system/cpu/cpu31/cache/index2/shared_cpu_list", "16,31"},
301     {"/sys/devices/system/cpu/cpu31/cache/index2/type", "Unified"},
302     {"/sys/devices/system/cpu/cpu31/cache/index3/shared_cpu_list",
303      "9-16,24-31"},
304     {"/sys/devices/system/cpu/cpu31/cache/index3/type", "Unified"}};
305
306 /// This is the expected CacheLocality structure for fakeSysfsTree
307 static const CacheLocality nonUniformExampleLocality = {32,
308                                                         {16, 16, 2},
309                                                         {0,
310                                                          2,
311                                                          4,
312                                                          6,
313                                                          8,
314                                                          10,
315                                                          11,
316                                                          12,
317                                                          14,
318                                                          16,
319                                                          18,
320                                                          20,
321                                                          22,
322                                                          24,
323                                                          26,
324                                                          28,
325                                                          30,
326                                                          1,
327                                                          3,
328                                                          5,
329                                                          7,
330                                                          9,
331                                                          13,
332                                                          15,
333                                                          17,
334                                                          19,
335                                                          21,
336                                                          23,
337                                                          25,
338                                                          27,
339                                                          29,
340                                                          31}};
341
342 TEST(CacheLocality, FakeSysfs) {
343   auto parsed = CacheLocality::readFromSysfsTree([](std::string name) {
344     auto iter = fakeSysfsTree.find(name);
345     return iter == fakeSysfsTree.end() ? std::string() : iter->second;
346   });
347
348   auto& expected = nonUniformExampleLocality;
349   EXPECT_EQ(expected.numCpus, parsed.numCpus);
350   EXPECT_EQ(expected.numCachesByLevel, parsed.numCachesByLevel);
351   EXPECT_EQ(expected.localityIndexByCpu, parsed.localityIndexByCpu);
352 }
353
354 TEST(Getcpu, VdsoGetcpu) {
355   unsigned cpu;
356   Getcpu::resolveVdsoFunc()(&cpu, nullptr, nullptr);
357
358   EXPECT_TRUE(cpu < CPU_SETSIZE);
359 }
360
361 #ifdef FOLLY_TLS
362 TEST(ThreadId, SimpleTls) {
363   unsigned cpu = 0;
364   auto rv =
365       folly::detail::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
366           &cpu, nullptr, nullptr);
367   EXPECT_EQ(rv, 0);
368   EXPECT_TRUE(cpu > 0);
369   unsigned again;
370   folly::detail::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
371       &again, nullptr, nullptr);
372   EXPECT_EQ(cpu, again);
373 }
374 #endif
375
376 TEST(ThreadId, SimplePthread) {
377   unsigned cpu = 0;
378   auto rv = folly::detail::FallbackGetcpu<HashingThreadId>::getcpu(
379       &cpu, nullptr, nullptr);
380   EXPECT_EQ(rv, 0);
381   EXPECT_TRUE(cpu > 0);
382   unsigned again;
383   folly::detail::FallbackGetcpu<HashingThreadId>::getcpu(
384       &again, nullptr, nullptr);
385   EXPECT_EQ(cpu, again);
386 }
387
388 static FOLLY_TLS unsigned testingCpu = 0;
389
390 static int testingGetcpu(unsigned* cpu, unsigned* node, void* /* unused */) {
391   if (cpu != nullptr) {
392     *cpu = testingCpu;
393   }
394   if (node != nullptr) {
395     *node = testingCpu;
396   }
397   return 0;
398 }
399
400 TEST(AccessSpreader, Simple) {
401   for (size_t s = 1; s < 200; ++s) {
402     EXPECT_LT(AccessSpreader<>::current(s), s);
403   }
404 }
405
406 #define DECLARE_SPREADER_TAG(tag, locality, func)      \
407   namespace {                                          \
408   template <typename dummy>                            \
409   struct tag {};                                       \
410   }                                                    \
411   DECLARE_ACCESS_SPREADER_TYPE(tag)                    \
412   namespace folly {                                    \
413   namespace detail {                                   \
414   template <>                                          \
415   const CacheLocality& CacheLocality::system<tag>() {  \
416     static auto* inst = new CacheLocality(locality);   \
417     return *inst;                                      \
418   }                                                    \
419   template <>                                          \
420   Getcpu::Func AccessSpreader<tag>::pickGetcpuFunc() { \
421     return func;                                       \
422   }                                                    \
423   }                                                    \
424   }
425
426 DECLARE_SPREADER_TAG(ManualTag, CacheLocality::uniform(16), testingGetcpu)
427
428 TEST(AccessSpreader, Wrapping) {
429   // this test won't pass unless locality.numCpus divides kMaxCpus
430   auto numCpus = CacheLocality::system<ManualTag>().numCpus;
431   EXPECT_EQ(0, 128 % numCpus);
432   for (size_t s = 1; s < 200; ++s) {
433     for (size_t c = 0; c < 400; ++c) {
434       testingCpu = c;
435       auto observed = AccessSpreader<ManualTag>::current(s);
436       testingCpu = c % numCpus;
437       auto expected = AccessSpreader<ManualTag>::current(s);
438       EXPECT_EQ(expected, observed) << "numCpus=" << numCpus << ", s=" << s
439                                     << ", c=" << c;
440     }
441   }
442 }