From 5a2914f6c70bd5177fac700568e3b06f94ba471b Mon Sep 17 00:00:00 2001 From: Dianne Skoll Date: Sat, 14 Dec 2024 11:52:16 -0500 Subject: [PATCH] Start hash tables with 7 buckets instead of 17; print more detailed hash stats with -ds; consistently use ErrFp instead of stderr --- src/calendar.c | 4 +-- src/dedupe.c | 10 +++---- src/expr.c | 8 +++--- src/funcs.c | 6 ++--- src/hashtab.c | 9 ++++++- src/hashtab.h | 4 +++ src/hashtab_stats.c | 7 +++-- src/init.c | 10 +++---- src/main.c | 28 +++++++++++--------- src/protos.h | 8 +++--- src/trans.c | 10 +++---- src/userfns.c | 10 +++---- src/var.c | 12 +++------ tests/test.cmp | 64 +++++++++++++++++++++++++++++++++++---------- 14 files changed, 113 insertions(+), 77 deletions(-) diff --git a/src/calendar.c b/src/calendar.c index 2e05e922..bdffa803 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -1272,7 +1272,7 @@ static void PrintLeft(char const *s, int width, char pad) buf = calloc(len+1, sizeof(wchar_t)); if (!buf) { /* Uh-oh... cannot recover */ - fprintf(stderr, "%s\n", GetErr(E_NO_MEM)); + fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM)); exit(EXIT_FAILURE); } } @@ -1357,7 +1357,7 @@ static void PrintCentered(char const *s, int width, char *pad) buf = calloc(len+1, sizeof(wchar_t)); if (!buf) { /* Uh-oh... cannot recover */ - fprintf(stderr, "%s\n", GetErr(E_NO_MEM)); + fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM)); exit(EXIT_FAILURE); } } diff --git a/src/dedupe.c b/src/dedupe.c index c8d4d58a..9c9bc024 100644 --- a/src/dedupe.c +++ b/src/dedupe.c @@ -167,17 +167,13 @@ InitDedupeTable(void) if (hash_table_init(&DedupeTable, offsetof(DedupeEntry, link), DedupeHashFunc, CompareDedupes) < 0) { - fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n"); + fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n"); exit(1); } } void -get_dedupe_hash_stats(int *total, int *maxlen, double *avglen) +dump_dedupe_hash_stats(void) { - struct hash_table_stats s; - hash_table_get_stats(&DedupeTable, &s); - *total = s.num_entries; - *maxlen = s.max_len; - *avglen = s.avg_len; + hash_table_dump_stats(&DedupeTable, ErrFp); } diff --git a/src/expr.c b/src/expr.c index d2827d7e..b8c93e03 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3088,10 +3088,10 @@ int DoCoerce(char type, Value *v) /***************************************************************/ void print_expr_nodes_stats(void) { - fprintf(stderr, " Expression nodes allocated: %d\n", ExprNodesAllocated); - fprintf(stderr, "Expression nodes high-water: %d\n", ExprNodesHighWater); - fprintf(stderr, " Expression nodes leaked: %d\n", ExprNodesUsed); - fprintf(stderr, " Parse level high-water: %d\n", parse_level_high_water); + fprintf(ErrFp, " Expression nodes allocated: %d\n", ExprNodesAllocated); + fprintf(ErrFp, "Expression nodes high-water: %d\n", ExprNodesHighWater); + fprintf(ErrFp, " Expression nodes leaked: %d\n", ExprNodesUsed); + fprintf(ErrFp, " Parse level high-water: %d\n", parse_level_high_water); } /* Return 1 if a value is "true" for its type, 0 if "false" */ diff --git a/src/funcs.c b/src/funcs.c index 4339147b..a970e8cf 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -3265,11 +3265,11 @@ static int setenv(char const *varname, char const *val, int overwrite) { static char tzbuf[256]; if (strcmp(varname, "TZ")) { - fprintf(stderr, "built-in setenv can only be used with TZ\n"); + fprintf(ErrFp, "built-in setenv can only be used with TZ\n"); abort(); } if (!overwrite) { - fprintf(stderr, "built-in setenv must have overwrite=1\n"); + fprintf(ErrFp, "built-in setenv must have overwrite=1\n"); abort(); } @@ -3287,7 +3287,7 @@ static void unsetenv(char const *varname) { static char tzbuf[8]; if (strcmp(varname, "TZ")) { - fprintf(stderr, "built-in unsetenv can only be used with TZ\n"); + fprintf(ErrFp, "built-in unsetenv can only be used with TZ\n"); abort(); } sprintf(tzbuf, "%s", varname); diff --git a/src/hashtab.c b/src/hashtab.c index d256756d..cc44248d 100644 --- a/src/hashtab.c +++ b/src/hashtab.c @@ -63,7 +63,7 @@ * These are used as choices for the number of hash buckets in the table */ static size_t bucket_choices[] = { - 17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719, + 7, 17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719, 175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671, 44917381, 89834777, 179669557, 359339171, 718678369, 1437356741 }; @@ -108,6 +108,8 @@ hash_table_init(hash_table *t, t->hashfunc = hashfunc; t->compare = compare; t->buckets = malloc(sizeof(void *) * bucket_choices[0]); + t->num_growths = 0; + t->num_shrinks = 0; if (!t->buckets) { return -1; } @@ -216,6 +218,11 @@ hash_table_resize(hash_table *t, int dir) /* Out of memory... just don't resize? */ return 0; } + if (dir == 1) { + t->num_growths++; + } else { + t->num_shrinks++; + } for (size_t j=0; jstddev = 0.0; stat->num_nonempty_buckets = 0; stat->avg_nonempty_len = 0.0; + stat->num_growths = t->num_growths; + stat->num_shrinks = t->num_shrinks; double sum = 0.0; double sumsq = 0.0; diff --git a/src/init.c b/src/init.c index c7a37f90..3de72461 100644 --- a/src/init.c +++ b/src/init.c @@ -149,7 +149,7 @@ static char const *DefaultFilename(void) s = getenv("HOME"); if (!s) { - fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n"); + fprintf(ErrFp, "HOME environment variable not set. Unable to determine reminder file.\n"); exit(EXIT_FAILURE); } DBufPuts(&default_filename_buf, s); @@ -237,7 +237,7 @@ void InitRemind(int argc, char const *argv[]) InvokedAsRem = 1; } } else { - fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n"); + fprintf(ErrFp, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n"); exit(EXIT_FAILURE); } @@ -577,7 +577,7 @@ void InitRemind(int argc, char const *argv[]) /* -wt means get width from /dev/tty */ ttyfd = open("/dev/tty", O_RDONLY); if (ttyfd < 0) { - fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n", + fprintf(ErrFp, "%s: `-wt': Cannot open /dev/tty: %s\n", argv[0], strerror(errno)); } else { InitCalWidthAndFormWidth(ttyfd); @@ -728,7 +728,7 @@ void InitRemind(int argc, char const *argv[]) default: if (tok.type == T_Illegal && tok.val < 0) { - fprintf(stderr, "%s: `%s'\n", GetErr(-tok.val), arg); + fprintf(ErrFp, "%s: `%s'\n", GetErr(-tok.val), arg); Usage(); } Usage(); @@ -1018,7 +1018,7 @@ AddTrustedUser(char const *username) { struct passwd *pwent; if (NumTrustedUsers >= MAX_TRUSTED_USERS) { - fprintf(stderr, "Too many trusted users (%d max)\n", + fprintf(ErrFp, "Too many trusted users (%d max)\n", MAX_TRUSTED_USERS); exit(EXIT_FAILURE); } diff --git a/src/main.c b/src/main.c index 8b4caf1d..3ba64cb5 100644 --- a/src/main.c +++ b/src/main.c @@ -60,19 +60,21 @@ exitfunc(void) /* Kill any execution-time-limiter process */ unlimit_execution_time(); - int maxlen, total; - double avglen; if (DebugFlag & DB_PARSE_EXPR) { fflush(stdout); - fflush(stderr); - get_var_hash_stats(&total, &maxlen, &avglen); - fprintf(stderr, " Var hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); - get_userfunc_hash_stats(&total, &maxlen, &avglen); - fprintf(stderr, " Func hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); - get_dedupe_hash_stats(&total, &maxlen, &avglen); - fprintf(stderr, "Dedup hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); - get_translation_hash_stats(&total, &maxlen, &avglen); - fprintf(stderr, "Trans hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); + fflush(ErrFp); + fprintf(ErrFp, "Variable hash table statistics:\n"); + dump_var_hash_stats(); + + fprintf(ErrFp, "Function hash table statistics:\n"); + dump_userfunc_hash_stats(); + + fprintf(ErrFp, "Dedupe hash table statistics:\n"); + dump_dedupe_hash_stats(); + + fprintf(ErrFp, "Translation hash table statistics:\n"); + dump_translation_hash_stats(); + UnsetAllUserFuncs(); print_expr_nodes_stats(); } @@ -128,7 +130,7 @@ int main(int argc, char *argv[]) sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; if (sigaction(SIGALRM, &act, NULL) < 0) { - fprintf(stderr, "%s: sigaction() failed: %s\n", + fprintf(ErrFp, "%s: sigaction() failed: %s\n", argv[0], strerror(errno)); exit(1); } @@ -137,7 +139,7 @@ int main(int argc, char *argv[]) act.sa_flags = SA_RESTART; sigemptyset(&act.sa_mask); if (sigaction(SIGXCPU, &act, NULL) < 0) { - fprintf(stderr, "%s: sigaction() failed: %s\n", + fprintf(ErrFp, "%s: sigaction() failed: %s\n", argv[0], strerror(errno)); exit(1); } diff --git a/src/protos.h b/src/protos.h index 3480ce24..862fc672 100644 --- a/src/protos.h +++ b/src/protos.h @@ -256,10 +256,10 @@ void print_builtinfunc_tokens(void); void print_remind_tokens(void); /* Stats for -ds output */ -void get_var_hash_stats(int *total, int *maxlen, double *avglen); -void get_userfunc_hash_stats(int *total, int *maxlen, double *avglen); -void get_dedupe_hash_stats(int *total, int *maxlen, double *avglen); -void get_translation_hash_stats(int *total, int *maxlen, double *avglen); +void dump_var_hash_stats(void); +void dump_userfunc_hash_stats(void); +void dump_dedupe_hash_stats(void); +void dump_translation_hash_stats(void); /* Dedupe code */ int ShouldDedupe(int trigger_date, int trigger_time, char const *body); diff --git a/src/trans.c b/src/trans.c index 9fbeed46..491bbec6 100644 --- a/src/trans.c +++ b/src/trans.c @@ -202,7 +202,7 @@ InitTranslationTable(void) { if (hash_table_init(&TranslationTable, offsetof(XlateItem, link), HashXlateItem, CompareXlateItems) < 0) { - fprintf(stderr, "Unable to initialize translation hash table: Out of memory. Exiting.\n"); + fprintf(ErrFp, "Unable to initialize translation hash table: Out of memory. Exiting.\n"); exit(1); } InsertTranslation("LANGID", "en"); @@ -386,12 +386,8 @@ DoTranslate(ParsePtr p) } void -get_translation_hash_stats(int *total, int *maxlen, double *avglen) +dump_translation_hash_stats(void) { - struct hash_table_stats s; - hash_table_get_stats(&TranslationTable, &s); - *total = s.num_entries; - *maxlen = s.max_len; - *avglen = s.avg_len; + hash_table_dump_stats(&TranslationTable, ErrFp); } diff --git a/src/userfns.c b/src/userfns.c index 8a1ca0f1..98170013 100644 --- a/src/userfns.c +++ b/src/userfns.c @@ -56,7 +56,7 @@ InitUserFunctions(void) offsetof(UserFunc, link), HashUserFunc, CompareUserFuncs) < 0) { - fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n"); + fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n"); exit(1); } } @@ -506,12 +506,8 @@ RenameUserFunc(char const *oldname, char const *newname) } void -get_userfunc_hash_stats(int *total, int *maxlen, double *avglen) +dump_userfunc_hash_stats(void) { - struct hash_table_stats s; - hash_table_get_stats(&FuncHash, &s); - *total = s.num_entries; - *maxlen = s.max_len; - *avglen = s.avg_len; + hash_table_dump_stats(&FuncHash, ErrFp); } diff --git a/src/var.c b/src/var.c index e690fa4f..22e1ebe5 100644 --- a/src/var.c +++ b/src/var.c @@ -56,7 +56,7 @@ InitVars(void) { if (hash_table_init(&VHashTbl, offsetof(Var, link), VarHashFunc, VarCompareFunc) < 0) { - fprintf(stderr, "Unable to initialize variable hash table: Out of memory. Exiting.\n"); + fprintf(ErrFp, "Unable to initialize variable hash table: Out of memory. Exiting.\n"); exit(1); } } @@ -723,7 +723,7 @@ int DoDump(ParsePtr p) /* */ /* DumpVarTable */ /* */ -/* Dump the variable table to stderr. */ +/* Dump the variable table to ErrFp. */ /* */ /***************************************************************/ void DumpVarTable(void) @@ -1249,11 +1249,7 @@ print_sysvar_tokens(void) } void -get_var_hash_stats(int *total, int *maxlen, double *avglen) +dump_var_hash_stats(void) { - struct hash_table_stats s; - hash_table_get_stats(&VHashTbl, &s); - *total = s.num_entries; - *maxlen = s.max_len; - *avglen = s.avg_len; + hash_table_dump_stats(&VHashTbl, ErrFp); } diff --git a/tests/test.cmp b/tests/test.cmp index 22806f17..9c98d42f 100644 --- a/tests/test.cmp +++ b/tests/test.cmp @@ -16127,8 +16127,8 @@ TRANSLATE "January" "translated-January" TRANSLATE "Tuesday" "translated-Tuesday" TRANSLATE "November" "translated-November" TRANSLATE "tomorrow" "translated-Tomorrow" -TRANSLATE "today" "translated-Today" TRANSLATE "is" "translated-Is" +TRANSLATE "today" "translated-Today" TRANSLATE "from now" "translated-Fromnow" TRANSLATE "Friday" "translated-Friday" TRANSLATE "am" "translated-Am" @@ -16139,8 +16139,8 @@ TRANSLATE "pm" "translated-Pm" TRANSLATE "August" "translated-August" TRANSLATE "May" "translated-May" TRANSLATE "February" "translated-February" -TRANSLATE "on" "translated-On" TRANSLATE "now" "translated-Now" +TRANSLATE "on" "translated-On" $Ago is otherway-Ago $Am is otherway-Am $And is otherway-And @@ -16238,10 +16238,22 @@ D'oh, a file whose name has spaces! ../tests/with space.rem DEBUG -e - Var hash: total = 100141; maxlen = 5; avglen = 1.142 - Func hash: total = 100016; maxlen = 5; avglen = 1.140 -Dedup hash: total = 10000; maxlen = 7; avglen = 1.828 -Trans hash: total = 1; maxlen = 1; avglen = 0.059 +Variable hash table statistics: + Entries: 100141; Buckets: 87719; Non-empty Buckets: 66299 + Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510 + Growths: 13; Shrinks: 0 +Function hash table statistics: + Entries: 100016; Buckets: 87719; Non-empty Buckets: 63572 + Maxlen: 5; Minlen: 0; Avglen: 1.140; Stddev: 0.934; Avg nonempty len: 1.573 + Growths: 13; Shrinks: 0 +Dedupe hash table statistics: + Entries: 10000; Buckets: 5471; Non-empty Buckets: 4752 + Maxlen: 7; Minlen: 0; Avglen: 1.828; Stddev: 1.302; Avg nonempty len: 2.104 + Growths: 9; Shrinks: 0 +Translation hash table statistics: + Entries: 1; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000 + Growths: 0; Shrinks: 0 Expression nodes allocated: 300096 Expression nodes high-water: 300073 Expression nodes leaked: 0 @@ -23707,10 +23719,22 @@ Parsed expression: isany("foo", 1 + 1, 2:00 + 1, '2021-01-01' + 1, '2021-01-01@1 "f" + "oo" => "foo" isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1 No reminders. - Var hash: total = 1; maxlen = 1; avglen = 0.059 - Func hash: total = 0; maxlen = 0; avglen = 0.000 -Dedup hash: total = 0; maxlen = 0; avglen = 0.000 -Trans hash: total = 1; maxlen = 1; avglen = 0.059 +Variable hash table statistics: + Entries: 1; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000 + Growths: 0; Shrinks: 0 +Function hash table statistics: + Entries: 0; Buckets: 7; Non-empty Buckets: 0 + Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000 + Growths: 0; Shrinks: 0 +Dedupe hash table statistics: + Entries: 0; Buckets: 7; Non-empty Buckets: 0 + Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000 + Growths: 0; Shrinks: 0 +Translation hash table statistics: + Entries: 1; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000 + Growths: 0; Shrinks: 0 Expression nodes allocated: 512 Expression nodes high-water: 499 Expression nodes leaked: 0 @@ -24234,10 +24258,22 @@ $Uy $Was $Wednesday No reminders. - Var hash: total = 1; maxlen = 1; avglen = 0.059 - Func hash: total = 1; maxlen = 1; avglen = 0.059 -Dedup hash: total = 0; maxlen = 0; avglen = 0.000 -Trans hash: total = 2; maxlen = 1; avglen = 0.118 +Variable hash table statistics: + Entries: 1; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000 + Growths: 13; Shrinks: 13 +Function hash table statistics: + Entries: 1; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000 + Growths: 13; Shrinks: 13 +Dedupe hash table statistics: + Entries: 0; Buckets: 7; Non-empty Buckets: 0 + Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000 + Growths: 0; Shrinks: 0 +Translation hash table statistics: + Entries: 2; Buckets: 7; Non-empty Buckets: 1 + Maxlen: 2; Minlen: 0; Avglen: 0.286; Stddev: 0.700; Avg nonempty len: 2.000 + Growths: 13; Shrinks: 13 Expression nodes allocated: 300032 Expression nodes high-water: 300000 Expression nodes leaked: 0