diff options
author | Marco Hinz <mh.codebro@gmail.com> | 2015-04-14 20:28:08 +0200 |
---|---|---|
committer | Marco Hinz <mh.codebro@gmail.com> | 2015-11-10 02:49:47 +0100 |
commit | 1902ee52ef60d96f2ad043687a1e86bcf7be8aed (patch) | |
tree | 3e65c5fa9849f391cfa0227a25874a0d3798e968 | |
parent | 588bf76650d6d645403e70437c649e7759430c05 (diff) | |
download | rneovim-1902ee52ef60d96f2ad043687a1e86bcf7be8aed.tar.gz rneovim-1902ee52ef60d96f2ad043687a1e86bcf7be8aed.tar.bz2 rneovim-1902ee52ef60d96f2ad043687a1e86bcf7be8aed.zip |
Add ":profile stop"
This writes the logfile and stops profiling.
-rw-r--r-- | runtime/doc/repeat.txt | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 45 | ||||
-rw-r--r-- | src/nvim/eval.h | 41 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 83 |
4 files changed, 115 insertions, 57 deletions
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index eae2c3867e..d029391c60 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -586,6 +586,9 @@ For example, to profile the one_script.vim script file: > If {fname} already exists it will be silently overwritten. The variable |v:profiling| is set to one. +:prof[ile] stop + Write the logfile and stop profiling. + :prof[ile] pause Don't profile until the following ":profile continue". Can be used when doing something that should not be counted (e.g., an diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8534cf5319..045d513a4a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -229,50 +229,11 @@ static int echo_attr = 0; /* attributes used for ":echo" */ #define GLV_QUIET TFN_QUIET /* no error messages */ #define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */ -/* - * Structure to hold info for a user function. - */ -typedef struct ufunc ufunc_T; - -struct ufunc { - int uf_varargs; /* variable nr of arguments */ - int uf_flags; - int uf_calls; /* nr of active calls */ - garray_T uf_args; /* arguments */ - garray_T uf_lines; /* function lines */ - int uf_profiling; /* TRUE when func is being profiled */ - /* profiling the function as a whole */ - int uf_tm_count; /* nr of calls */ - proftime_T uf_tm_total; /* time spent in function + children */ - proftime_T uf_tm_self; /* time spent in function itself */ - proftime_T uf_tm_children; /* time spent in children this call */ - /* profiling the function per line */ - int *uf_tml_count; /* nr of times line was executed */ - proftime_T *uf_tml_total; /* time spent in a line + children */ - proftime_T *uf_tml_self; /* time spent in a line itself */ - proftime_T uf_tml_start; /* start time for current line */ - proftime_T uf_tml_children; /* time spent in children for this line */ - proftime_T uf_tml_wait; /* start wait time for current line */ - int uf_tml_idx; /* index of line being timed; -1 if none */ - int uf_tml_execed; /* line being timed was executed */ - scid_T uf_script_ID; /* ID of script where function was defined, - used for s: variables */ - int uf_refcount; /* for numbered function: reference count */ - char_u uf_name[1]; /* name of function (actually longer); can - start with <SNR>123_ (<SNR> is K_SPECIAL - KS_EXTRA KE_SNR) */ -}; - /* function flags */ #define FC_ABORT 1 /* abort function on error */ #define FC_RANGE 2 /* function accepts range */ #define FC_DICT 4 /* Dict function, uses "self" */ -/* - * All user-defined functions are found in this hashtable. - */ -static hashtab_T func_hashtab; - /* The names of packages that once were loaded are remembered. */ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; @@ -280,12 +241,6 @@ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; static dict_T *first_dict = NULL; /* list of all dicts */ static list_T *first_list = NULL; /* list of all lists */ -/* From user function to hashitem and back. */ -static ufunc_T dumuf; -#define UF2HIKEY(fp) ((fp)->uf_name) -#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) -#define HI2UF(hi) HIKEY2UF((hi)->hi_key) - #define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] #define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 864daed716..8ccf71068c 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -5,6 +5,47 @@ #include "nvim/profile.h" +// All user-defined functions are found in this hashtable. +EXTERN hashtab_T func_hashtab; + +// Structure to hold info for a user function. +typedef struct ufunc ufunc_T; + +struct ufunc { + int uf_varargs; ///< variable nr of arguments + int uf_flags; + int uf_calls; ///< nr of active calls + garray_T uf_args; ///< arguments + garray_T uf_lines; ///< function lines + int uf_profiling; ///< true when func is being profiled + // Profiling the function as a whole. + int uf_tm_count; ///< nr of calls + proftime_T uf_tm_total; ///< time spent in function + children + proftime_T uf_tm_self; ///< time spent in function itself + proftime_T uf_tm_children; ///< time spent in children this call + // Profiling the function per line. + int *uf_tml_count; ///< nr of times line was executed + proftime_T *uf_tml_total; ///< time spent in a line + children + proftime_T *uf_tml_self; ///< time spent in a line itself + proftime_T uf_tml_start; ///< start time for current line + proftime_T uf_tml_children; ///< time spent in children for this line + proftime_T uf_tml_wait; ///< start wait time for current line + int uf_tml_idx; ///< index of line being timed; -1 if none + int uf_tml_execed; ///< line being timed was executed + scid_T uf_script_ID; ///< ID of script where function was defined, + // used for s: variables + int uf_refcount; ///< for numbered function: reference count + char_u uf_name[1]; ///< name of function (actually longer); can + // start with <SNR>123_ (<SNR> is K_SPECIAL + // KS_EXTRA KE_SNR) +}; + +// From user function to hashitem and back. +EXTERN ufunc_T dumuf; +#define UF2HIKEY(fp) ((fp)->uf_name) +#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) +#define HI2UF(hi) HIKEY2UF((hi)->hi_key) + /* Defines for Vim variables. These must match vimvars[] in eval.c! */ enum { VV_COUNT, diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 46bd8685d9..ba17423475 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -761,9 +761,14 @@ void ex_profile(exarg_T *eap) do_profiling = PROF_YES; profile_set_wait(profile_zero()); set_vim_var_nr(VV_PROFILING, 1L); - } else if (do_profiling == PROF_NONE) + } else if (do_profiling == PROF_NONE) { EMSG(_("E750: First use \":profile start {fname}\"")); - else if (STRCMP(eap->arg, "pause") == 0) { + } else if (STRCMP(eap->arg, "stop") == 0) { + profile_dump(); + do_profiling = PROF_NONE; + set_vim_var_nr(VV_PROFILING, 0L); + profile_reset(); + } else if (STRCMP(eap->arg, "pause") == 0) { if (do_profiling == PROF_YES) pause_time = profile_start(); do_profiling = PROF_PAUSED; @@ -818,12 +823,13 @@ static enum { } pexpand_what; static char *pexpand_cmds[] = { - "start", - "pause", "continue", - "func", - "file", "dump", + "file", + "func", + "pause", + "start", + "stop", NULL }; @@ -887,10 +893,63 @@ void profile_dump(void) } } -/* - * Start profiling script "fp". - */ -static void script_do_profile(scriptitem_T *si) +/// Reset all profiling information. +static void profile_reset(void) +{ + // Reset sourced files. + for (int id = 1; id <= script_items.ga_len; id++) { + scriptitem_T *si = &SCRIPT_ITEM(id); + if (si->sn_prof_on) { + si->sn_prof_on = 0; + si->sn_pr_force = 0; + si->sn_pr_child = profile_zero(); + si->sn_pr_nest = 0; + si->sn_pr_count = 0; + si->sn_pr_total = profile_zero(); + si->sn_pr_self = profile_zero(); + si->sn_pr_start = profile_zero(); + si->sn_pr_children = profile_zero(); + ga_clear(&si->sn_prl_ga); + si->sn_prl_start = profile_zero(); + si->sn_prl_children = profile_zero(); + si->sn_prl_wait = profile_zero(); + si->sn_prl_idx = -1; + si->sn_prl_execed = 0; + } + } + + // Reset functions. + size_t n = func_hashtab.ht_used; + hashitem_T *hi = func_hashtab.ht_array; + + for (; n > (size_t)0; hi++) { + if (!HASHITEM_EMPTY(hi)) { + n--; + ufunc_T *uf = HI2UF(hi); + if (uf->uf_profiling) { + uf->uf_profiling = 0; + uf->uf_tm_count = 0; + uf->uf_tm_total = profile_zero(); + uf->uf_tm_self = profile_zero(); + uf->uf_tm_children = profile_zero(); + uf->uf_tml_count = NULL; + uf->uf_tml_total = NULL; + uf->uf_tml_self = NULL; + uf->uf_tml_start = profile_zero(); + uf->uf_tml_children = profile_zero(); + uf->uf_tml_wait = profile_zero(); + uf->uf_tml_idx = -1; + uf->uf_tml_execed = 0; + } + } + } + + xfree(profile_fname); + profile_fname = NULL; +} + +/// Start profiling a script. +static void profile_init(scriptitem_T *si) { si->sn_pr_count = 0; si->sn_pr_total = profile_zero(); @@ -2506,8 +2565,8 @@ do_source ( int forceit; /* Check if we do profiling for this script. */ - if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) { - script_do_profile(si); + if (!si->sn_prof_on && has_profiling(true, si->sn_name, &forceit)) { + profile_init(si); si->sn_pr_force = forceit; } if (si->sn_prof_on) { |