1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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 <memory>
20 #include <thread>
21 #include <unordered_map>
22 
23 #include <folly/portability/GTest.h>
24 #include <folly/portability/SysResource.h>
25 
26 #include <glog/logging.h>
27 
28 using namespace folly;
29 
30 /// This is the relevant nodes from a production box's sysfs tree.  If you
31 /// think this map is ugly you should see the version of this test that
32 /// used a real directory tree.  To reduce the chance of testing error
33 /// I haven't tried to remove the common prefix
34 static std::unordered_map<std::string, std::string> fakeSysfsTree = {
35     {"/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list", "0,17"},
36     {"/sys/devices/system/cpu/cpu0/cache/index0/type", "Data"},
37     {"/sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_list", "0,17"},
38     {"/sys/devices/system/cpu/cpu0/cache/index1/type", "Instruction"},
39     {"/sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_list", "0,17"},
40     {"/sys/devices/system/cpu/cpu0/cache/index2/type", "Unified"},
41     {"/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_list", "0-8,17-23"},
42     {"/sys/devices/system/cpu/cpu0/cache/index3/type", "Unified"},
43     {"/sys/devices/system/cpu/cpu1/cache/index0/shared_cpu_list", "1,18"},
44     {"/sys/devices/system/cpu/cpu1/cache/index0/type", "Data"},
45     {"/sys/devices/system/cpu/cpu1/cache/index1/shared_cpu_list", "1,18"},
46     {"/sys/devices/system/cpu/cpu1/cache/index1/type", "Instruction"},
47     {"/sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_list", "1,18"},
48     {"/sys/devices/system/cpu/cpu1/cache/index2/type", "Unified"},
49     {"/sys/devices/system/cpu/cpu1/cache/index3/shared_cpu_list", "0-8,17-23"},
50     {"/sys/devices/system/cpu/cpu1/cache/index3/type", "Unified"},
51     {"/sys/devices/system/cpu/cpu2/cache/index0/shared_cpu_list", "2,19"},
52     {"/sys/devices/system/cpu/cpu2/cache/index0/type", "Data"},
53     {"/sys/devices/system/cpu/cpu2/cache/index1/shared_cpu_list", "2,19"},
54     {"/sys/devices/system/cpu/cpu2/cache/index1/type", "Instruction"},
55     {"/sys/devices/system/cpu/cpu2/cache/index2/shared_cpu_list", "2,19"},
56     {"/sys/devices/system/cpu/cpu2/cache/index2/type", "Unified"},
57     {"/sys/devices/system/cpu/cpu2/cache/index3/shared_cpu_list", "0-8,17-23"},
58     {"/sys/devices/system/cpu/cpu2/cache/index3/type", "Unified"},
59     {"/sys/devices/system/cpu/cpu3/cache/index0/shared_cpu_list", "3,20"},
60     {"/sys/devices/system/cpu/cpu3/cache/index0/type", "Data"},
61     {"/sys/devices/system/cpu/cpu3/cache/index1/shared_cpu_list", "3,20"},
62     {"/sys/devices/system/cpu/cpu3/cache/index1/type", "Instruction"},
63     {"/sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_list", "3,20"},
64     {"/sys/devices/system/cpu/cpu3/cache/index2/type", "Unified"},
65     {"/sys/devices/system/cpu/cpu3/cache/index3/shared_cpu_list", "0-8,17-23"},
66     {"/sys/devices/system/cpu/cpu3/cache/index3/type", "Unified"},
67     {"/sys/devices/system/cpu/cpu4/cache/index0/shared_cpu_list", "4,21"},
68     {"/sys/devices/system/cpu/cpu4/cache/index0/type", "Data"},
69     {"/sys/devices/system/cpu/cpu4/cache/index1/shared_cpu_list", "4,21"},
70     {"/sys/devices/system/cpu/cpu4/cache/index1/type", "Instruction"},
71     {"/sys/devices/system/cpu/cpu4/cache/index2/shared_cpu_list", "4,21"},
72     {"/sys/devices/system/cpu/cpu4/cache/index2/type", "Unified"},
73     {"/sys/devices/system/cpu/cpu4/cache/index3/shared_cpu_list", "0-8,17-23"},
74     {"/sys/devices/system/cpu/cpu4/cache/index3/type", "Unified"},
75     {"/sys/devices/system/cpu/cpu5/cache/index0/shared_cpu_list", "5-6"},
76     {"/sys/devices/system/cpu/cpu5/cache/index0/type", "Data"},
77     {"/sys/devices/system/cpu/cpu5/cache/index1/shared_cpu_list", "5-6"},
78     {"/sys/devices/system/cpu/cpu5/cache/index1/type", "Instruction"},
79     {"/sys/devices/system/cpu/cpu5/cache/index2/shared_cpu_list", "5-6"},
80     {"/sys/devices/system/cpu/cpu5/cache/index2/type", "Unified"},
81     {"/sys/devices/system/cpu/cpu5/cache/index3/shared_cpu_list", "0-8,17-23"},
82     {"/sys/devices/system/cpu/cpu5/cache/index3/type", "Unified"},
83     {"/sys/devices/system/cpu/cpu6/cache/index0/shared_cpu_list", "5-6"},
84     {"/sys/devices/system/cpu/cpu6/cache/index0/type", "Data"},
85     {"/sys/devices/system/cpu/cpu6/cache/index1/shared_cpu_list", "5-6"},
86     {"/sys/devices/system/cpu/cpu6/cache/index1/type", "Instruction"},
87     {"/sys/devices/system/cpu/cpu6/cache/index2/shared_cpu_list", "5-6"},
88     {"/sys/devices/system/cpu/cpu6/cache/index2/type", "Unified"},
89     {"/sys/devices/system/cpu/cpu6/cache/index3/shared_cpu_list", "0-8,17-23"},
90     {"/sys/devices/system/cpu/cpu6/cache/index3/type", "Unified"},
91     {"/sys/devices/system/cpu/cpu7/cache/index0/shared_cpu_list", "7,22"},
92     {"/sys/devices/system/cpu/cpu7/cache/index0/type", "Data"},
93     {"/sys/devices/system/cpu/cpu7/cache/index1/shared_cpu_list", "7,22"},
94     {"/sys/devices/system/cpu/cpu7/cache/index1/type", "Instruction"},
95     {"/sys/devices/system/cpu/cpu7/cache/index2/shared_cpu_list", "7,22"},
96     {"/sys/devices/system/cpu/cpu7/cache/index2/type", "Unified"},
97     {"/sys/devices/system/cpu/cpu7/cache/index3/shared_cpu_list", "0-8,17-23"},
98     {"/sys/devices/system/cpu/cpu7/cache/index3/type", "Unified"},
99     {"/sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_list", "8,23"},
100     {"/sys/devices/system/cpu/cpu8/cache/index0/type", "Data"},
101     {"/sys/devices/system/cpu/cpu8/cache/index1/shared_cpu_list", "8,23"},
102     {"/sys/devices/system/cpu/cpu8/cache/index1/type", "Instruction"},
103     {"/sys/devices/system/cpu/cpu8/cache/index2/shared_cpu_list", "8,23"},
104     {"/sys/devices/system/cpu/cpu8/cache/index2/type", "Unified"},
105     {"/sys/devices/system/cpu/cpu8/cache/index3/shared_cpu_list", "0-8,17-23"},
106     {"/sys/devices/system/cpu/cpu8/cache/index3/type", "Unified"},
107     {"/sys/devices/system/cpu/cpu9/cache/index0/shared_cpu_list", "9,24"},
108     {"/sys/devices/system/cpu/cpu9/cache/index0/type", "Data"},
109     {"/sys/devices/system/cpu/cpu9/cache/index1/shared_cpu_list", "9,24"},
110     {"/sys/devices/system/cpu/cpu9/cache/index1/type", "Instruction"},
111     {"/sys/devices/system/cpu/cpu9/cache/index2/shared_cpu_list", "9,24"},
112     {"/sys/devices/system/cpu/cpu9/cache/index2/type", "Unified"},
113     {"/sys/devices/system/cpu/cpu9/cache/index3/shared_cpu_list", "9-16,24-31"},
114     {"/sys/devices/system/cpu/cpu9/cache/index3/type", "Unified"},
115     {"/sys/devices/system/cpu/cpu10/cache/index0/shared_cpu_list", "10,25"},
116     {"/sys/devices/system/cpu/cpu10/cache/index0/type", "Data"},
117     {"/sys/devices/system/cpu/cpu10/cache/index1/shared_cpu_list", "10,25"},
118     {"/sys/devices/system/cpu/cpu10/cache/index1/type", "Instruction"},
119     {"/sys/devices/system/cpu/cpu10/cache/index2/shared_cpu_list", "10,25"},
120     {"/sys/devices/system/cpu/cpu10/cache/index2/type", "Unified"},
121     {"/sys/devices/system/cpu/cpu10/cache/index3/shared_cpu_list",
122      "9-16,24-31"},
123     {"/sys/devices/system/cpu/cpu10/cache/index3/type", "Unified"},
124     {"/sys/devices/system/cpu/cpu11/cache/index0/shared_cpu_list", "11,26"},
125     {"/sys/devices/system/cpu/cpu11/cache/index0/type", "Data"},
126     {"/sys/devices/system/cpu/cpu11/cache/index1/shared_cpu_list", "11,26"},
127     {"/sys/devices/system/cpu/cpu11/cache/index1/type", "Instruction"},
128     {"/sys/devices/system/cpu/cpu11/cache/index2/shared_cpu_list", "11,26"},
129     {"/sys/devices/system/cpu/cpu11/cache/index2/type", "Unified"},
130     {"/sys/devices/system/cpu/cpu11/cache/index3/shared_cpu_list",
131      "9-16,24-31"},
132     {"/sys/devices/system/cpu/cpu11/cache/index3/type", "Unified"},
133     {"/sys/devices/system/cpu/cpu12/cache/index0/shared_cpu_list", "12,27"},
134     {"/sys/devices/system/cpu/cpu12/cache/index0/type", "Data"},
135     {"/sys/devices/system/cpu/cpu12/cache/index1/shared_cpu_list", "12,27"},
136     {"/sys/devices/system/cpu/cpu12/cache/index1/type", "Instruction"},
137     {"/sys/devices/system/cpu/cpu12/cache/index2/shared_cpu_list", "12,27"},
138     {"/sys/devices/system/cpu/cpu12/cache/index2/type", "Unified"},
139     {"/sys/devices/system/cpu/cpu12/cache/index3/shared_cpu_list",
140      "9-16,24-31"},
141     {"/sys/devices/system/cpu/cpu12/cache/index3/type", "Unified"},
142     {"/sys/devices/system/cpu/cpu13/cache/index0/shared_cpu_list", "13,28"},
143     {"/sys/devices/system/cpu/cpu13/cache/index0/type", "Data"},
144     {"/sys/devices/system/cpu/cpu13/cache/index1/shared_cpu_list", "13,28"},
145     {"/sys/devices/system/cpu/cpu13/cache/index1/type", "Instruction"},
146     {"/sys/devices/system/cpu/cpu13/cache/index2/shared_cpu_list", "13,28"},
147     {"/sys/devices/system/cpu/cpu13/cache/index2/type", "Unified"},
148     {"/sys/devices/system/cpu/cpu13/cache/index3/shared_cpu_list",
149      "9-16,24-31"},
150     {"/sys/devices/system/cpu/cpu13/cache/index3/type", "Unified"},
151     {"/sys/devices/system/cpu/cpu14/cache/index0/shared_cpu_list", "14,29"},
152     {"/sys/devices/system/cpu/cpu14/cache/index0/type", "Data"},
153     {"/sys/devices/system/cpu/cpu14/cache/index1/shared_cpu_list", "14,29"},
154     {"/sys/devices/system/cpu/cpu14/cache/index1/type", "Instruction"},
155     {"/sys/devices/system/cpu/cpu14/cache/index2/shared_cpu_list", "14,29"},
156     {"/sys/devices/system/cpu/cpu14/cache/index2/type", "Unified"},
157     {"/sys/devices/system/cpu/cpu14/cache/index3/shared_cpu_list",
158      "9-16,24-31"},
159     {"/sys/devices/system/cpu/cpu14/cache/index3/type", "Unified"},
160     {"/sys/devices/system/cpu/cpu15/cache/index0/shared_cpu_list", "15,30"},
161     {"/sys/devices/system/cpu/cpu15/cache/index0/type", "Data"},
162     {"/sys/devices/system/cpu/cpu15/cache/index1/shared_cpu_list", "15,30"},
163     {"/sys/devices/system/cpu/cpu15/cache/index1/type", "Instruction"},
164     {"/sys/devices/system/cpu/cpu15/cache/index2/shared_cpu_list", "15,30"},
165     {"/sys/devices/system/cpu/cpu15/cache/index2/type", "Unified"},
166     {"/sys/devices/system/cpu/cpu15/cache/index3/shared_cpu_list",
167      "9-16,24-31"},
168     {"/sys/devices/system/cpu/cpu15/cache/index3/type", "Unified"},
169     {"/sys/devices/system/cpu/cpu16/cache/index0/shared_cpu_list", "16,31"},
170     {"/sys/devices/system/cpu/cpu16/cache/index0/type", "Data"},
171     {"/sys/devices/system/cpu/cpu16/cache/index1/shared_cpu_list", "16,31"},
172     {"/sys/devices/system/cpu/cpu16/cache/index1/type", "Instruction"},
173     {"/sys/devices/system/cpu/cpu16/cache/index2/shared_cpu_list", "16,31"},
174     {"/sys/devices/system/cpu/cpu16/cache/index2/type", "Unified"},
175     {"/sys/devices/system/cpu/cpu16/cache/index3/shared_cpu_list",
176      "9-16,24-31"},
177     {"/sys/devices/system/cpu/cpu16/cache/index3/type", "Unified"},
178     {"/sys/devices/system/cpu/cpu17/cache/index0/shared_cpu_list", "0,17"},
179     {"/sys/devices/system/cpu/cpu17/cache/index0/type", "Data"},
180     {"/sys/devices/system/cpu/cpu17/cache/index1/shared_cpu_list", "0,17"},
181     {"/sys/devices/system/cpu/cpu17/cache/index1/type", "Instruction"},
182     {"/sys/devices/system/cpu/cpu17/cache/index2/shared_cpu_list", "0,17"},
183     {"/sys/devices/system/cpu/cpu17/cache/index2/type", "Unified"},
184     {"/sys/devices/system/cpu/cpu17/cache/index3/shared_cpu_list", "0-8,17-23"},
185     {"/sys/devices/system/cpu/cpu17/cache/index3/type", "Unified"},
186     {"/sys/devices/system/cpu/cpu18/cache/index0/shared_cpu_list", "1,18"},
187     {"/sys/devices/system/cpu/cpu18/cache/index0/type", "Data"},
188     {"/sys/devices/system/cpu/cpu18/cache/index1/shared_cpu_list", "1,18"},
189     {"/sys/devices/system/cpu/cpu18/cache/index1/type", "Instruction"},
190     {"/sys/devices/system/cpu/cpu18/cache/index2/shared_cpu_list", "1,18"},
191     {"/sys/devices/system/cpu/cpu18/cache/index2/type", "Unified"},
192     {"/sys/devices/system/cpu/cpu18/cache/index3/shared_cpu_list", "0-8,17-23"},
193     {"/sys/devices/system/cpu/cpu18/cache/index3/type", "Unified"},
194     {"/sys/devices/system/cpu/cpu19/cache/index0/shared_cpu_list", "2,19"},
195     {"/sys/devices/system/cpu/cpu19/cache/index0/type", "Data"},
196     {"/sys/devices/system/cpu/cpu19/cache/index1/shared_cpu_list", "2,19"},
197     {"/sys/devices/system/cpu/cpu19/cache/index1/type", "Instruction"},
198     {"/sys/devices/system/cpu/cpu19/cache/index2/shared_cpu_list", "2,19"},
199     {"/sys/devices/system/cpu/cpu19/cache/index2/type", "Unified"},
200     {"/sys/devices/system/cpu/cpu19/cache/index3/shared_cpu_list", "0-8,17-23"},
201     {"/sys/devices/system/cpu/cpu19/cache/index3/type", "Unified"},
202     {"/sys/devices/system/cpu/cpu20/cache/index0/shared_cpu_list", "3,20"},
203     {"/sys/devices/system/cpu/cpu20/cache/index0/type", "Data"},
204     {"/sys/devices/system/cpu/cpu20/cache/index1/shared_cpu_list", "3,20"},
205     {"/sys/devices/system/cpu/cpu20/cache/index1/type", "Instruction"},
206     {"/sys/devices/system/cpu/cpu20/cache/index2/shared_cpu_list", "3,20"},
207     {"/sys/devices/system/cpu/cpu20/cache/index2/type", "Unified"},
208     {"/sys/devices/system/cpu/cpu20/cache/index3/shared_cpu_list", "0-8,17-23"},
209     {"/sys/devices/system/cpu/cpu20/cache/index3/type", "Unified"},
210     {"/sys/devices/system/cpu/cpu21/cache/index0/shared_cpu_list", "4,21"},
211     {"/sys/devices/system/cpu/cpu21/cache/index0/type", "Data"},
212     {"/sys/devices/system/cpu/cpu21/cache/index1/shared_cpu_list", "4,21"},
213     {"/sys/devices/system/cpu/cpu21/cache/index1/type", "Instruction"},
214     {"/sys/devices/system/cpu/cpu21/cache/index2/shared_cpu_list", "4,21"},
215     {"/sys/devices/system/cpu/cpu21/cache/index2/type", "Unified"},
216     {"/sys/devices/system/cpu/cpu21/cache/index3/shared_cpu_list", "0-8,17-23"},
217     {"/sys/devices/system/cpu/cpu21/cache/index3/type", "Unified"},
218     {"/sys/devices/system/cpu/cpu22/cache/index0/shared_cpu_list", "7,22"},
219     {"/sys/devices/system/cpu/cpu22/cache/index0/type", "Data"},
220     {"/sys/devices/system/cpu/cpu22/cache/index1/shared_cpu_list", "7,22"},
221     {"/sys/devices/system/cpu/cpu22/cache/index1/type", "Instruction"},
222     {"/sys/devices/system/cpu/cpu22/cache/index2/shared_cpu_list", "7,22"},
223     {"/sys/devices/system/cpu/cpu22/cache/index2/type", "Unified"},
224     {"/sys/devices/system/cpu/cpu22/cache/index3/shared_cpu_list", "0-8,17-23"},
225     {"/sys/devices/system/cpu/cpu22/cache/index3/type", "Unified"},
226     {"/sys/devices/system/cpu/cpu23/cache/index0/shared_cpu_list", "8,23"},
227     {"/sys/devices/system/cpu/cpu23/cache/index0/type", "Data"},
228     {"/sys/devices/system/cpu/cpu23/cache/index1/shared_cpu_list", "8,23"},
229     {"/sys/devices/system/cpu/cpu23/cache/index1/type", "Instruction"},
230     {"/sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_list", "8,23"},
231     {"/sys/devices/system/cpu/cpu23/cache/index2/type", "Unified"},
232     {"/sys/devices/system/cpu/cpu23/cache/index3/shared_cpu_list", "0-8,17-23"},
233     {"/sys/devices/system/cpu/cpu23/cache/index3/type", "Unified"},
234     {"/sys/devices/system/cpu/cpu24/cache/index0/shared_cpu_list", "9,24"},
235     {"/sys/devices/system/cpu/cpu24/cache/index0/type", "Data"},
236     {"/sys/devices/system/cpu/cpu24/cache/index1/shared_cpu_list", "9,24"},
237     {"/sys/devices/system/cpu/cpu24/cache/index1/type", "Instruction"},
238     {"/sys/devices/system/cpu/cpu24/cache/index2/shared_cpu_list", "9,24"},
239     {"/sys/devices/system/cpu/cpu24/cache/index2/type", "Unified"},
240     {"/sys/devices/system/cpu/cpu24/cache/index3/shared_cpu_list",
241      "9-16,24-31"},
242     {"/sys/devices/system/cpu/cpu24/cache/index3/type", "Unified"},
243     {"/sys/devices/system/cpu/cpu25/cache/index0/shared_cpu_list", "10,25"},
244     {"/sys/devices/system/cpu/cpu25/cache/index0/type", "Data"},
245     {"/sys/devices/system/cpu/cpu25/cache/index1/shared_cpu_list", "10,25"},
246     {"/sys/devices/system/cpu/cpu25/cache/index1/type", "Instruction"},
247     {"/sys/devices/system/cpu/cpu25/cache/index2/shared_cpu_list", "10,25"},
248     {"/sys/devices/system/cpu/cpu25/cache/index2/type", "Unified"},
249     {"/sys/devices/system/cpu/cpu25/cache/index3/shared_cpu_list",
250      "9-16,24-31"},
251     {"/sys/devices/system/cpu/cpu25/cache/index3/type", "Unified"},
252     {"/sys/devices/system/cpu/cpu26/cache/index0/shared_cpu_list", "11,26"},
253     {"/sys/devices/system/cpu/cpu26/cache/index0/type", "Data"},
254     {"/sys/devices/system/cpu/cpu26/cache/index1/shared_cpu_list", "11,26"},
255     {"/sys/devices/system/cpu/cpu26/cache/index1/type", "Instruction"},
256     {"/sys/devices/system/cpu/cpu26/cache/index2/shared_cpu_list", "11,26"},
257     {"/sys/devices/system/cpu/cpu26/cache/index2/type", "Unified"},
258     {"/sys/devices/system/cpu/cpu26/cache/index3/shared_cpu_list",
259      "9-16,24-31"},
260     {"/sys/devices/system/cpu/cpu26/cache/index3/type", "Unified"},
261     {"/sys/devices/system/cpu/cpu27/cache/index0/shared_cpu_list", "12,27"},
262     {"/sys/devices/system/cpu/cpu27/cache/index0/type", "Data"},
263     {"/sys/devices/system/cpu/cpu27/cache/index1/shared_cpu_list", "12,27"},
264     {"/sys/devices/system/cpu/cpu27/cache/index1/type", "Instruction"},
265     {"/sys/devices/system/cpu/cpu27/cache/index2/shared_cpu_list", "12,27"},
266     {"/sys/devices/system/cpu/cpu27/cache/index2/type", "Unified"},
267     {"/sys/devices/system/cpu/cpu27/cache/index3/shared_cpu_list",
268      "9-16,24-31"},
269     {"/sys/devices/system/cpu/cpu27/cache/index3/type", "Unified"},
270     {"/sys/devices/system/cpu/cpu28/cache/index0/shared_cpu_list", "13,28"},
271     {"/sys/devices/system/cpu/cpu28/cache/index0/type", "Data"},
272     {"/sys/devices/system/cpu/cpu28/cache/index1/shared_cpu_list", "13,28"},
273     {"/sys/devices/system/cpu/cpu28/cache/index1/type", "Instruction"},
274     {"/sys/devices/system/cpu/cpu28/cache/index2/shared_cpu_list", "13,28"},
275     {"/sys/devices/system/cpu/cpu28/cache/index2/type", "Unified"},
276     {"/sys/devices/system/cpu/cpu28/cache/index3/shared_cpu_list",
277      "9-16,24-31"},
278     {"/sys/devices/system/cpu/cpu28/cache/index3/type", "Unified"},
279     {"/sys/devices/system/cpu/cpu29/cache/index0/shared_cpu_list", "14,29"},
280     {"/sys/devices/system/cpu/cpu29/cache/index0/type", "Data"},
281     {"/sys/devices/system/cpu/cpu29/cache/index1/shared_cpu_list", "14,29"},
282     {"/sys/devices/system/cpu/cpu29/cache/index1/type", "Instruction"},
283     {"/sys/devices/system/cpu/cpu29/cache/index2/shared_cpu_list", "14,29"},
284     {"/sys/devices/system/cpu/cpu29/cache/index2/type", "Unified"},
285     {"/sys/devices/system/cpu/cpu29/cache/index3/shared_cpu_list",
286      "9-16,24-31"},
287     {"/sys/devices/system/cpu/cpu29/cache/index3/type", "Unified"},
288     {"/sys/devices/system/cpu/cpu30/cache/index0/shared_cpu_list", "15,30"},
289     {"/sys/devices/system/cpu/cpu30/cache/index0/type", "Data"},
290     {"/sys/devices/system/cpu/cpu30/cache/index1/shared_cpu_list", "15,30"},
291     {"/sys/devices/system/cpu/cpu30/cache/index1/type", "Instruction"},
292     {"/sys/devices/system/cpu/cpu30/cache/index2/shared_cpu_list", "15,30"},
293     {"/sys/devices/system/cpu/cpu30/cache/index2/type", "Unified"},
294     {"/sys/devices/system/cpu/cpu30/cache/index3/shared_cpu_list",
295      "9-16,24-31"},
296     {"/sys/devices/system/cpu/cpu30/cache/index3/type", "Unified"},
297     {"/sys/devices/system/cpu/cpu31/cache/index0/shared_cpu_list", "16,31"},
298     {"/sys/devices/system/cpu/cpu31/cache/index0/type", "Data"},
299     {"/sys/devices/system/cpu/cpu31/cache/index1/shared_cpu_list", "16,31"},
300     {"/sys/devices/system/cpu/cpu31/cache/index1/type", "Instruction"},
301     {"/sys/devices/system/cpu/cpu31/cache/index2/shared_cpu_list", "16,31"},
302     {"/sys/devices/system/cpu/cpu31/cache/index2/type", "Unified"},
303     {"/sys/devices/system/cpu/cpu31/cache/index3/shared_cpu_list",
304      "9-16,24-31"},
305     {"/sys/devices/system/cpu/cpu31/cache/index3/type", "Unified"}};
306 
307 /// This is the expected CacheLocality structure for fakeSysfsTree
308 static const CacheLocality nonUniformExampleLocality = {
309     32, {16, 16, 2}, {0,  2,  4,  6,  8,  10, 11, 12, 14, 16, 18,
310                       20, 22, 24, 26, 28, 30, 1,  3,  5,  7,  9,
311                       13, 15, 17, 19, 21, 23, 25, 27, 29, 31}};
312 
TEST(CacheLocality,FakeSysfs)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 static const std::vector<std::string> fakeProcCpuinfo = {
326     "processor	: 0",
327     "vendor_id	: GenuineIntel",
328     "cpu family	: 6",
329     "model		: 79",
330     "model name	: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz",
331     "stepping	: 1",
332     "microcode	: 0xb00001b",
333     "cpu MHz		: 2401.000",
334     "cache size	: 35840 KB",
335     "physical id	: 0",
336     "siblings	: 28",
337     "core id		: 0",
338     "cpu cores	: 14",
339     "apicid		: 0",
340     "initial apicid	: 0",
341     "fpu		: yes",
342     "fpu_exception	: yes",
343     "cpuid level	: 20",
344     "wp		: yes",
345     "flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts",
346     "bugs		:",
347     "bogomips	: 4788.90",
348     "clflush size	: 64",
349     "cache_alignment	: 64",
350     "address sizes	: 46 bits physical, 48 bits virtual",
351     "power management:",
352     "",
353     "processor	: 1",
354     "cpu family	: 6",
355     "cpu MHz		: 2401.000",
356     "cache size	: 35840 KB",
357     "physical id	: 0",
358     "core id		: 1",
359     "cpu cores	: 14",
360     "cpuid level	: 20",
361     "clflush size	: 64",
362     "cache_alignment	: 64",
363     "power management:",
364     "processor	: 2",
365     "cpu family	: 6",
366     "cpu MHz		: 2401.000",
367     "cache size	: 35840 KB",
368     "physical id	: 0",
369     "core id		: 2",
370     "cpu cores	: 14",
371     "cpuid level	: 20",
372     "clflush size	: 64",
373     "cache_alignment	: 64",
374     "power management:",
375     "processor	: 3",
376     "cpu family	: 6",
377     "cpu MHz		: 2401.000",
378     "cache size	: 35840 KB",
379     "physical id	: 0",
380     "core id		: 3",
381     "cpu cores	: 14",
382     "cpuid level	: 20",
383     "clflush size	: 64",
384     "cache_alignment	: 64",
385     "power management:",
386     "processor	: 4",
387     "cpu family	: 6",
388     "cpu MHz		: 2401.000",
389     "cache size	: 35840 KB",
390     "physical id	: 0",
391     "core id		: 4",
392     "cpu cores	: 14",
393     "cpuid level	: 20",
394     "clflush size	: 64",
395     "cache_alignment	: 64",
396     "power management:",
397     "processor	: 5",
398     "cpu family	: 6",
399     "cpu MHz		: 2401.000",
400     "cache size	: 35840 KB",
401     "physical id	: 0",
402     "core id		: 5",
403     "cpu cores	: 14",
404     "cpuid level	: 20",
405     "clflush size	: 64",
406     "cache_alignment	: 64",
407     "power management:",
408     "processor	: 6",
409     "cpu family	: 6",
410     "cpu MHz		: 2401.000",
411     "cache size	: 35840 KB",
412     "physical id	: 0",
413     "core id		: 6",
414     "cpu cores	: 14",
415     "cpuid level	: 20",
416     "clflush size	: 64",
417     "cache_alignment	: 64",
418     "power management:",
419     "processor	: 7",
420     "cpu family	: 6",
421     "cpu MHz		: 2401.000",
422     "cache size	: 35840 KB",
423     "physical id	: 0",
424     "core id		: 8",
425     "cpu cores	: 14",
426     "cpuid level	: 20",
427     "clflush size	: 64",
428     "cache_alignment	: 64",
429     "power management:",
430     "processor	: 8",
431     "cpu family	: 6",
432     "cpu MHz		: 2401.000",
433     "cache size	: 35840 KB",
434     "physical id	: 0",
435     "core id		: 9",
436     "cpu cores	: 14",
437     "cpuid level	: 20",
438     "clflush size	: 64",
439     "cache_alignment	: 64",
440     "power management:",
441     "processor	: 9",
442     "cpu family	: 6",
443     "cpu MHz		: 2401.000",
444     "cache size	: 35840 KB",
445     "physical id	: 0",
446     "core id		: 10",
447     "cpu cores	: 14",
448     "cpuid level	: 20",
449     "clflush size	: 64",
450     "cache_alignment	: 64",
451     "power management:",
452     "processor	: 10",
453     "cpu family	: 6",
454     "cpu MHz		: 2401.000",
455     "cache size	: 35840 KB",
456     "physical id	: 0",
457     "core id		: 11",
458     "cpu cores	: 14",
459     "cpuid level	: 20",
460     "clflush size	: 64",
461     "cache_alignment	: 64",
462     "power management:",
463     "processor	: 11",
464     "cpu family	: 6",
465     "cpu MHz		: 2401.000",
466     "cache size	: 35840 KB",
467     "physical id	: 0",
468     "core id		: 12",
469     "cpu cores	: 14",
470     "cpuid level	: 20",
471     "clflush size	: 64",
472     "cache_alignment	: 64",
473     "power management:",
474     "processor	: 12",
475     "cpu family	: 6",
476     "cpu MHz		: 2401.000",
477     "cache size	: 35840 KB",
478     "physical id	: 0",
479     "core id		: 13",
480     "cpu cores	: 14",
481     "cpuid level	: 20",
482     "clflush size	: 64",
483     "cache_alignment	: 64",
484     "power management:",
485     "processor	: 13",
486     "cpu family	: 6",
487     "cpu MHz		: 2401.000",
488     "cache size	: 35840 KB",
489     "physical id	: 0",
490     "core id		: 14",
491     "cpu cores	: 14",
492     "cpuid level	: 20",
493     "clflush size	: 64",
494     "cache_alignment	: 64",
495     "power management:",
496     "processor	: 14",
497     "cpu family	: 6",
498     "cpu MHz		: 2401.000",
499     "cache size	: 35840 KB",
500     "physical id	: 1",
501     "core id		: 0",
502     "cpu cores	: 14",
503     "cpuid level	: 20",
504     "clflush size	: 64",
505     "cache_alignment	: 64",
506     "power management:",
507     "processor	: 15",
508     "cpu family	: 6",
509     "cpu MHz		: 2401.000",
510     "cache size	: 35840 KB",
511     "physical id	: 1",
512     "core id		: 1",
513     "cpu cores	: 14",
514     "cpuid level	: 20",
515     "clflush size	: 64",
516     "cache_alignment	: 64",
517     "power management:",
518     "processor	: 16",
519     "cpu family	: 6",
520     "cpu MHz		: 2401.000",
521     "cache size	: 35840 KB",
522     "physical id	: 1",
523     "core id		: 2",
524     "cpu cores	: 14",
525     "cpuid level	: 20",
526     "clflush size	: 64",
527     "cache_alignment	: 64",
528     "power management:",
529     "processor	: 17",
530     "cpu family	: 6",
531     "cpu MHz		: 2401.000",
532     "cache size	: 35840 KB",
533     "physical id	: 1",
534     "core id		: 3",
535     "cpu cores	: 14",
536     "cpuid level	: 20",
537     "clflush size	: 64",
538     "cache_alignment	: 64",
539     "power management:",
540     "processor	: 18",
541     "cpu family	: 6",
542     "cpu MHz		: 2401.000",
543     "cache size	: 35840 KB",
544     "physical id	: 1",
545     "core id		: 4",
546     "cpu cores	: 14",
547     "cpuid level	: 20",
548     "clflush size	: 64",
549     "cache_alignment	: 64",
550     "power management:",
551     "processor	: 19",
552     "cpu family	: 6",
553     "cpu MHz		: 2401.000",
554     "cache size	: 35840 KB",
555     "physical id	: 1",
556     "core id		: 5",
557     "cpu cores	: 14",
558     "cpuid level	: 20",
559     "clflush size	: 64",
560     "cache_alignment	: 64",
561     "power management:",
562     "processor	: 20",
563     "cpu family	: 6",
564     "cpu MHz		: 2401.000",
565     "cache size	: 35840 KB",
566     "physical id	: 1",
567     "core id		: 6",
568     "cpu cores	: 14",
569     "cpuid level	: 20",
570     "clflush size	: 64",
571     "cache_alignment	: 64",
572     "power management:",
573     "processor	: 21",
574     "cpu family	: 6",
575     "cpu MHz		: 2401.000",
576     "cache size	: 35840 KB",
577     "physical id	: 1",
578     "core id		: 8",
579     "cpu cores	: 14",
580     "cpuid level	: 20",
581     "clflush size	: 64",
582     "cache_alignment	: 64",
583     "power management:",
584     "processor	: 22",
585     "cpu family	: 6",
586     "cpu MHz		: 2401.000",
587     "cache size	: 35840 KB",
588     "physical id	: 1",
589     "core id		: 9",
590     "cpu cores	: 14",
591     "cpuid level	: 20",
592     "clflush size	: 64",
593     "cache_alignment	: 64",
594     "power management:",
595     "processor	: 23",
596     "cpu family	: 6",
597     "cpu MHz		: 2401.000",
598     "cache size	: 35840 KB",
599     "physical id	: 1",
600     "core id		: 10",
601     "cpu cores	: 14",
602     "cpuid level	: 20",
603     "clflush size	: 64",
604     "cache_alignment	: 64",
605     "power management:",
606     "processor	: 24",
607     "cpu family	: 6",
608     "cpu MHz		: 2401.000",
609     "cache size	: 35840 KB",
610     "physical id	: 1",
611     "core id		: 11",
612     "cpu cores	: 14",
613     "cpuid level	: 20",
614     "clflush size	: 64",
615     "cache_alignment	: 64",
616     "power management:",
617     "processor	: 25",
618     "cpu family	: 6",
619     "cpu MHz		: 2401.000",
620     "cache size	: 35840 KB",
621     "physical id	: 1",
622     "core id		: 12",
623     "cpu cores	: 14",
624     "cpuid level	: 20",
625     "clflush size	: 64",
626     "cache_alignment	: 64",
627     "power management:",
628     "processor	: 26",
629     "cpu family	: 6",
630     "cpu MHz		: 2401.000",
631     "cache size	: 35840 KB",
632     "physical id	: 1",
633     "core id		: 13",
634     "cpu cores	: 14",
635     "cpuid level	: 20",
636     "clflush size	: 64",
637     "cache_alignment	: 64",
638     "power management:",
639     "processor	: 27",
640     "cpu family	: 6",
641     "cpu MHz		: 2401.000",
642     "cache size	: 35840 KB",
643     "physical id	: 1",
644     "core id		: 14",
645     "cpu cores	: 14",
646     "cpuid level	: 20",
647     "clflush size	: 64",
648     "cache_alignment	: 64",
649     "power management:",
650     "processor	: 28",
651     "cpu family	: 6",
652     "cpu MHz		: 2401.000",
653     "cache size	: 35840 KB",
654     "physical id	: 0",
655     "core id		: 0",
656     "cpu cores	: 14",
657     "cpuid level	: 20",
658     "clflush size	: 64",
659     "cache_alignment	: 64",
660     "power management:",
661     "processor	: 29",
662     "cpu family	: 6",
663     "cpu MHz		: 2401.000",
664     "cache size	: 35840 KB",
665     "physical id	: 0",
666     "core id		: 1",
667     "cpu cores	: 14",
668     "cpuid level	: 20",
669     "clflush size	: 64",
670     "cache_alignment	: 64",
671     "power management:",
672     "processor	: 30",
673     "cpu family	: 6",
674     "cpu MHz		: 2401.000",
675     "cache size	: 35840 KB",
676     "physical id	: 0",
677     "core id		: 2",
678     "cpu cores	: 14",
679     "cpuid level	: 20",
680     "clflush size	: 64",
681     "cache_alignment	: 64",
682     "power management:",
683     "processor	: 31",
684     "cpu family	: 6",
685     "cpu MHz		: 2401.000",
686     "cache size	: 35840 KB",
687     "physical id	: 0",
688     "core id		: 3",
689     "cpu cores	: 14",
690     "cpuid level	: 20",
691     "clflush size	: 64",
692     "cache_alignment	: 64",
693     "power management:",
694     "processor	: 32",
695     "cpu family	: 6",
696     "cpu MHz		: 2401.000",
697     "cache size	: 35840 KB",
698     "physical id	: 0",
699     "core id		: 4",
700     "cpu cores	: 14",
701     "cpuid level	: 20",
702     "clflush size	: 64",
703     "cache_alignment	: 64",
704     "power management:",
705     "processor	: 33",
706     "cpu family	: 6",
707     "cpu MHz		: 2401.000",
708     "cache size	: 35840 KB",
709     "physical id	: 0",
710     "core id		: 5",
711     "cpu cores	: 14",
712     "cpuid level	: 20",
713     "clflush size	: 64",
714     "cache_alignment	: 64",
715     "power management:",
716     "processor	: 34",
717     "cpu family	: 6",
718     "cpu MHz		: 2401.000",
719     "cache size	: 35840 KB",
720     "physical id	: 0",
721     "core id		: 6",
722     "cpu cores	: 14",
723     "cpuid level	: 20",
724     "clflush size	: 64",
725     "cache_alignment	: 64",
726     "power management:",
727     "processor	: 35",
728     "cpu family	: 6",
729     "cpu MHz		: 2401.000",
730     "cache size	: 35840 KB",
731     "physical id	: 0",
732     "core id		: 8",
733     "cpu cores	: 14",
734     "cpuid level	: 20",
735     "clflush size	: 64",
736     "cache_alignment	: 64",
737     "power management:",
738     "processor	: 36",
739     "cpu family	: 6",
740     "cpu MHz		: 2401.000",
741     "cache size	: 35840 KB",
742     "physical id	: 0",
743     "core id		: 9",
744     "cpu cores	: 14",
745     "cpuid level	: 20",
746     "clflush size	: 64",
747     "cache_alignment	: 64",
748     "power management:",
749     "processor	: 37",
750     "cpu family	: 6",
751     "cpu MHz		: 2401.000",
752     "cache size	: 35840 KB",
753     "physical id	: 0",
754     "core id		: 10",
755     "cpu cores	: 14",
756     "cpuid level	: 20",
757     "clflush size	: 64",
758     "cache_alignment	: 64",
759     "power management:",
760     "processor	: 38",
761     "cpu family	: 6",
762     "cpu MHz		: 2401.000",
763     "cache size	: 35840 KB",
764     "physical id	: 0",
765     "core id		: 11",
766     "cpu cores	: 14",
767     "cpuid level	: 20",
768     "clflush size	: 64",
769     "cache_alignment	: 64",
770     "power management:",
771     "processor	: 39",
772     "cpu family	: 6",
773     "cpu MHz		: 2401.000",
774     "cache size	: 35840 KB",
775     "physical id	: 0",
776     "core id		: 12",
777     "cpu cores	: 14",
778     "cpuid level	: 20",
779     "clflush size	: 64",
780     "cache_alignment	: 64",
781     "power management:",
782     "processor	: 40",
783     "cpu family	: 6",
784     "cpu MHz		: 2401.000",
785     "cache size	: 35840 KB",
786     "physical id	: 0",
787     "core id		: 13",
788     "cpu cores	: 14",
789     "cpuid level	: 20",
790     "clflush size	: 64",
791     "cache_alignment	: 64",
792     "power management:",
793     "processor	: 41",
794     "cpu family	: 6",
795     "cpu MHz		: 2401.000",
796     "cache size	: 35840 KB",
797     "physical id	: 0",
798     "core id		: 14",
799     "cpu cores	: 14",
800     "cpuid level	: 20",
801     "clflush size	: 64",
802     "cache_alignment	: 64",
803     "power management:",
804     "processor	: 42",
805     "cpu family	: 6",
806     "cpu MHz		: 2401.000",
807     "cache size	: 35840 KB",
808     "physical id	: 1",
809     "core id		: 0",
810     "cpu cores	: 14",
811     "cpuid level	: 20",
812     "clflush size	: 64",
813     "cache_alignment	: 64",
814     "power management:",
815     "processor	: 43",
816     "cpu family	: 6",
817     "cpu MHz		: 2401.000",
818     "cache size	: 35840 KB",
819     "physical id	: 1",
820     "core id		: 1",
821     "cpu cores	: 14",
822     "cpuid level	: 20",
823     "clflush size	: 64",
824     "cache_alignment	: 64",
825     "power management:",
826     "processor	: 44",
827     "cpu family	: 6",
828     "cpu MHz		: 2401.000",
829     "cache size	: 35840 KB",
830     "physical id	: 1",
831     "core id		: 2",
832     "cpu cores	: 14",
833     "cpuid level	: 20",
834     "clflush size	: 64",
835     "cache_alignment	: 64",
836     "power management:",
837     "processor	: 45",
838     "cpu family	: 6",
839     "cpu MHz		: 2401.000",
840     "cache size	: 35840 KB",
841     "physical id	: 1",
842     "core id		: 3",
843     "cpu cores	: 14",
844     "cpuid level	: 20",
845     "clflush size	: 64",
846     "cache_alignment	: 64",
847     "power management:",
848     "processor	: 46",
849     "cpu family	: 6",
850     "cpu MHz		: 2401.000",
851     "cache size	: 35840 KB",
852     "physical id	: 1",
853     "core id		: 4",
854     "cpu cores	: 14",
855     "cpuid level	: 20",
856     "clflush size	: 64",
857     "cache_alignment	: 64",
858     "power management:",
859     "processor	: 47",
860     "cpu family	: 6",
861     "cpu MHz		: 2401.000",
862     "cache size	: 35840 KB",
863     "physical id	: 1",
864     "core id		: 5",
865     "cpu cores	: 14",
866     "cpuid level	: 20",
867     "clflush size	: 64",
868     "cache_alignment	: 64",
869     "power management:",
870     "processor	: 48",
871     "cpu family	: 6",
872     "cpu MHz		: 2401.000",
873     "cache size	: 35840 KB",
874     "physical id	: 1",
875     "core id		: 6",
876     "cpu cores	: 14",
877     "cpuid level	: 20",
878     "clflush size	: 64",
879     "cache_alignment	: 64",
880     "power management:",
881     "processor	: 49",
882     "cpu family	: 6",
883     "cpu MHz		: 2401.000",
884     "cache size	: 35840 KB",
885     "physical id	: 1",
886     "core id		: 8",
887     "cpu cores	: 14",
888     "cpuid level	: 20",
889     "clflush size	: 64",
890     "cache_alignment	: 64",
891     "power management:",
892     "processor	: 50",
893     "cpu family	: 6",
894     "cpu MHz		: 2401.000",
895     "cache size	: 35840 KB",
896     "physical id	: 1",
897     "core id		: 9",
898     "cpu cores	: 14",
899     "cpuid level	: 20",
900     "clflush size	: 64",
901     "cache_alignment	: 64",
902     "power management:",
903     "processor	: 51",
904     "cpu family	: 6",
905     "cpu MHz		: 2401.000",
906     "cache size	: 35840 KB",
907     "physical id	: 1",
908     "core id		: 10",
909     "cpu cores	: 14",
910     "cpuid level	: 20",
911     "clflush size	: 64",
912     "cache_alignment	: 64",
913     "power management:",
914     "processor	: 52",
915     "cpu family	: 6",
916     "cpu MHz		: 2401.000",
917     "cache size	: 35840 KB",
918     "physical id	: 1",
919     "core id		: 11",
920     "cpu cores	: 14",
921     "cpuid level	: 20",
922     "clflush size	: 64",
923     "cache_alignment	: 64",
924     "power management:",
925     "processor	: 53",
926     "cpu family	: 6",
927     "cpu MHz		: 2401.000",
928     "cache size	: 35840 KB",
929     "physical id	: 1",
930     "core id		: 12",
931     "cpu cores	: 14",
932     "cpuid level	: 20",
933     "clflush size	: 64",
934     "cache_alignment	: 64",
935     "power management:",
936     "processor	: 54",
937     "cpu family	: 6",
938     "cpu MHz		: 2401.000",
939     "cache size	: 35840 KB",
940     "physical id	: 1",
941     "core id		: 13",
942     "cpu cores	: 14",
943     "cpuid level	: 20",
944     "clflush size	: 64",
945     "cache_alignment	: 64",
946     "power management:",
947     "processor	: 55",
948     "cpu family	: 6",
949     "cpu MHz		: 2401.000",
950     "cache size	: 35840 KB",
951     "physical id	: 1",
952     "core id		: 14",
953     "cpu cores	: 14",
954     "cpuid level	: 20",
955     "clflush size	: 64",
956     "cache_alignment	: 64",
957     "power management:",
958 };
959 
960 /// This is the expected CacheLocality structure for fakeProcCpuinfo
961 static const CacheLocality fakeProcCpuinfoLocality = {
962     56, {28, 28, 2}, {0,  2,  4,  6,  8,  10, 12, 14, 16, 18, 20, 22, 24, 26,
963                       28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
964                       1,  3,  5,  7,  9,  11, 13, 15, 17, 19, 21, 23, 25, 27,
965                       29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55}};
966 
TEST(CacheLocality,ProcCpu)967 TEST(CacheLocality, ProcCpu) {
968   auto parsed = CacheLocality::readFromProcCpuinfoLines(fakeProcCpuinfo);
969   auto& expected = fakeProcCpuinfoLocality;
970   EXPECT_EQ(expected.numCpus, parsed.numCpus);
971   EXPECT_EQ(expected.numCachesByLevel, parsed.numCachesByLevel);
972   EXPECT_EQ(expected.localityIndexByCpu, parsed.localityIndexByCpu);
973 }
974 
TEST(CacheLocality,LinuxActual)975 TEST(CacheLocality, LinuxActual) {
976   if (!kIsLinux) {
977     return;
978   }
979 
980   auto parsed1 = CacheLocality::readFromProcCpuinfo();
981   EXPECT_EQ(parsed1.numCpus, std::thread::hardware_concurrency());
982 
983   auto parsed2 = CacheLocality::readFromSysfs();
984   EXPECT_EQ(parsed2.numCpus, std::thread::hardware_concurrency());
985 
986   EXPECT_EQ(parsed1.localityIndexByCpu, parsed2.localityIndexByCpu);
987 }
988 
TEST(CacheLocality,LogSystem)989 TEST(CacheLocality, LogSystem) {
990   auto& sys = CacheLocality::system<>();
991   LOG(INFO) << "numCpus= " << sys.numCpus;
992   LOG(INFO) << "numCachesByLevel= ";
993   for (std::size_t i = 0; i < sys.numCachesByLevel.size(); ++i) {
994     LOG(INFO) << "  [" << i << "]= " << sys.numCachesByLevel[i];
995   }
996   LOG(INFO) << "localityIndexByCpu= ";
997   for (std::size_t i = 0; i < sys.localityIndexByCpu.size(); ++i) {
998     LOG(INFO) << "  [" << i << "]= " << sys.localityIndexByCpu[i];
999   }
1000 }
1001 
1002 #ifdef RUSAGE_THREAD
micros(struct timeval & tv)1003 static uint64_t micros(struct timeval& tv) {
1004   return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
1005 }
1006 
1007 template <typename F>
logRusageFor(std::string name,F func)1008 static void logRusageFor(std::string name, F func) {
1009   struct rusage before;
1010   getrusage(RUSAGE_THREAD, &before);
1011   auto beforeNow = std::chrono::steady_clock::now();
1012   func();
1013   auto afterNow = std::chrono::steady_clock::now();
1014   struct rusage after;
1015   getrusage(RUSAGE_THREAD, &after);
1016   LOG(INFO) << name << ": real: "
1017             << std::chrono::duration_cast<std::chrono::microseconds>(
1018                    afterNow - beforeNow)
1019                    .count()
1020             << " usec, user: "
1021             << (micros(after.ru_utime) - micros(before.ru_utime))
1022             << " usec, sys: "
1023             << (micros(after.ru_stime) - micros(before.ru_stime)) << " usec";
1024 }
1025 
TEST(CacheLocality,BenchmarkProcCpuinfo)1026 TEST(CacheLocality, BenchmarkProcCpuinfo) {
1027   logRusageFor("readFromProcCpuinfo", CacheLocality::readFromProcCpuinfo);
1028 }
1029 
TEST(CacheLocality,BenchmarkSysfs)1030 TEST(CacheLocality, BenchmarkSysfs) {
1031   logRusageFor("readFromSysfs", CacheLocality::readFromSysfs);
1032 }
1033 #endif
1034 
1035 #if defined(FOLLY_HAVE_LINUX_VDSO) && !defined(FOLLY_SANITIZE_MEMORY)
TEST(Getcpu,VdsoGetcpu)1036 TEST(Getcpu, VdsoGetcpu) {
1037   unsigned cpu;
1038   Getcpu::resolveVdsoFunc()(&cpu, nullptr, nullptr);
1039 
1040   EXPECT_TRUE(cpu < CPU_SETSIZE);
1041 }
1042 #endif
1043 
TEST(ThreadId,SimpleTls)1044 TEST(ThreadId, SimpleTls) {
1045   unsigned cpu = 0;
1046   auto rv =
1047       folly::FallbackGetcpu<SequentialThreadId>::getcpu(&cpu, nullptr, nullptr);
1048   EXPECT_EQ(rv, 0);
1049   EXPECT_TRUE(cpu > 0);
1050   unsigned again;
1051   folly::FallbackGetcpu<SequentialThreadId>::getcpu(&again, nullptr, nullptr);
1052   EXPECT_EQ(cpu, again);
1053 }
1054 
TEST(ThreadId,SimplePthread)1055 TEST(ThreadId, SimplePthread) {
1056   unsigned cpu = 0;
1057   auto rv =
1058       folly::FallbackGetcpu<HashingThreadId>::getcpu(&cpu, nullptr, nullptr);
1059   EXPECT_EQ(rv, 0);
1060   EXPECT_TRUE(cpu > 0);
1061   unsigned again;
1062   folly::FallbackGetcpu<HashingThreadId>::getcpu(&again, nullptr, nullptr);
1063   EXPECT_EQ(cpu, again);
1064 }
1065 
1066 static thread_local unsigned testingCpu = 0;
1067 
testingGetcpu(unsigned * cpu,unsigned * node,void *)1068 static int testingGetcpu(unsigned* cpu, unsigned* node, void* /* unused */) {
1069   if (cpu != nullptr) {
1070     *cpu = testingCpu;
1071   }
1072   if (node != nullptr) {
1073     *node = testingCpu;
1074   }
1075   return 0;
1076 }
1077 
TEST(AccessSpreader,Simple)1078 TEST(AccessSpreader, Simple) {
1079   for (size_t s = 1; s < 200; ++s) {
1080     EXPECT_LT(AccessSpreader<>::current(s), s);
1081   }
1082 }
1083 
TEST(AccessSpreader,SimpleCached)1084 TEST(AccessSpreader, SimpleCached) {
1085   for (size_t s = 1; s < 200; ++s) {
1086     EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
1087   }
1088 }
1089 
TEST(AccessSpreader,ConcurrentAccessCached)1090 TEST(AccessSpreader, ConcurrentAccessCached) {
1091   std::vector<std::thread> threads;
1092   for (size_t i = 0; i < 4; ++i) {
1093     threads.emplace_back([]() {
1094       for (size_t s : {16, 32, 64}) {
1095         for (size_t j = 1; j < 200; ++j) {
1096           EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
1097           EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
1098         }
1099         std::this_thread::yield();
1100       }
1101     });
1102   }
1103   for (auto& thread : threads) {
1104     thread.join();
1105   }
1106 }
1107 
1108 #define DECLARE_SPREADER_TAG(tag, locality, func)      \
1109   namespace {                                          \
1110   template <typename dummy>                            \
1111   struct tag {};                                       \
1112   }                                                    \
1113   namespace folly {                                    \
1114   template <>                                          \
1115   const CacheLocality& CacheLocality::system<tag>() {  \
1116     static auto* inst = new CacheLocality(locality);   \
1117     return *inst;                                      \
1118   }                                                    \
1119   template <>                                          \
1120   Getcpu::Func AccessSpreader<tag>::pickGetcpuFunc() { \
1121     return func;                                       \
1122   }                                                    \
1123   template struct AccessSpreader<tag>;                 \
1124   }
1125 
1126 DECLARE_SPREADER_TAG(ManualTag, CacheLocality::uniform(16), testingGetcpu)
1127 
TEST(AccessSpreader,Wrapping)1128 TEST(AccessSpreader, Wrapping) {
1129   // this test won't pass unless locality.numCpus divides kMaxCpus
1130   auto numCpus = CacheLocality::system<ManualTag>().numCpus;
1131   EXPECT_EQ(0, 128 % numCpus);
1132   for (size_t s = 1; s < 200; ++s) {
1133     for (size_t c = 0; c < 400; ++c) {
1134       testingCpu = c;
1135       auto observed = AccessSpreader<ManualTag>::current(s);
1136       testingCpu = c % numCpus;
1137       auto expected = AccessSpreader<ManualTag>::current(s);
1138       EXPECT_EQ(expected, observed)
1139           << "numCpus=" << numCpus << ", s=" << s << ", c=" << c;
1140       EXPECT_LE(observed, AccessSpreader<ManualTag>::maxStripeValue());
1141     }
1142   }
1143 }
1144 
TEST(CoreRawAllocator,Basic)1145 TEST(CoreRawAllocator, Basic) {
1146   CoreRawAllocator<32> alloc;
1147   auto& a = alloc.get(0);
1148   auto res = a.allocate(8);
1149   memset(res, 0, 8);
1150   a.deallocate(res);
1151   res = a.allocate(8);
1152   EXPECT_TRUE((intptr_t)res % 8 == 0); // check alignment
1153   memset(res, 0, 8);
1154   a.deallocate(res);
1155   res = a.allocate(12);
1156   EXPECT_TRUE((intptr_t)res % 16 == 0); // check alignment
1157   memset(res, 0, 12);
1158   a.deallocate(res);
1159   res = a.allocate(257);
1160   memset(res, 0, 257);
1161   a.deallocate(res);
1162 
1163   std::vector<void*> mems;
1164   for (int i = 0; i < 10000; i++) {
1165     mems.push_back(a.allocate(1));
1166   }
1167   for (auto& mem : mems) {
1168     a.deallocate(mem);
1169   }
1170   mems.clear();
1171 }
1172