0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.1.1684: profiling functionality is spread out

Problem:    Profiling functionality is spread out.
Solution:   Put profiling functionality in profiling.c. (Yegappan Lakshmanan,
            closes #4666)
This commit is contained in:
Bram Moolenaar
2019-07-13 22:59:32 +02:00
parent d5abb4c877
commit fa55cfc69d
20 changed files with 832 additions and 755 deletions

View File

@@ -29,7 +29,6 @@
#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]
/*
* All user-defined functions are found in this hashtable.
@@ -51,13 +50,6 @@ static char *e_funcdict = N_("E717: Dictionary entry already exists");
static char *e_funcref = N_("E718: Funcref required");
static char *e_nofunc = N_("E130: Unknown function: %s");
#ifdef FEAT_PROFILE
static void func_do_profile(ufunc_T *fp);
static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self);
static void prof_func_line(FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self);
static int prof_total_cmp(const void *s1, const void *s2);
static int prof_self_cmp(const void *s1, const void *s2);
#endif
static void funccal_unref(funccall_T *fc, ufunc_T *fp, int force);
void
@@ -1312,6 +1304,12 @@ restore_funccal(void)
}
}
funccall_T *
get_current_funccal(void)
{
return current_funccal;
}
#if defined(EXITFREE) || defined(PROTO)
void
free_all_functions(void)
@@ -2762,36 +2760,6 @@ get_expanded_name(char_u *name, int check)
#endif
#if defined(FEAT_PROFILE) || defined(PROTO)
/*
* Start profiling function "fp".
*/
static void
func_do_profile(ufunc_T *fp)
{
int len = fp->uf_lines.ga_len;
if (!fp->uf_prof_initialized)
{
if (len == 0)
len = 1; /* avoid getting error for allocating zero bytes */
fp->uf_tm_count = 0;
profile_zero(&fp->uf_tm_self);
profile_zero(&fp->uf_tm_total);
if (fp->uf_tml_count == NULL)
fp->uf_tml_count = ALLOC_CLEAR_MULT(int, len);
if (fp->uf_tml_total == NULL)
fp->uf_tml_total = ALLOC_CLEAR_MULT(proftime_T, len);
if (fp->uf_tml_self == NULL)
fp->uf_tml_self = ALLOC_CLEAR_MULT(proftime_T, len);
fp->uf_tml_idx = -1;
if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
|| fp->uf_tml_self == NULL)
return; /* out of memory */
fp->uf_prof_initialized = TRUE;
}
fp->uf_profiling = TRUE;
}
/*
* Dump the profiling results for all functions in file "fd".
@@ -2871,121 +2839,6 @@ func_dump_profile(FILE *fd)
vim_free(sorttab);
}
static void
prof_sort_list(
FILE *fd,
ufunc_T **sorttab,
int st_len,
char *title,
int prefer_self) /* when equal print only self time */
{
int i;
ufunc_T *fp;
fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
fprintf(fd, "count total (s) self (s) function\n");
for (i = 0; i < 20 && i < st_len; ++i)
{
fp = sorttab[i];
prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
prefer_self);
if (fp->uf_name[0] == K_SPECIAL)
fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
else
fprintf(fd, " %s()\n", fp->uf_name);
}
fprintf(fd, "\n");
}
/*
* Print the count and times for one function or function line.
*/
static void
prof_func_line(
FILE *fd,
int count,
proftime_T *total,
proftime_T *self,
int prefer_self) /* when equal print only self time */
{
if (count > 0)
{
fprintf(fd, "%5d ", count);
if (prefer_self && profile_equal(total, self))
fprintf(fd, " ");
else
fprintf(fd, "%s ", profile_msg(total));
if (!prefer_self && profile_equal(total, self))
fprintf(fd, " ");
else
fprintf(fd, "%s ", profile_msg(self));
}
else
fprintf(fd, " ");
}
/*
* Compare function for total time sorting.
*/
static int
prof_total_cmp(const void *s1, const void *s2)
{
ufunc_T *p1, *p2;
p1 = *(ufunc_T **)s1;
p2 = *(ufunc_T **)s2;
return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
}
/*
* Compare function for self time sorting.
*/
static int
prof_self_cmp(const void *s1, const void *s2)
{
ufunc_T *p1, *p2;
p1 = *(ufunc_T **)s1;
p2 = *(ufunc_T **)s2;
return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
}
/*
* Prepare profiling for entering a child or something else that is not
* counted for the script/function itself.
* Should always be called in pair with prof_child_exit().
*/
void
prof_child_enter(
proftime_T *tm) /* place to store waittime */
{
funccall_T *fc = current_funccal;
if (fc != NULL && fc->func->uf_profiling)
profile_start(&fc->prof_child);
script_prof_save(tm);
}
/*
* Take care of time spent in a child.
* Should always be called after prof_child_enter().
*/
void
prof_child_exit(
proftime_T *tm) /* where waittime was stored */
{
funccall_T *fc = current_funccal;
if (fc != NULL && fc->func->uf_profiling)
{
profile_end(&fc->prof_child);
profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
profile_add(&fc->func->uf_tm_children, &fc->prof_child);
profile_add(&fc->func->uf_tml_children, &fc->prof_child);
}
script_prof_restore(tm);
}
#endif /* FEAT_PROFILE */
#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
@@ -3574,71 +3427,6 @@ get_func_line(
return retval;
}
#if defined(FEAT_PROFILE) || defined(PROTO)
/*
* Called when starting to read a function line.
* "sourcing_lnum" must be correct!
* When skipping lines it may not actually be executed, but we won't find out
* until later and we need to store the time now.
*/
void
func_line_start(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func;
if (fp->uf_profiling && sourcing_lnum >= 1
&& sourcing_lnum <= fp->uf_lines.ga_len)
{
fp->uf_tml_idx = sourcing_lnum - 1;
/* Skip continuation lines. */
while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL)
--fp->uf_tml_idx;
fp->uf_tml_execed = FALSE;
profile_start(&fp->uf_tml_start);
profile_zero(&fp->uf_tml_children);
profile_get_wait(&fp->uf_tml_wait);
}
}
/*
* Called when actually executing a function line.
*/
void
func_line_exec(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func;
if (fp->uf_profiling && fp->uf_tml_idx >= 0)
fp->uf_tml_execed = TRUE;
}
/*
* Called when done with a function line.
*/
void
func_line_end(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func;
if (fp->uf_profiling && fp->uf_tml_idx >= 0)
{
if (fp->uf_tml_execed)
{
++fp->uf_tml_count[fp->uf_tml_idx];
profile_end(&fp->uf_tml_start);
profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
profile_self(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start,
&fp->uf_tml_children);
}
fp->uf_tml_idx = -1;
}
}
#endif
/*
* Return TRUE if the currently active function should be ended, because a
* return was encountered or an error occurred. Used inside a ":while".