Mercurial > vim
comparison src/debugger.c @ 33119:bede81965821 v9.0.1842
patch 9.0.1842: Need more accurate profiling
Commit: https://github.com/vim/vim/commit/21d3212361f687704acb52cad7c1b9228e7c83f0
Author: Ernie Rael <errael@raelity.com>
Date: Sat Sep 2 15:09:18 2023 +0200
patch 9.0.1842: Need more accurate profiling
Problem: Need more accurate profiling
Solution: Improve profiling results
closes: #12192
Reduce overhead of checking if a function should be profiled,
by caching results of checking (which are done with regexp).
Cache uf_hash for uf_name in ufunc_T.
Cache cleared when regexps are changed.
Break at first match for has_profiling lookup.
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 02 Sep 2023 15:15:06 +0200 |
parents | 695b50472e85 |
children | 3af53f2895dc |
comparison
equal
deleted
inserted
replaced
33118:67f506069462 | 33119:bede81965821 |
---|---|
526 static int has_expr_breakpoint = FALSE; | 526 static int has_expr_breakpoint = FALSE; |
527 | 527 |
528 #ifdef FEAT_PROFILE | 528 #ifdef FEAT_PROFILE |
529 // Profiling uses file and func names similar to breakpoints. | 529 // Profiling uses file and func names similar to breakpoints. |
530 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; | 530 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; |
531 | |
532 // Profiling caches results of regexp lookups for function/script name. | |
533 #define N_PROF_HTAB 2 | |
534 static hashtab_T prof_cache[N_PROF_HTAB]; | |
535 #define PROF_HTAB_FUNCS 0 | |
536 #define PROF_HTAB_FILES 1 | |
537 static int prof_cache_initialized; | |
538 typedef struct profentry_S | |
539 { | |
540 char pen_flags; // cache data booleans: profiling, forceit | |
541 char_u pen_name[1]; // actually longer | |
542 } profentry_T; | |
543 #define PEN_FLAG_PROFILING 1 | |
544 #define PEN_FLAG_FORCEIT 2 | |
545 #define PEN_SET_PROFILING(pe) ((pe)->pen_flags |= PEN_FLAG_PROFILING) | |
546 #define PEN_SET_FORCEIT(pe) ((pe)->pen_flags |= PEN_FLAG_FORCEIT) | |
547 #define PEN_IS_PROFILING(pe) (((pe)->pen_flags & PEN_FLAG_PROFILING) != 0) | |
548 #define PEN_IS_FORCEIT(pe) (((pe)->pen_flags & PEN_FLAG_FORCEIT) != 0) | |
549 | |
550 #define PE2HIKEY(pe) ((pe)->pen_name) | |
551 #define HIKEY2PE(p) ((profentry_T *)((p) - (offsetof(profentry_T, pen_name)))) | |
552 #define HI2PE(hi) HIKEY2PE((hi)->hi_key) | |
553 | |
554 static void prof_clear_cache(void); | |
555 #define PROF_CLEAR_CACHE(gap) do {if ((gap) == &prof_ga) prof_clear_cache();} while (0) | |
556 // Can enable to get some info about profile caching | |
557 // #define PROF_CACHE_LOG | |
558 #else | |
559 #define PROF_CLEAR_CACHE(gap) do {} while (0) | |
531 #endif | 560 #endif |
532 #define DBG_FUNC 1 | 561 #define DBG_FUNC 1 |
533 #define DBG_FILE 2 | 562 #define DBG_FILE 2 |
534 #define DBG_EXPR 3 | 563 #define DBG_EXPR 3 |
535 | 564 |
706 { | 735 { |
707 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; | 736 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; |
708 ++debug_tick; | 737 ++debug_tick; |
709 } | 738 } |
710 ++gap->ga_len; | 739 ++gap->ga_len; |
740 PROF_CLEAR_CACHE(gap); | |
711 } | 741 } |
712 } | 742 } |
713 else | 743 else |
714 { | 744 { |
715 // DBG_EXPR | 745 // DBG_EXPR |
843 #endif | 873 #endif |
844 ++debug_tick; | 874 ++debug_tick; |
845 if (!del_all) | 875 if (!del_all) |
846 break; | 876 break; |
847 } | 877 } |
878 PROF_CLEAR_CACHE(gap); | |
848 | 879 |
849 // If all breakpoints were removed clear the array. | 880 // If all breakpoints were removed clear the array. |
850 if (gap->ga_len == 0) | 881 if (gap->ga_len == 0) |
851 ga_clear(gap); | 882 ga_clear(gap); |
852 if (gap == &dbg_breakp) | 883 if (gap == &dbg_breakp) |
897 { | 928 { |
898 return debuggy_find(file, fname, after, &dbg_breakp, NULL); | 929 return debuggy_find(file, fname, after, &dbg_breakp, NULL); |
899 } | 930 } |
900 | 931 |
901 #if defined(FEAT_PROFILE) || defined(PROTO) | 932 #if defined(FEAT_PROFILE) || defined(PROTO) |
933 #if defined(PROF_CACHE_LOG) | |
934 static int count_lookups[2]; | |
935 #endif | |
902 /* | 936 /* |
903 * Return TRUE if profiling is on for a function or sourced file. | 937 * Return TRUE if profiling is on for a function or sourced file. |
938 * Cache the results of debuggy_find(). | |
939 * Cache is cleared whenever prof_ga.ga_len is changed. | |
904 */ | 940 */ |
905 int | 941 int |
906 has_profiling( | 942 has_profiling( |
907 int file, // TRUE for a file, FALSE for a function | 943 int file, // TRUE for a file, FALSE for a function |
908 char_u *fname, // file or function name | 944 char_u *fname, // file or function name |
909 int *fp) // return: forceit | 945 int *fp, // return: forceit |
910 { | 946 hash_T *hashp) // use/return fname hash, may be NULL |
911 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp) | 947 { |
912 != (linenr_T)0); | 948 if (prof_ga.ga_len == 0 || !prof_cache_initialized) |
949 return debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp) | |
950 != (linenr_T)0; | |
951 | |
952 hash_T hash; | |
953 if (hashp != NULL) | |
954 { | |
955 hash = *hashp; | |
956 if (hash == 0) | |
957 { | |
958 hash = hash_hash(fname); | |
959 *hashp = hash; | |
960 } | |
961 } | |
962 else | |
963 hash = hash_hash(fname); | |
964 | |
965 hashtab_T *ht = &prof_cache[file ? PROF_HTAB_FILES : PROF_HTAB_FUNCS]; | |
966 hashitem_T *hi = hash_lookup(ht, fname, hash); | |
967 profentry_T *pe; | |
968 if (HASHITEM_EMPTY(hi)) | |
969 { | |
970 pe = alloc(offsetof(profentry_T, pen_name) + STRLEN(fname) + 1); | |
971 if (pe == NULL) | |
972 return FALSE; | |
973 STRCPY(pe->pen_name, fname); | |
974 pe->pen_flags = 0; | |
975 // run debuggy_find and capture return and forceit | |
976 int f; | |
977 int lnum = debuggy_find(file, fname, (linenr_T)0, &prof_ga, &f); | |
978 if (lnum) | |
979 { | |
980 PEN_SET_PROFILING(pe); | |
981 if (f) | |
982 PEN_SET_FORCEIT(pe); | |
983 } | |
984 hash_add_item(ht, hi, pe->pen_name, hash); | |
985 #if defined(PROF_CACHE_LOG) | |
986 ch_log(NULL, "has_profiling: %s %s forceit %s, profile %s", | |
987 file ? "file" : "func", fname, | |
988 PEN_IS_FORCEIT(pe) ? "true" : "false", | |
989 PEN_IS_PROFILING(pe) ? "true" : "false"); | |
990 #endif | |
991 } | |
992 else | |
993 pe = HI2PE(hi); | |
994 if (fp) | |
995 *fp = PEN_IS_FORCEIT(pe); | |
996 #if defined(PROF_CACHE_LOG) | |
997 count_lookups[file ? PROF_HTAB_FILES : PROF_HTAB_FUNCS]++; | |
998 #endif | |
999 return PEN_IS_PROFILING(pe); | |
1000 } | |
1001 | |
1002 static void | |
1003 prof_clear_cache() | |
1004 { | |
1005 if (!prof_cache_initialized) | |
1006 { | |
1007 hash_init(&prof_cache[PROF_HTAB_FUNCS]); | |
1008 hash_init(&prof_cache[PROF_HTAB_FILES]); | |
1009 prof_cache_initialized = TRUE; | |
1010 } | |
1011 | |
1012 hashtab_T *ht; | |
1013 for (ht = &prof_cache[0]; ht < &prof_cache[N_PROF_HTAB]; ht++) | |
1014 { | |
1015 if (ht->ht_used > 0) | |
1016 { | |
1017 #if defined(PROF_CACHE_LOG) | |
1018 int idx = ht == &prof_cache[PROF_HTAB_FUNCS] | |
1019 ? PROF_HTAB_FUNCS : PROF_HTAB_FILES; | |
1020 ch_log(NULL, "prof_clear_cache: %s, used: %ld, lookups: %d", | |
1021 idx == PROF_HTAB_FUNCS ? "function" : "script", | |
1022 ht->ht_used, count_lookups[idx]); | |
1023 count_lookups[idx] = 0; | |
1024 #endif | |
1025 hash_clear_all(ht, offsetof(profentry_T, pen_name)); | |
1026 hash_init(ht); | |
1027 } | |
1028 } | |
913 } | 1029 } |
914 #endif | 1030 #endif |
915 | 1031 |
916 /* | 1032 /* |
917 * Common code for dbg_find_breakpoint() and has_profiling(). | 1033 * Common code for dbg_find_breakpoint() and has_profiling(). |
977 lnum = bp->dbg_lnum; | 1093 lnum = bp->dbg_lnum; |
978 if (fp != NULL) | 1094 if (fp != NULL) |
979 *fp = bp->dbg_forceit; | 1095 *fp = bp->dbg_forceit; |
980 } | 1096 } |
981 got_int |= prev_got_int; | 1097 got_int |= prev_got_int; |
1098 #ifdef FEAT_PROFILE | |
1099 if (lnum && gap == &prof_ga) | |
1100 break; | |
1101 #endif | |
982 } | 1102 } |
983 #ifdef FEAT_EVAL | 1103 #ifdef FEAT_EVAL |
984 else if (bp->dbg_type == DBG_EXPR) | 1104 else if (bp->dbg_type == DBG_EXPR) |
985 { | 1105 { |
986 typval_T *tv; | 1106 typval_T *tv; |