aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/basic
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-11-09 10:29:27 -0500
committerMichal Marek <mmarek@suse.cz>2010-11-11 11:12:06 -0500
commit8af27e1dc4e4dd7a7b04c2cd0fc3d419d91d45b0 (patch)
tree0cf6febb82aafa421259a69007a6e848c3b9fa3c /scripts/basic
parentd63f6d1b4d3ad0d88685a5f8eb1c3cac01ddd0db (diff)
fixdep: use hash table instead of a single array
I noticed fixdep uses ~2% of cpu time in kernel build, in function use_config() fixdep spends a lot of cpu cycles in linear searches in its internal string array. With about 400 stored strings per dep file, this begins to be noticeable. Convert fixdep to use a hash table. kbuild results on my x86_64 allmodconfig Before patch : real 10m30.414s user 61m51.456s sys 8m28.200s real 10m12.334s user 61m50.236s sys 8m30.448s real 10m42.947s user 61m50.028s sys 8m32.380s After: real 10m8.180s user 61m22.506s sys 8m32.384s real 10m35.039s user 61m21.654s sys 8m32.212s real 10m14.487s user 61m23.498s sys 8m32.312s Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Michal Marek <mmarek@suse.cz>
Diffstat (limited to 'scripts/basic')
-rw-r--r--scripts/basic/fixdep.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index ea26b23de08..ed058462369 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -138,38 +138,36 @@ static void print_cmdline(void)
138 printf("cmd_%s := %s\n\n", target, cmdline); 138 printf("cmd_%s := %s\n\n", target, cmdline);
139} 139}
140 140
141char * str_config = NULL; 141struct item {
142int size_config = 0; 142 struct item *next;
143int len_config = 0; 143 unsigned int len;
144 unsigned int hash;
145 char name[0];
146};
144 147
145/* 148#define HASHSZ 256
146 * Grow the configuration string to a desired length. 149static struct item *hashtab[HASHSZ];
147 * Usually the first growth is plenty.
148 */
149static void grow_config(int len)
150{
151 while (len_config + len > size_config) {
152 if (size_config == 0)
153 size_config = 2048;
154 str_config = realloc(str_config, size_config *= 2);
155 if (str_config == NULL)
156 { perror("fixdep:malloc"); exit(1); }
157 }
158}
159 150
151static unsigned int strhash(const char *str, unsigned int sz)
152{
153 /* fnv32 hash */
154 unsigned int i, hash = 2166136261U;
160 155
156 for (i = 0; i < sz; i++)
157 hash = (hash ^ str[i]) * 0x01000193;
158 return hash;
159}
161 160
162/* 161/*
163 * Lookup a value in the configuration string. 162 * Lookup a value in the configuration string.
164 */ 163 */
165static int is_defined_config(const char * name, int len) 164static int is_defined_config(const char *name, int len, unsigned int hash)
166{ 165{
167 const char * pconfig; 166 struct item *aux;
168 const char * plast = str_config + len_config - len; 167
169 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { 168 for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) {
170 if (pconfig[ -1] == '\n' 169 if (aux->hash == hash && aux->len == len &&
171 && pconfig[len] == '\n' 170 memcmp(aux->name, name, len) == 0)
172 && !memcmp(pconfig, name, len))
173 return 1; 171 return 1;
174 } 172 }
175 return 0; 173 return 0;
@@ -178,13 +176,19 @@ static int is_defined_config(const char * name, int len)
178/* 176/*
179 * Add a new value to the configuration string. 177 * Add a new value to the configuration string.
180 */ 178 */
181static void define_config(const char * name, int len) 179static void define_config(const char *name, int len, unsigned int hash)
182{ 180{
183 grow_config(len + 1); 181 struct item *aux = malloc(sizeof(*aux) + len);
184 182
185 memcpy(str_config+len_config, name, len); 183 if (!aux) {
186 len_config += len; 184 perror("fixdep:malloc");
187 str_config[len_config++] = '\n'; 185 exit(1);
186 }
187 memcpy(aux->name, name, len);
188 aux->len = len;
189 aux->hash = hash;
190 aux->next = hashtab[hash % HASHSZ];
191 hashtab[hash % HASHSZ] = aux;
188} 192}
189 193
190/* 194/*
@@ -192,40 +196,49 @@ static void define_config(const char * name, int len)
192 */ 196 */
193static void clear_config(void) 197static void clear_config(void)
194{ 198{
195 len_config = 0; 199 struct item *aux, *next;
196 define_config("", 0); 200 unsigned int i;
201
202 for (i = 0; i < HASHSZ; i++) {
203 for (aux = hashtab[i]; aux; aux = next) {
204 next = aux->next;
205 free(aux);
206 }
207 hashtab[i] = NULL;
208 }
197} 209}
198 210
199/* 211/*
200 * Record the use of a CONFIG_* word. 212 * Record the use of a CONFIG_* word.
201 */ 213 */
202static void use_config(char *m, int slen) 214static void use_config(const char *m, int slen)
203{ 215{
204 char s[PATH_MAX]; 216 unsigned int hash = strhash(m, slen);
205 char *p; 217 int c, i;
206 218
207 if (is_defined_config(m, slen)) 219 if (is_defined_config(m, slen, hash))
208 return; 220 return;
209 221
210 define_config(m, slen); 222 define_config(m, slen, hash);
211
212 memcpy(s, m, slen); s[slen] = 0;
213 223
214 for (p = s; p < s + slen; p++) { 224 printf(" $(wildcard include/config/");
215 if (*p == '_') 225 for (i = 0; i < slen; i++) {
216 *p = '/'; 226 c = m[i];
227 if (c == '_')
228 c = '/';
217 else 229 else
218 *p = tolower((int)*p); 230 c = tolower(c);
231 putchar(c);
219 } 232 }
220 printf(" $(wildcard include/config/%s.h) \\\n", s); 233 printf(".h) \\\n");
221} 234}
222 235
223static void parse_config_file(char *map, size_t len) 236static void parse_config_file(const char *map, size_t len)
224{ 237{
225 int *end = (int *) (map + len); 238 const int *end = (const int *) (map + len);
226 /* start at +1, so that p can never be < map */ 239 /* start at +1, so that p can never be < map */
227 int *m = (int *) map + 1; 240 const int *m = (const int *) map + 1;
228 char *p, *q; 241 const char *p, *q;
229 242
230 for (; m < end; m++) { 243 for (; m < end; m++) {
231 if (*m == INT_CONF) { p = (char *) m ; goto conf; } 244 if (*m == INT_CONF) { p = (char *) m ; goto conf; }
@@ -265,7 +278,7 @@ static int strrcmp(char *s, char *sub)
265 return memcmp(s + slen - sublen, sub, sublen); 278 return memcmp(s + slen - sublen, sub, sublen);
266} 279}
267 280
268static void do_config_file(char *filename) 281static void do_config_file(const char *filename)
269{ 282{
270 struct stat st; 283 struct stat st;
271 int fd; 284 int fd;