aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-04-02 22:54:23 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-04-02 22:54:23 +0200
commita93e4fd376d990ead254657228e75715b74ca0ac (patch)
tree0b5a12034639058875befb5f2146c67c9fd95173
parent8b0f459af7aa108089d0f87b0be81ccadb8638cb (diff)
downloadbusybox-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.c80
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
142int FAST_FUNC find_applet_by_name(const char *name) 142int 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