This commit improves scantime performance by adding checks to:
- Place longer lists earlier in the trie.
- Keep close patterns close, rather than scattering them further apart.
This reduced memory cache faults to improve load and scan time performance.
... | ... |
@@ -172,7 +172,6 @@ static int patt_cmp_fn(const struct cli_ac_patt *a, const struct cli_ac_patt *b) |
172 | 172 |
return 0; |
173 | 173 |
} |
174 | 174 |
|
175 |
- |
|
176 | 175 |
static int sort_list_fn(const void *a, const void *b) { |
177 | 176 |
const struct cli_ac_node *node_a = (*(const struct cli_ac_list **)a)->node; |
178 | 177 |
const struct cli_ac_node *node_b = (*(const struct cli_ac_list **)b)->node; |
... | ... |
@@ -180,24 +179,56 @@ static int sort_list_fn(const void *a, const void *b) { |
180 | 180 |
const struct cli_ac_patt *patt_b = (*(const struct cli_ac_list **)b)->me; |
181 | 181 |
int res; |
182 | 182 |
|
183 |
- /* 1. Group by owning node */ |
|
183 |
+ /* 1. Group by owning node |
|
184 |
+ * (this is for assigning entries to nodes) */ |
|
184 | 185 |
RETURN_RES_IF_NE(node_a, node_b); |
185 | 186 |
|
186 |
- /* 2. Group together equal pattern in a node */ |
|
187 |
+ /* 2. Group together equal pattern in a node |
|
188 |
+ * (this is for building the next_same list) */ |
|
187 | 189 |
res = patt_cmp_fn(patt_a, patt_b); |
188 | 190 |
if(res) |
189 | 191 |
return res; |
190 | 192 |
|
191 |
- /* 3. Sort equal patterns in a node by partno in ascending order */ |
|
193 |
+ /* 3. Sort equal patterns in a node by partno in ascending order |
|
194 |
+ * (this is required by the matcher) */ |
|
192 | 195 |
RETURN_RES_IF_NE(patt_a->partno, patt_b->partno); |
193 | 196 |
|
197 |
+ /* 4. Keep close patterns close |
|
198 |
+ * (this is for performace) */ |
|
199 |
+ RETURN_RES_IF_NE(patt_a, patt_b); |
|
200 |
+ |
|
194 | 201 |
return 0; |
195 | 202 |
} |
196 | 203 |
|
197 | 204 |
static int sort_heads_by_partno_fn(const void *a, const void *b) { |
198 |
- const struct cli_ac_patt *patt_a = (*(const struct cli_ac_list **)a)->me; |
|
199 |
- const struct cli_ac_patt *patt_b = (*(const struct cli_ac_list **)b)->me; |
|
205 |
+ const struct cli_ac_list *list_a = *(const struct cli_ac_list **)a; |
|
206 |
+ const struct cli_ac_list *list_b = *(const struct cli_ac_list **)b; |
|
207 |
+ const struct cli_ac_patt *patt_a = list_a->me; |
|
208 |
+ const struct cli_ac_patt *patt_b = list_b->me; |
|
209 |
+ |
|
210 |
+ /* 1. Sort heads by partno |
|
211 |
+ * (this is required by the matcher) */ |
|
200 | 212 |
RETURN_RES_IF_NE(patt_a->partno, patt_b->partno); |
213 |
+ |
|
214 |
+ /* 2. Place longer lists earlier |
|
215 |
+ * (this is for performance) */ |
|
216 |
+ |
|
217 |
+ while(1) { |
|
218 |
+ if(!list_a->next_same) { |
|
219 |
+ if(!list_b->next_same) |
|
220 |
+ break; |
|
221 |
+ return +1; |
|
222 |
+ } |
|
223 |
+ if(!list_b->next_same) |
|
224 |
+ return -1; |
|
225 |
+ list_a = list_a->next_same; |
|
226 |
+ list_b = list_b->next_same; |
|
227 |
+ } |
|
228 |
+ |
|
229 |
+ /* 3. Keep close patterns close |
|
230 |
+ * (this is for performace) */ |
|
231 |
+ RETURN_RES_IF_NE(patt_a, patt_b); |
|
232 |
+ |
|
201 | 233 |
return 0; |
202 | 234 |
} |
203 | 235 |
|
... | ... |
@@ -211,9 +242,9 @@ static inline void link_node_lists(struct cli_ac_list **listtable, unsigned int |
211 | 211 |
int ret = patt_cmp_fn(prev->me, listtable[i]->me); |
212 | 212 |
if(ret) { |
213 | 213 |
/* This is a new head of a next_same chain */ |
214 |
+ prev = listtable[i]; |
|
214 | 215 |
if(i != nheads) { |
215 | 216 |
/* Move heads towards the beginning of the table */ |
216 |
- prev = listtable[i]; |
|
217 | 217 |
listtable[i] = listtable[nheads]; |
218 | 218 |
listtable[nheads] = prev; |
219 | 219 |
} |