diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-29 19:07:36 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-29 19:07:36 +0200 |
commit | 3aff3b9cb81c1f574aaafaf3981e755c6639e2bc (patch) | |
tree | 1f67a3cc384ab9e7e4c9e030a469e6b0b9bb15dc | |
parent | b3c91a127f8baecee0265ba92898ae1e718bdb31 (diff) | |
download | busybox-w32-3aff3b9cb81c1f574aaafaf3981e755c6639e2bc.tar.gz busybox-w32-3aff3b9cb81c1f574aaafaf3981e755c6639e2bc.tar.bz2 busybox-w32-3aff3b9cb81c1f574aaafaf3981e755c6639e2bc.zip |
awk: assorted optimizations
hash_find(): do not caclculate hash twice. Do not divide - can use
cheap multiply-by-8 shift.
nextword(): do not repeatedly increment in-memory value, do it in register,
then store final result.
hashwalk_init(): do not strlen() twice.
function old new delta
hash_search3 - 49 +49
hash_find 259 281 +22
nextword 19 16 -3
evaluate 3141 3137 -4
hash_search 54 28 -26
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/3 up/down: 71/-33) Total: 38 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/editors/awk.c b/editors/awk.c index 4e29b28cf..a4cd3cf93 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -696,6 +696,7 @@ static void hash_clear(xhash *hash) | |||
696 | while (hi) { | 696 | while (hi) { |
697 | thi = hi; | 697 | thi = hi; |
698 | hi = hi->next; | 698 | hi = hi->next; |
699 | //FIXME: this assumes that it's a hash of *variables*: | ||
699 | free(thi->data.v.string); | 700 | free(thi->data.v.string); |
700 | free(thi); | 701 | free(thi); |
701 | } | 702 | } |
@@ -714,11 +715,11 @@ static void hash_free(xhash *hash) | |||
714 | #endif | 715 | #endif |
715 | 716 | ||
716 | /* find item in hash, return ptr to data, NULL if not found */ | 717 | /* find item in hash, return ptr to data, NULL if not found */ |
717 | static void *hash_search(xhash *hash, const char *name) | 718 | static NOINLINE void *hash_search3(xhash *hash, const char *name, unsigned idx) |
718 | { | 719 | { |
719 | hash_item *hi; | 720 | hash_item *hi; |
720 | 721 | ||
721 | hi = hash->items[hashidx(name) % hash->csize]; | 722 | hi = hash->items[idx % hash->csize]; |
722 | while (hi) { | 723 | while (hi) { |
723 | if (strcmp(hi->name, name) == 0) | 724 | if (strcmp(hi->name, name) == 0) |
724 | return &hi->data; | 725 | return &hi->data; |
@@ -727,6 +728,11 @@ static void *hash_search(xhash *hash, const char *name) | |||
727 | return NULL; | 728 | return NULL; |
728 | } | 729 | } |
729 | 730 | ||
731 | static void *hash_search(xhash *hash, const char *name) | ||
732 | { | ||
733 | return hash_search3(hash, name, hashidx(name)); | ||
734 | } | ||
735 | |||
730 | /* grow hash if it becomes too big */ | 736 | /* grow hash if it becomes too big */ |
731 | static void hash_rebuild(xhash *hash) | 737 | static void hash_rebuild(xhash *hash) |
732 | { | 738 | { |
@@ -762,16 +768,17 @@ static void *hash_find(xhash *hash, const char *name) | |||
762 | unsigned idx; | 768 | unsigned idx; |
763 | int l; | 769 | int l; |
764 | 770 | ||
765 | hi = hash_search(hash, name); | 771 | idx = hashidx(name); |
772 | hi = hash_search3(hash, name, idx); | ||
766 | if (!hi) { | 773 | if (!hi) { |
767 | if (++hash->nel / hash->csize > 10) | 774 | if (++hash->nel > hash->csize * 8) |
768 | hash_rebuild(hash); | 775 | hash_rebuild(hash); |
769 | 776 | ||
770 | l = strlen(name) + 1; | 777 | l = strlen(name) + 1; |
771 | hi = xzalloc(sizeof(*hi) + l); | 778 | hi = xzalloc(sizeof(*hi) + l); |
772 | strcpy(hi->name, name); | 779 | strcpy(hi->name, name); |
773 | 780 | ||
774 | idx = hashidx(name) % hash->csize; | 781 | idx = idx % hash->csize; |
775 | hi->next = hash->items[idx]; | 782 | hi->next = hash->items[idx]; |
776 | hash->items[idx] = hi; | 783 | hash->items[idx] = hi; |
777 | hash->glen += l; | 784 | hash->glen += l; |
@@ -822,8 +829,10 @@ static char *skip_spaces(char *p) | |||
822 | static char *nextword(char **s) | 829 | static char *nextword(char **s) |
823 | { | 830 | { |
824 | char *p = *s; | 831 | char *p = *s; |
825 | while (*(*s)++ != '\0') | 832 | char *q = p; |
833 | while (*q++ != '\0') | ||
826 | continue; | 834 | continue; |
835 | *s = q; | ||
827 | return p; | 836 | return p; |
828 | } | 837 | } |
829 | 838 | ||
@@ -2116,8 +2125,7 @@ static void hashwalk_init(var *v, xhash *array) | |||
2116 | for (i = 0; i < array->csize; i++) { | 2125 | for (i = 0; i < array->csize; i++) { |
2117 | hi = array->items[i]; | 2126 | hi = array->items[i]; |
2118 | while (hi) { | 2127 | while (hi) { |
2119 | strcpy(w->end, hi->name); | 2128 | w->end = stpcpy(w->end, hi->name) + 1; |
2120 | nextword(&w->end); | ||
2121 | hi = hi->next; | 2129 | hi = hi->next; |
2122 | } | 2130 | } |
2123 | } | 2131 | } |
@@ -3504,7 +3512,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | |||
3504 | setari_u(intvar[ARGV], ++i, *argv++); | 3512 | setari_u(intvar[ARGV], ++i, *argv++); |
3505 | setvar_i(intvar[ARGC], i + 1); | 3513 | setvar_i(intvar[ARGC], i + 1); |
3506 | 3514 | ||
3507 | //fdhash = ahash - done via define | 3515 | //fdhash = ahash; // done via define |
3508 | newfile("/dev/stdin")->F = stdin; | 3516 | newfile("/dev/stdin")->F = stdin; |
3509 | newfile("/dev/stdout")->F = stdout; | 3517 | newfile("/dev/stdout")->F = stdout; |
3510 | newfile("/dev/stderr")->F = stderr; | 3518 | newfile("/dev/stderr")->F = stderr; |