Browse code

bb12389 - fast AC sig load, part 2 - courtesy of Alberto Wu

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.

Micah Snyder authored on 2019/10/24 22:15:25
Showing 1 changed files
... ...
@@ -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
 	    }