diff options
| author | Timo Teras <timo.teras@iki.fi> | 2011-06-20 09:49:56 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-06-20 09:49:56 +0200 |
| commit | adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3 (patch) | |
| tree | 5bb62bad050d86c1b711a19a1ea9e7ae525b9311 | |
| parent | e12e0acb92329f95a77121f489b491d84b6a2c33 (diff) | |
| download | busybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.tar.gz busybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.tar.bz2 busybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.zip | |
parse_config: use getline. BIG speedup with glibc (~40%).
function old new delta
config_read 559 604 +45
getline - 23 +23
config_close 29 49 +20
find_pair 169 187 +18
showmode 330 338 +8
hash_find 233 234 +1
builtin_umask 133 132 -1
lzo1x_optimize 1434 1429 -5
test_main 253 247 -6
buffer_fill_and_print 196 179 -17
create_J 1849 1826 -23
config_free_data 37 - -37
------------------------------------------------------------------------------
(add/remove: 3/1 grow/shrink: 5/5 up/down: 138/-89) Total: 26 bytes
Signed-off-by: Timo Teras <timo.teras@iki.fi>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | include/libbb.h | 3 | ||||
| -rw-r--r-- | libbb/parse_config.c | 92 |
2 files changed, 45 insertions, 50 deletions
diff --git a/include/libbb.h b/include/libbb.h index 2cac7e60c..953bec334 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -1184,8 +1184,9 @@ enum { | |||
| 1184 | }; | 1184 | }; |
| 1185 | typedef struct parser_t { | 1185 | typedef struct parser_t { |
| 1186 | FILE *fp; | 1186 | FILE *fp; |
| 1187 | char *line; | ||
| 1188 | char *data; | 1187 | char *data; |
| 1188 | char *line, *nline; | ||
| 1189 | size_t line_alloc, nline_alloc; | ||
| 1189 | int lineno; | 1190 | int lineno; |
| 1190 | } parser_t; | 1191 | } parser_t; |
| 1191 | parser_t* config_open(const char *filename) FAST_FUNC; | 1192 | parser_t* config_open(const char *filename) FAST_FUNC; |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index c0c34f312..cf5ba4deb 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
| @@ -83,60 +83,55 @@ parser_t* FAST_FUNC config_open(const char *filename) | |||
| 83 | return config_open2(filename, fopen_or_warn_stdin); | 83 | return config_open2(filename, fopen_or_warn_stdin); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static void config_free_data(parser_t *parser) | ||
| 87 | { | ||
| 88 | free(parser->line); | ||
| 89 | parser->line = NULL; | ||
| 90 | if (PARSE_KEEP_COPY) { /* compile-time constant */ | ||
| 91 | free(parser->data); | ||
| 92 | parser->data = NULL; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | void FAST_FUNC config_close(parser_t *parser) | 86 | void FAST_FUNC config_close(parser_t *parser) |
| 97 | { | 87 | { |
| 98 | if (parser) { | 88 | if (parser) { |
| 99 | config_free_data(parser); | 89 | if (PARSE_KEEP_COPY) /* compile-time constant */ |
| 90 | free(parser->data); | ||
| 100 | fclose(parser->fp); | 91 | fclose(parser->fp); |
| 92 | free(parser->line); | ||
| 93 | free(parser->nline); | ||
| 101 | free(parser); | 94 | free(parser); |
| 102 | } | 95 | } |
| 103 | } | 96 | } |
| 104 | 97 | ||
| 105 | /* This function reads an entire line from a text file, up to a newline | 98 | /* This function reads an entire line from a text file, |
| 106 | * or NUL byte, exclusive. It returns a malloc'ed char*. | 99 | * up to a newline, exclusive. |
| 107 | * *lineno is incremented for each line. | ||
| 108 | * Trailing '\' is recognized as line continuation. | 100 | * Trailing '\' is recognized as line continuation. |
| 109 | * Returns NULL if EOF/error. | 101 | * Returns -1 if EOF/error. |
| 110 | */ | 102 | */ |
| 111 | static char* get_line_with_continuation(FILE *file, int *lineno) | 103 | static int get_line_with_continuation(parser_t *parser) |
| 112 | { | 104 | { |
| 113 | int ch; | 105 | ssize_t len, nlen; |
| 114 | unsigned idx = 0; | 106 | char *line; |
| 115 | char *linebuf = NULL; | 107 | |
| 116 | 108 | len = getline(&parser->line, &parser->line_alloc, parser->fp); | |
| 117 | while ((ch = getc(file)) != EOF) { | 109 | if (len <= 0) |
| 118 | /* grow the line buffer as necessary */ | 110 | return len; |
| 119 | if (!(idx & 0xff)) | 111 | |
| 120 | linebuf = xrealloc(linebuf, idx + 0x101); | 112 | line = parser->line; |
| 121 | if (ch == '\n') | 113 | for (;;) { |
| 122 | ch = '\0'; | 114 | parser->lineno++; |
| 123 | linebuf[idx] = (char) ch; | 115 | if (line[len - 1] == '\n') |
| 124 | if (ch == '\0') { | 116 | len--; |
| 125 | (*lineno)++; | 117 | if (len == 0 || line[len - 1] != '\\') |
| 126 | if (idx == 0 || linebuf[idx-1] != '\\') | 118 | break; |
| 127 | break; | 119 | len--; |
| 128 | idx--; /* go back to '/' */ | 120 | |
| 129 | continue; | 121 | nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp); |
| 122 | if (nlen <= 0) | ||
| 123 | break; | ||
| 124 | |||
| 125 | if (parser->line_alloc < len + nlen + 1) { | ||
| 126 | parser->line_alloc = len + nlen + 1; | ||
| 127 | line = parser->line = xrealloc(line, parser->line_alloc); | ||
| 130 | } | 128 | } |
| 131 | idx++; | 129 | memcpy(&line[len], parser->nline, nlen); |
| 132 | } | 130 | len += nlen; |
| 133 | if (ch == EOF) { | ||
| 134 | /* handle corner case when the file is not ended with '\n' */ | ||
| 135 | (*lineno)++; | ||
| 136 | if (linebuf) | ||
| 137 | linebuf[idx] = '\0'; | ||
| 138 | } | 131 | } |
| 139 | return linebuf; | 132 | |
| 133 | line[len] = '\0'; | ||
| 134 | return len; | ||
| 140 | } | 135 | } |
| 141 | 136 | ||
| 142 | 137 | ||
| @@ -176,15 +171,14 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const | |||
| 176 | ntokens = (uint8_t)flags; | 171 | ntokens = (uint8_t)flags; |
| 177 | mintokens = (uint8_t)(flags >> 8); | 172 | mintokens = (uint8_t)(flags >> 8); |
| 178 | 173 | ||
| 179 | again: | 174 | again: |
| 180 | memset(tokens, 0, sizeof(tokens[0]) * ntokens); | 175 | memset(tokens, 0, sizeof(tokens[0]) * ntokens); |
| 181 | config_free_data(parser); | ||
| 182 | 176 | ||
| 183 | /* Read one line (handling continuations with backslash) */ | 177 | /* Read one line (handling continuations with backslash) */ |
| 184 | line = get_line_with_continuation(parser->fp, &parser->lineno); | 178 | if (get_line_with_continuation(parser) < 0) |
| 185 | if (line == NULL) | ||
| 186 | return 0; | 179 | return 0; |
| 187 | parser->line = line; | 180 | |
| 181 | line = parser->line; | ||
| 188 | 182 | ||
| 189 | /* Skip token in the start of line? */ | 183 | /* Skip token in the start of line? */ |
| 190 | if (flags & PARSE_TRIM) | 184 | if (flags & PARSE_TRIM) |
| @@ -193,8 +187,10 @@ again: | |||
| 193 | if (line[0] == '\0' || line[0] == delims[0]) | 187 | if (line[0] == '\0' || line[0] == delims[0]) |
| 194 | goto again; | 188 | goto again; |
| 195 | 189 | ||
| 196 | if (flags & PARSE_KEEP_COPY) | 190 | if (flags & PARSE_KEEP_COPY) { |
| 191 | free(parser->data); | ||
| 197 | parser->data = xstrdup(line); | 192 | parser->data = xstrdup(line); |
| 193 | } | ||
| 198 | 194 | ||
| 199 | /* Tokenize the line */ | 195 | /* Tokenize the line */ |
| 200 | t = 0; | 196 | t = 0; |
| @@ -240,8 +236,6 @@ again: | |||
| 240 | parser->lineno, t, mintokens); | 236 | parser->lineno, t, mintokens); |
| 241 | if (flags & PARSE_MIN_DIE) | 237 | if (flags & PARSE_MIN_DIE) |
| 242 | xfunc_die(); | 238 | xfunc_die(); |
| 243 | if (flags & PARSE_KEEP_COPY) | ||
| 244 | free(parser->data); | ||
| 245 | goto again; | 239 | goto again; |
| 246 | } | 240 | } |
| 247 | 241 | ||
