]>
Commit | Line | Data |
---|---|---|
bdafeae0 | 1 | #define USE_THE_INDEX_VARIABLE |
64eb82fe | 2 | #include "test-tool.h" |
ea194895 | 3 | #include "cache.h" |
32a8f510 | 4 | #include "environment.h" |
ea194895 JH |
5 | #include "parse-options.h" |
6 | ||
7 | static int single; | |
8 | static int multi; | |
9 | static int count = 1; | |
10 | static int dump; | |
11 | static int perf; | |
12 | static int analyze; | |
13 | static int analyze_step; | |
14 | ||
15 | /* | |
16 | * Dump the contents of the "dir" and "name" hash tables to stdout. | |
17 | * If you sort the result, you can compare it with the other type | |
18 | * mode and verify that both single and multi produce the same set. | |
19 | */ | |
20 | static void dump_run(void) | |
21 | { | |
22 | struct hashmap_iter iter_dir; | |
23 | struct hashmap_iter iter_cache; | |
24 | ||
25 | /* Stolen from name-hash.c */ | |
26 | struct dir_entry { | |
27 | struct hashmap_entry ent; | |
28 | struct dir_entry *parent; | |
29 | int nr; | |
30 | unsigned int namelen; | |
31 | char name[FLEX_ARRAY]; | |
32 | }; | |
33 | ||
34 | struct dir_entry *dir; | |
35 | struct cache_entry *ce; | |
36 | ||
0ea414a1 | 37 | repo_read_index(the_repository); |
ea194895 JH |
38 | if (single) { |
39 | test_lazy_init_name_hash(&the_index, 0); | |
40 | } else { | |
41 | int nr_threads_used = test_lazy_init_name_hash(&the_index, 1); | |
42 | if (!nr_threads_used) | |
43 | die("non-threaded code path used"); | |
44 | } | |
45 | ||
87571c3f | 46 | hashmap_for_each_entry(&the_index.dir_hash, &iter_dir, dir, |
23dee69f | 47 | ent /* member name */) |
ea194895 | 48 | printf("dir %08x %7d %s\n", dir->ent.hash, dir->nr, dir->name); |
ea194895 | 49 | |
87571c3f | 50 | hashmap_for_each_entry(&the_index.name_hash, &iter_cache, ce, |
23dee69f | 51 | ent /* member name */) |
ea194895 | 52 | printf("name %08x %s\n", ce->ent.hash, ce->name); |
ea194895 | 53 | |
0ea414a1 | 54 | discard_index(&the_index); |
ea194895 JH |
55 | } |
56 | ||
57 | /* | |
58 | * Run the single or multi threaded version "count" times and | |
59 | * report on the time taken. | |
60 | */ | |
61 | static uint64_t time_runs(int try_threaded) | |
62 | { | |
63 | uint64_t t0, t1, t2; | |
64 | uint64_t sum = 0; | |
65 | uint64_t avg; | |
66 | int nr_threads_used; | |
67 | int i; | |
68 | ||
69 | for (i = 0; i < count; i++) { | |
70 | t0 = getnanotime(); | |
0ea414a1 | 71 | repo_read_index(the_repository); |
ea194895 JH |
72 | t1 = getnanotime(); |
73 | nr_threads_used = test_lazy_init_name_hash(&the_index, try_threaded); | |
74 | t2 = getnanotime(); | |
75 | ||
76 | sum += (t2 - t1); | |
77 | ||
78 | if (try_threaded && !nr_threads_used) | |
79 | die("non-threaded code path used"); | |
80 | ||
81 | if (nr_threads_used) | |
82 | printf("%f %f %d multi %d\n", | |
83 | ((double)(t1 - t0))/1000000000, | |
84 | ((double)(t2 - t1))/1000000000, | |
85 | the_index.cache_nr, | |
86 | nr_threads_used); | |
87 | else | |
88 | printf("%f %f %d single\n", | |
89 | ((double)(t1 - t0))/1000000000, | |
90 | ((double)(t2 - t1))/1000000000, | |
91 | the_index.cache_nr); | |
92 | fflush(stdout); | |
93 | ||
0ea414a1 | 94 | discard_index(&the_index); |
ea194895 JH |
95 | } |
96 | ||
97 | avg = sum / count; | |
98 | if (count > 1) | |
99 | printf("avg %f %s\n", | |
100 | (double)avg/1000000000, | |
101 | (try_threaded) ? "multi" : "single"); | |
102 | ||
103 | return avg; | |
104 | } | |
105 | ||
106 | /* | |
107 | * Try a series of runs varying the "istate->cache_nr" and | |
108 | * try to find a good value for the multi-threaded criteria. | |
109 | */ | |
110 | static void analyze_run(void) | |
111 | { | |
112 | uint64_t t1s, t1m, t2s, t2m; | |
113 | int cache_nr_limit; | |
74dea0e1 | 114 | int nr_threads_used = 0; |
ea194895 JH |
115 | int i; |
116 | int nr; | |
117 | ||
0ea414a1 | 118 | repo_read_index(the_repository); |
ea194895 | 119 | cache_nr_limit = the_index.cache_nr; |
0ea414a1 | 120 | discard_index(&the_index); |
ea194895 JH |
121 | |
122 | nr = analyze; | |
123 | while (1) { | |
124 | uint64_t sum_single = 0; | |
125 | uint64_t sum_multi = 0; | |
126 | uint64_t avg_single; | |
127 | uint64_t avg_multi; | |
128 | ||
129 | if (nr > cache_nr_limit) | |
130 | nr = cache_nr_limit; | |
131 | ||
132 | for (i = 0; i < count; i++) { | |
0ea414a1 | 133 | repo_read_index(the_repository); |
ea194895 JH |
134 | the_index.cache_nr = nr; /* cheap truncate of index */ |
135 | t1s = getnanotime(); | |
136 | test_lazy_init_name_hash(&the_index, 0); | |
137 | t2s = getnanotime(); | |
138 | sum_single += (t2s - t1s); | |
139 | the_index.cache_nr = cache_nr_limit; | |
0ea414a1 | 140 | discard_index(&the_index); |
ea194895 | 141 | |
0ea414a1 | 142 | repo_read_index(the_repository); |
ea194895 JH |
143 | the_index.cache_nr = nr; /* cheap truncate of index */ |
144 | t1m = getnanotime(); | |
145 | nr_threads_used = test_lazy_init_name_hash(&the_index, 1); | |
146 | t2m = getnanotime(); | |
147 | sum_multi += (t2m - t1m); | |
148 | the_index.cache_nr = cache_nr_limit; | |
0ea414a1 | 149 | discard_index(&the_index); |
ea194895 JH |
150 | |
151 | if (!nr_threads_used) | |
152 | printf(" [size %8d] [single %f] non-threaded code path used\n", | |
153 | nr, ((double)(t2s - t1s))/1000000000); | |
154 | else | |
155 | printf(" [size %8d] [single %f] %c [multi %f %d]\n", | |
156 | nr, | |
157 | ((double)(t2s - t1s))/1000000000, | |
158 | (((t2s - t1s) < (t2m - t1m)) ? '<' : '>'), | |
159 | ((double)(t2m - t1m))/1000000000, | |
160 | nr_threads_used); | |
161 | fflush(stdout); | |
162 | } | |
163 | if (count > 1) { | |
164 | avg_single = sum_single / count; | |
165 | avg_multi = sum_multi / count; | |
166 | if (!nr_threads_used) | |
167 | printf("avg [size %8d] [single %f]\n", | |
168 | nr, | |
169 | (double)avg_single/1000000000); | |
170 | else | |
171 | printf("avg [size %8d] [single %f] %c [multi %f %d]\n", | |
172 | nr, | |
173 | (double)avg_single/1000000000, | |
174 | (avg_single < avg_multi ? '<' : '>'), | |
175 | (double)avg_multi/1000000000, | |
176 | nr_threads_used); | |
177 | fflush(stdout); | |
178 | } | |
179 | ||
180 | if (nr >= cache_nr_limit) | |
181 | return; | |
182 | nr += analyze_step; | |
183 | } | |
184 | } | |
185 | ||
64eb82fe | 186 | int cmd__lazy_init_name_hash(int argc, const char **argv) |
ea194895 JH |
187 | { |
188 | const char *usage[] = { | |
64eb82fe NTND |
189 | "test-tool lazy-init-name-hash -d (-s | -m)", |
190 | "test-tool lazy-init-name-hash -p [-c c]", | |
191 | "test-tool lazy-init-name-hash -a a [--step s] [-c c]", | |
192 | "test-tool lazy-init-name-hash (-s | -m) [-c c]", | |
193 | "test-tool lazy-init-name-hash -s -m [-c c]", | |
ea194895 JH |
194 | NULL |
195 | }; | |
196 | struct option options[] = { | |
197 | OPT_BOOL('s', "single", &single, "run single-threaded code"), | |
198 | OPT_BOOL('m', "multi", &multi, "run multi-threaded code"), | |
199 | OPT_INTEGER('c', "count", &count, "number of passes"), | |
200 | OPT_BOOL('d', "dump", &dump, "dump hash tables"), | |
201 | OPT_BOOL('p', "perf", &perf, "compare single vs multi"), | |
202 | OPT_INTEGER('a', "analyze", &analyze, "analyze different multi sizes"), | |
203 | OPT_INTEGER(0, "step", &analyze_step, "analyze step factor"), | |
204 | OPT_END(), | |
205 | }; | |
206 | const char *prefix; | |
207 | uint64_t avg_single, avg_multi; | |
208 | ||
209 | prefix = setup_git_directory(); | |
210 | ||
211 | argc = parse_options(argc, argv, prefix, options, usage, 0); | |
212 | ||
213 | /* | |
214 | * istate->dir_hash is only created when ignore_case is set. | |
215 | */ | |
216 | ignore_case = 1; | |
217 | ||
218 | if (dump) { | |
219 | if (perf || analyze > 0) | |
220 | die("cannot combine dump, perf, or analyze"); | |
221 | if (count > 1) | |
222 | die("count not valid with dump"); | |
223 | if (single && multi) | |
224 | die("cannot use both single and multi with dump"); | |
225 | if (!single && !multi) | |
226 | die("dump requires either single or multi"); | |
227 | dump_run(); | |
228 | return 0; | |
229 | } | |
230 | ||
231 | if (perf) { | |
232 | if (analyze > 0) | |
233 | die("cannot combine dump, perf, or analyze"); | |
234 | if (single || multi) | |
235 | die("cannot use single or multi with perf"); | |
236 | avg_single = time_runs(0); | |
237 | avg_multi = time_runs(1); | |
238 | if (avg_multi > avg_single) | |
239 | die("multi is slower"); | |
240 | return 0; | |
241 | } | |
242 | ||
243 | if (analyze) { | |
244 | if (analyze < 500) | |
245 | die("analyze must be at least 500"); | |
246 | if (!analyze_step) | |
247 | analyze_step = analyze; | |
248 | if (single || multi) | |
249 | die("cannot use single or multi with analyze"); | |
250 | analyze_run(); | |
251 | return 0; | |
252 | } | |
253 | ||
254 | if (!single && !multi) | |
255 | die("require either -s or -m or both"); | |
256 | ||
257 | if (single) | |
258 | time_runs(0); | |
259 | if (multi) | |
260 | time_runs(1); | |
261 | ||
262 | return 0; | |
263 | } |