5005d65acac6c46f9a884f3d839306cffb9c2498
[folly.git] / folly / concurrency / test / CacheLocalityTest.cpp
1 /*
2  * Copyright 2017 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/concurrency/CacheLocality.h>
18
19 #include <folly/portability/GTest.h>
20
21 #include <glog/logging.h>
22 #include <memory>
23 #include <thread>
24 #include <type_traits>
25 #include <unordered_map>
26
27 using namespace folly;
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 = {
308     32,
309     {16, 16, 2},
310     {0,  2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28,
311      30, 1, 3, 5, 7, 9,  13, 15, 17, 19, 21, 23, 25, 27, 29, 31}};
312
313 TEST(CacheLocality, FakeSysfs) {
314   auto parsed = CacheLocality::readFromSysfsTree([](std::string name) {
315     auto iter = fakeSysfsTree.find(name);
316     return iter == fakeSysfsTree.end() ? std::string() : iter->second;
317   });
318
319   auto& expected = nonUniformExampleLocality;
320   EXPECT_EQ(expected.numCpus, parsed.numCpus);
321   EXPECT_EQ(expected.numCachesByLevel, parsed.numCachesByLevel);
322   EXPECT_EQ(expected.localityIndexByCpu, parsed.localityIndexByCpu);
323 }
324
325 #if FOLLY_HAVE_LINUX_VDSO
326 TEST(Getcpu, VdsoGetcpu) {
327   unsigned cpu;
328   Getcpu::resolveVdsoFunc()(&cpu, nullptr, nullptr);
329
330   EXPECT_TRUE(cpu < CPU_SETSIZE);
331 }
332 #endif
333
334 #ifdef FOLLY_TLS
335 TEST(ThreadId, SimpleTls) {
336   unsigned cpu = 0;
337   auto rv = folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
338       &cpu, nullptr, nullptr);
339   EXPECT_EQ(rv, 0);
340   EXPECT_TRUE(cpu > 0);
341   unsigned again;
342   folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
343       &again, nullptr, nullptr);
344   EXPECT_EQ(cpu, again);
345 }
346 #endif
347
348 TEST(ThreadId, SimplePthread) {
349   unsigned cpu = 0;
350   auto rv =
351       folly::FallbackGetcpu<HashingThreadId>::getcpu(&cpu, nullptr, nullptr);
352   EXPECT_EQ(rv, 0);
353   EXPECT_TRUE(cpu > 0);
354   unsigned again;
355   folly::FallbackGetcpu<HashingThreadId>::getcpu(&again, nullptr, nullptr);
356   EXPECT_EQ(cpu, again);
357 }
358
359 #ifdef FOLLY_TLS
360 static FOLLY_TLS unsigned testingCpu = 0;
361
362 static int testingGetcpu(unsigned* cpu, unsigned* node, void* /* unused */) {
363   if (cpu != nullptr) {
364     *cpu = testingCpu;
365   }
366   if (node != nullptr) {
367     *node = testingCpu;
368   }
369   return 0;
370 }
371 #endif
372
373 TEST(AccessSpreader, Simple) {
374   for (size_t s = 1; s < 200; ++s) {
375     EXPECT_LT(AccessSpreader<>::current(s), s);
376   }
377 }
378
379 #ifdef FOLLY_TLS
380 #define DECLARE_SPREADER_TAG(tag, locality, func)      \
381   namespace {                                          \
382   template <typename dummy>                            \
383   struct tag {};                                       \
384   }                                                    \
385   namespace folly {                                    \
386   template <>                                          \
387   const CacheLocality& CacheLocality::system<tag>() {  \
388     static auto* inst = new CacheLocality(locality);   \
389     return *inst;                                      \
390   }                                                    \
391   template <>                                          \
392   Getcpu::Func AccessSpreader<tag>::pickGetcpuFunc() { \
393     return func;                                       \
394   }                                                    \
395   }
396
397 DECLARE_SPREADER_TAG(ManualTag, CacheLocality::uniform(16), testingGetcpu)
398
399 TEST(AccessSpreader, Wrapping) {
400   // this test won't pass unless locality.numCpus divides kMaxCpus
401   auto numCpus = CacheLocality::system<ManualTag>().numCpus;
402   EXPECT_EQ(0, 128 % numCpus);
403   for (size_t s = 1; s < 200; ++s) {
404     for (size_t c = 0; c < 400; ++c) {
405       testingCpu = c;
406       auto observed = AccessSpreader<ManualTag>::current(s);
407       testingCpu = c % numCpus;
408       auto expected = AccessSpreader<ManualTag>::current(s);
409       EXPECT_EQ(expected, observed)
410           << "numCpus=" << numCpus << ", s=" << s << ", c=" << c;
411     }
412   }
413 }
414
415 TEST(CoreAllocator, Basic) {
416   CoreAllocator<32> alloc;
417   auto a = alloc.get(0);
418   auto res = a->allocate(8);
419   memset(res, 0, 8);
420   a->deallocate(res);
421   res = a->allocate(8);
422   EXPECT_TRUE((intptr_t)res % 8 == 0); // check alignment
423   memset(res, 0, 8);
424   a->deallocate(res);
425   res = a->allocate(12);
426   EXPECT_TRUE((intptr_t)res % 16 == 0); // check alignment
427   memset(res, 0, 12);
428   a->deallocate(res);
429   res = a->allocate(257);
430   memset(res, 0, 257);
431   a->deallocate(res);
432
433   std::vector<void*> mems;
434   for (int i = 0; i < 10000; i++) {
435     mems.push_back(a->allocate(1));
436   }
437   for (auto& mem : mems) {
438     a->deallocate(mem);
439   }
440   mems.clear();
441 }
442
443 #endif