diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-04-02 22:54:23 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-04-02 22:54:23 +0200 |
commit | a93e4fd376d990ead254657228e75715b74ca0ac (patch) | |
tree | 0b5a12034639058875befb5f2146c67c9fd95173 | |
parent | 8b0f459af7aa108089d0f87b0be81ccadb8638cb (diff) | |
download | busybox-w32-a93e4fd376d990ead254657228e75715b74ca0ac.tar.gz busybox-w32-a93e4fd376d990ead254657228e75715b74ca0ac.tar.bz2 busybox-w32-a93e4fd376d990ead254657228e75715b74ca0ac.zip |
find_applet_by_name: add an example of faster linear search code
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/appletlib.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index aeaf238f1..18583f91a 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -141,10 +141,28 @@ void FAST_FUNC bb_show_usage(void) | |||
141 | 141 | ||
142 | int FAST_FUNC find_applet_by_name(const char *name) | 142 | int FAST_FUNC find_applet_by_name(const char *name) |
143 | { | 143 | { |
144 | unsigned i, max; | 144 | unsigned i, j, max; |
145 | int j; | ||
146 | const char *p; | 145 | const char *p; |
147 | 146 | ||
147 | /* The commented-out word-at-a-time code is ~40% faster, but +160 bytes. | ||
148 | * "Faster" here saves ~0.5 microsecond of real time - not worth it. | ||
149 | */ | ||
150 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ | ||
151 | uint32_t n32; | ||
152 | |||
153 | /* Handle all names < 2 chars long early */ | ||
154 | if (name[0] == '\0') | ||
155 | return -1; /* "" is not a valid applet name */ | ||
156 | if (name[1] == '\0') { | ||
157 | if (!ENABLE_TEST) | ||
158 | return -1; /* 1-char name is not valid */ | ||
159 | if (name[0] != ']') | ||
160 | return -1; /* 1-char name which isn't "[" is not valid */ | ||
161 | /* applet "[" is always applet #0: */ | ||
162 | return 0; | ||
163 | } | ||
164 | #endif | ||
165 | |||
148 | p = applet_names; | 166 | p = applet_names; |
149 | i = 0; | 167 | i = 0; |
150 | #if KNOWN_APPNAME_OFFSETS <= 0 | 168 | #if KNOWN_APPNAME_OFFSETS <= 0 |
@@ -166,7 +184,62 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
166 | //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); | 184 | //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); |
167 | #endif | 185 | #endif |
168 | 186 | ||
169 | /* Open-coding without strcmp/strlen calls for speed */ | 187 | /* Open-coded linear seatch without strcmp/strlen calls for speed */ |
188 | |||
189 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ | ||
190 | /* skip "[\0" name, it's surely not it */ | ||
191 | if (ENABLE_TEST && LONE_CHAR(p, '[')) | ||
192 | i++, p += 2; | ||
193 | /* All remaining applet names in p[] are at least 2 chars long */ | ||
194 | /* name[] is also at least 2 chars long */ | ||
195 | |||
196 | n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16); | ||
197 | while (i < max) { | ||
198 | uint32_t p32; | ||
199 | char ch; | ||
200 | |||
201 | /* Quickly check match of the first 3 bytes */ | ||
202 | move_from_unaligned32(p32, p); | ||
203 | p += 3; | ||
204 | if ((p32 & 0x00ffffff) != n32) { | ||
205 | /* Most likely case: 3 first bytes do not match */ | ||
206 | i++; | ||
207 | if ((p32 & 0x00ff0000) == '\0') | ||
208 | continue; // p[2] was NUL | ||
209 | p++; | ||
210 | if ((p32 & 0xff000000) == '\0') | ||
211 | continue; // p[3] was NUL | ||
212 | /* p[0..3] aren't matching and none is NUL, check the rest */ | ||
213 | while (*p++ != '\0') | ||
214 | continue; | ||
215 | continue; | ||
216 | } | ||
217 | |||
218 | /* Unlikely branch: first 3 bytes ([0..2]) match */ | ||
219 | if ((p32 & 0x00ff0000) == '\0') { | ||
220 | /* name is 2-byte long, it is full match */ | ||
221 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
222 | return i; | ||
223 | } | ||
224 | /* Check remaining bytes [3..NUL] */ | ||
225 | ch = (p32 >> 24); | ||
226 | j = 3; | ||
227 | while (ch == name[j]) { | ||
228 | if (ch == '\0') { | ||
229 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
230 | return i; | ||
231 | } | ||
232 | ch = *++p; | ||
233 | j++; | ||
234 | } | ||
235 | /* Not a match. Skip it, including NUL */ | ||
236 | while (ch != '\0') | ||
237 | ch = *++p; | ||
238 | p++; | ||
239 | i++; | ||
240 | } | ||
241 | return -1; | ||
242 | #else | ||
170 | while (i < max) { | 243 | while (i < max) { |
171 | char ch; | 244 | char ch; |
172 | j = 0; | 245 | j = 0; |
@@ -189,6 +262,7 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
189 | i++; | 262 | i++; |
190 | } | 263 | } |
191 | return -1; | 264 | return -1; |
265 | #endif | ||
192 | } | 266 | } |
193 | 267 | ||
194 | 268 | ||