diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-07-13 22:59:32 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-07-13 22:59:32 +0200 |
commit | fa55cfc69d2b14761e2a8bd85bc1e0d82df770aa (patch) | |
tree | 3420b78d3aa0d58695f9a660592b655ac2f22fb1 | |
parent | d5abb4c87727eecb71b0e8ffdda60fc9598272f3 (diff) |
patch 8.1.1684: profiling functionality is spread outv8.1.1684
Problem: Profiling functionality is spread out.
Solution: Put profiling functionality in profiling.c. (Yegappan Lakshmanan,
closes #4666)
-rw-r--r-- | Filelist | 1 | ||||
-rw-r--r-- | src/Make_cyg_ming.mak | 1 | ||||
-rw-r--r-- | src/Make_dice.mak | 4 | ||||
-rw-r--r-- | src/Make_manx.mak | 6 | ||||
-rw-r--r-- | src/Make_morph.mak | 1 | ||||
-rw-r--r-- | src/Make_mvc.mak | 4 | ||||
-rw-r--r-- | src/Make_sas.mak | 5 | ||||
-rw-r--r-- | src/Make_vms.mms | 23 | ||||
-rw-r--r-- | src/Makefile | 11 | ||||
-rw-r--r-- | src/README.md | 3 | ||||
-rw-r--r-- | src/ex_cmds2.c | 505 | ||||
-rw-r--r-- | src/globals.h | 3 | ||||
-rw-r--r-- | src/profiler.c | 679 | ||||
-rw-r--r-- | src/proto.h | 3 | ||||
-rw-r--r-- | src/proto/ex_cmds2.pro | 24 | ||||
-rw-r--r-- | src/proto/profiler.pro | 34 | ||||
-rw-r--r-- | src/proto/userfunc.pro | 3 | ||||
-rw-r--r-- | src/structs.h | 51 | ||||
-rw-r--r-- | src/userfunc.c | 224 | ||||
-rw-r--r-- | src/version.c | 2 |
20 files changed, 832 insertions, 755 deletions
@@ -80,6 +80,7 @@ SRC_ALL = \ src/option.h \ src/popupmnu.c \ src/popupwin.c \ + src/profiler.c \ src/quickfix.c \ src/regexp.c \ src/regexp_nfa.c \ diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index d0769c39ee..b689df8ad6 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -752,6 +752,7 @@ OBJ = \ $(OUTDIR)/pathdef.o \ $(OUTDIR)/popupmnu.o \ $(OUTDIR)/popupwin.o \ + $(OUTDIR)/profiler.o \ $(OUTDIR)/quickfix.o \ $(OUTDIR)/regexp.o \ $(OUTDIR)/screen.o \ diff --git a/src/Make_dice.mak b/src/Make_dice.mak index 440955eb34..f95262ebb5 100644 --- a/src/Make_dice.mak +++ b/src/Make_dice.mak @@ -71,6 +71,7 @@ SRC = \ option.c \ os_amiga.c \ popupmnu.c \ + profiler.c \ quickfix.c \ regexp.c \ screen.c \ @@ -134,6 +135,7 @@ OBJ = o/arabic.o \ o/option.o \ o/os_amiga.o \ o/popupmnu.o \ + o/profiler.o \ o/quickfix.o \ o/regexp.o \ o/screen.o \ @@ -266,6 +268,8 @@ o/os_amiga.o: os_amiga.c $(SYMS) os_amiga.h o/popupmnu.o: popupmnu.c $(SYMS) +o/profiler.o: profiler.c $(SYMS) + o/quickfix.o: quickfix.c $(SYMS) o/regexp.o: regexp.c $(SYMS) regexp.h diff --git a/src/Make_manx.mak b/src/Make_manx.mak index 211d8ccebf..e3babe567d 100644 --- a/src/Make_manx.mak +++ b/src/Make_manx.mak @@ -81,6 +81,7 @@ SRC = arabic.c \ option.c \ os_amiga.c \ popupmnu.c \ + profiler.c \ quickfix.c \ regexp.c \ screen.c \ @@ -146,6 +147,7 @@ OBJ = obj/arabic.o \ obj/option.o \ obj/os_amiga.o \ obj/popupmnu.o \ + obj/profiler.o \ obj/quickfix.o \ obj/regexp.o \ obj/screen.o \ @@ -209,6 +211,7 @@ PRO = proto/arabic.pro \ proto/option.pro \ proto/os_amiga.pro \ proto/popupmnu.pro \ + proto/profiler.pro \ proto/quickfix.pro \ proto/regexp.pro \ proto/screen.pro \ @@ -410,6 +413,9 @@ obj/os_amiga.o: os_amiga.c obj/popupmnu.o: popupmnu.c $(CCSYM) $@ popupmnu.c +obj/profiler.o: profiler.c + $(CCSYM) $@ profiler.c + obj/quickfix.o: quickfix.c $(CCSYM) $@ quickfix.c diff --git a/src/Make_morph.mak b/src/Make_morph.mak index 1eb5ff52d7..7bd39faa3e 100644 --- a/src/Make_morph.mak +++ b/src/Make_morph.mak @@ -69,6 +69,7 @@ SRC = arabic.c \ option.c \ os_amiga.c \ popupmnu.c \ + profiler.c \ quickfix.c \ regexp.c \ screen.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 04e566bbbc..4a6aaa995f 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -761,6 +761,7 @@ OBJ = \ $(OUTDIR)\pathdef.obj \ $(OUTDIR)\popupmnu.obj \ $(OUTDIR)\popupwin.obj \ + $(OUTDIR)\profiler.obj \ $(OUTDIR)\quickfix.obj \ $(OUTDIR)\regexp.obj \ $(OUTDIR)\screen.obj \ @@ -1595,6 +1596,8 @@ $(OUTDIR)/popupmnu.obj: $(OUTDIR) popupmnu.c $(INCL) $(OUTDIR)/popupwin.obj: $(OUTDIR) popupwin.c $(INCL) +$(OUTDIR)/profiler.obj: $(OUTDIR) profiler.c $(INCL) + $(OUTDIR)/quickfix.obj: $(OUTDIR) quickfix.c $(INCL) $(OUTDIR)/regexp.obj: $(OUTDIR) regexp.c regexp_nfa.c $(INCL) @@ -1763,6 +1766,7 @@ proto.h: \ proto/os_win32.pro \ proto/popupmnu.pro \ proto/popupwin.pro \ + proto/profiler.pro \ proto/quickfix.pro \ proto/regexp.pro \ proto/screen.pro \ diff --git a/src/Make_sas.mak b/src/Make_sas.mak index 7090119d75..607f48448c 100644 --- a/src/Make_sas.mak +++ b/src/Make_sas.mak @@ -134,6 +134,7 @@ SRC = \ option.c \ os_amiga.c \ popupmnu.c \ + profiler.c \ quickfix.c \ regexp.c \ screen.c \ @@ -198,6 +199,7 @@ OBJ = \ option.o \ os_amiga.o \ popupmnu.o \ + profiler.o \ quickfix.o \ regexp.o \ screen.o \ @@ -262,6 +264,7 @@ PRO = \ proto/option.pro \ proto/os_amiga.pro \ proto/popupmnu.pro \ + proto/profiler.pro \ proto/quickfix.pro \ proto/regexp.pro \ proto/screen.pro \ @@ -425,6 +428,8 @@ os_amiga.o: os_amiga.c proto/os_amiga.pro: os_amiga.c popupmnu.o: popupmnu.c proto/popupmnu.pro: popupmnu.c +profiler.o: profiler.c +proto/profiler.pro: profiler.c quickfix.o: quickfix.c proto/quickfix.pro: quickfix.c regexp.o: regexp.c diff --git a/src/Make_vms.mms b/src/Make_vms.mms index f01d325c0a..b7063e158d 100644 --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -313,10 +313,10 @@ SRC = arabic.c autocmd.c beval.c blob.c blowfish.c buffer.c change.c charset.c \ if_cscope.c if_xcmdsrv.c fileio.c findfile.c fold.c getchar.c \ hardcopy.c hashtab.c indent.c insexpand.c json.c list.c main.c mark.c \ menu.c mbyte.c memfile.c memline.c message.c misc1.c misc2.c move.c \ - normal.c ops.c option.c popupmnu.c popupwin.c, quickfix.c regexp.c search.c \ - sha256.c sign.c spell.c spellfile.c syntax.c tag.c term.c termlib.c \ - textprop.c ui.c undo.c usercmd.c userfunc.c version.c screen.c \ - window.c os_unix.c os_vms.c pathdef.c \ + normal.c ops.c option.c popupmnu.c popupwin.c profiler.c quickfix.c \ + regexp.c search.c sha256.c sign.c spell.c spellfile.c syntax.c tag.c \ + term.c termlib.c textprop.c ui.c undo.c usercmd.c userfunc.c \ + version.c screen.c window.c os_unix.c os_vms.c pathdef.c \ $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) \ $(RUBY_SRC) $(HANGULIN_SRC) $(MZSCH_SRC) $(XDIFF_SRC) @@ -327,11 +327,12 @@ OBJ = arabic.obj autocmd.obj beval.obj blob.obj blowfish.obj buffer.obj change. fileio.obj findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \ indent.obj insexpand.obj json.obj list.obj main.obj mark.obj \ menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \ - move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj popupwin.obj\ - quickfix.obj regexp.obj search.obj sha256.obj sign.obj spell.obj \ - spellfile.obj syntax.obj tag.obj term.obj termlib.obj textprop.obj \ - ui.obj undo.obj usercmd.obj userfunc.obj screen.obj version.obj \ - window.obj os_unix.obj os_vms.obj pathdef.obj if_mzsch.obj \ + move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj \ + popupwin.obj profiler.obj quickfix.obj regexp.obj search.obj \ + sha256.obj sign.obj spell.obj spellfile.obj syntax.obj tag.obj \ + term.obj termlib.obj textprop.obj ui.obj undo.obj usercmd.obj \ + userfunc.obj screen.obj version.obj window.obj os_unix.obj os_vms.obj \ + pathdef.obj if_mzsch.obj \ $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \ $(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ) $(XDIFF_OBJ) @@ -692,6 +693,10 @@ popupwin.obj : popupwin.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h \ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ globals.h +profiler.obj : profiler.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ + globals.h quickfix.obj : quickfix.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h \ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ diff --git a/src/Makefile b/src/Makefile index 9c4a42893b..3f91e5bf1f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -521,6 +521,7 @@ CClink = $(CC) # gpm - For mouse support on Linux console via gpm # Uncomment this when you do not want to include gpm support, even # though you have gpm libraries and includes. +# For Debian/Ubuntu gpm support requires the libgpm-dev package. #CONF_OPT_GPM = --disable-gpm # sysmouse - For mouse support on FreeBSD and DragonFly console via sysmouse @@ -1626,6 +1627,7 @@ BASIC_SRC = \ auto/pathdef.c \ popupmnu.c \ popupwin.c \ + profiler.c \ pty.c \ quickfix.c \ regexp.c \ @@ -1742,6 +1744,7 @@ OBJ_COMMON = \ objects/pathdef.o \ objects/popupmnu.o \ objects/popupwin.o \ + objects/profiler.o \ objects/pty.o \ objects/quickfix.o \ objects/regexp.o \ @@ -1883,6 +1886,7 @@ PRO_AUTO = \ os_unix.pro \ popupmnu.pro \ popupwin.pro \ + profiler.pro \ pty.pro \ quickfix.pro \ regexp.pro \ @@ -3222,6 +3226,9 @@ objects/popupmnu.o: popupmnu.c objects/popupwin.o: popupwin.c $(CCC) -o $@ popupwin.c +objects/profiler.o: profiler.c + $(CCC) -o $@ profiler.c + objects/pty.o: pty.c $(CCC) -o $@ pty.c @@ -3633,6 +3640,10 @@ objects/popupwin.o: popupwin.c vim.h protodef.h auto/config.h feature.h os_unix. auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h +objects/profiler.o: profiler.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h objects/pty.o: pty.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/README.md b/src/README.md index ff9f93ac6d..87361097fe 100644 --- a/src/README.md +++ b/src/README.md @@ -44,13 +44,14 @@ menu.c | menus message.c | (error) messages ops.c | handling operators ("d", "y", "p") option.c | options +profiler.c | vim script profiler quickfix.c | quickfix commands (":make", ":cn") regexp.c | pattern matching screen.c | updating the windows search.c | pattern searching sign.c | signs spell.c | spell checking -syntax.c | syntax and other highlighting +syntax.c | syntax and other highlighting tag.c | tags term.c | terminal handling, termcap codes undo.c | undo and redo diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index fb26b2aa4f..77ff08cf7c 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -16,215 +16,7 @@ static void cmd_source(char_u *fname, exarg_T *eap); -#ifdef FEAT_EVAL -/* Growarray to store info about already sourced scripts. - * For Unix also store the dev/ino, so that we don't have to stat() each - * script when going through the list. */ -typedef struct scriptitem_S -{ - char_u *sn_name; -# ifdef UNIX - int sn_dev_valid; - dev_t sn_dev; - ino_t sn_ino; -# endif -# ifdef FEAT_PROFILE - int sn_prof_on; /* TRUE when script is/was profiled */ - int sn_pr_force; /* forceit: profile functions in this script */ - proftime_T sn_pr_child; /* time set when going into first child */ - int sn_pr_nest; /* nesting for sn_pr_child */ - /* profiling the script as a whole */ - int sn_pr_count; /* nr of times sourced */ - proftime_T sn_pr_total; /* time spent in script + children */ - proftime_T sn_pr_self; /* time spent in script itself */ - proftime_T sn_pr_start; /* time at script start */ - proftime_T sn_pr_children; /* time in children after script start */ - /* profiling the script per line */ - garray_T sn_prl_ga; /* things stored for every line */ - proftime_T sn_prl_start; /* start time for current line */ - proftime_T sn_prl_children; /* time spent in children for this line */ - proftime_T sn_prl_wait; /* wait start time for current line */ - int sn_prl_idx; /* index of line being timed; -1 if none */ - int sn_prl_execed; /* line being timed was executed */ -# endif -} scriptitem_T; - -static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL}; -#define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) - -# ifdef FEAT_PROFILE -/* Struct used in sn_prl_ga for every line of a script. */ -typedef struct sn_prl_S -{ - int snp_count; /* nr of times line was executed */ - proftime_T sn_prl_total; /* time spent in a line + children */ - proftime_T sn_prl_self; /* time spent in a line itself */ -} sn_prl_T; - -# define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)]) -# endif -#endif - #if defined(FEAT_EVAL) || defined(PROTO) -# if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO) -/* - * Store the current time in "tm". - */ - void -profile_start(proftime_T *tm) -{ -# ifdef MSWIN - QueryPerformanceCounter(tm); -# else - gettimeofday(tm, NULL); -# endif -} - -/* - * Compute the elapsed time from "tm" till now and store in "tm". - */ - void -profile_end(proftime_T *tm) -{ - proftime_T now; - -# ifdef MSWIN - QueryPerformanceCounter(&now); - tm->QuadPart = now.QuadPart - tm->QuadPart; -# else - gettimeofday(&now, NULL); - tm->tv_usec = now.tv_usec - tm->tv_usec; - tm->tv_sec = now.tv_sec - tm->tv_sec; - if (tm->tv_usec < 0) - { - tm->tv_usec += 1000000; - --tm->tv_sec; - } -# endif -} - -/* - * Subtract the time "tm2" from "tm". - */ - void -profile_sub(proftime_T *tm, proftime_T *tm2) -{ -# ifdef MSWIN - tm->QuadPart -= tm2->QuadPart; -# else - tm->tv_usec -= tm2->tv_usec; - tm->tv_sec -= tm2->tv_sec; - if (tm->tv_usec < 0) - { - tm->tv_usec += 1000000; - --tm->tv_sec; - } -# endif -} - -/* - * Return a string that represents the time in "tm". - * Uses a static buffer! - */ - char * -profile_msg(proftime_T *tm) -{ - static char buf[50]; - -# ifdef MSWIN - LARGE_INTEGER fr; - - QueryPerformanceFrequency(&fr); - sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart); -# else - sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec); -# endif - return buf; -} - -# if defined(FEAT_FLOAT) || defined(PROTO) -/* - * Return a float that represents the time in "tm". - */ - float_T -profile_float(proftime_T *tm) -{ -# ifdef MSWIN - LARGE_INTEGER fr; - - QueryPerformanceFrequency(&fr); - return (float_T)tm->QuadPart / (float_T)fr.QuadPart; -# else - return (float_T)tm->tv_sec + (float_T)tm->tv_usec / 1000000.0; -# endif -} -# endif - -/* - * Put the time "msec" past now in "tm". - */ - void -profile_setlimit(long msec, proftime_T *tm) -{ - if (msec <= 0) /* no limit */ - profile_zero(tm); - else - { -# ifdef MSWIN - LARGE_INTEGER fr; - - QueryPerformanceCounter(tm); - QueryPerformanceFrequency(&fr); - tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart); -# else - long usec; - - gettimeofday(tm, NULL); - usec = (long)tm->tv_usec + (long)msec * 1000; - tm->tv_usec = usec % 1000000L; - tm->tv_sec += usec / 1000000L; -# endif - } -} - -/* - * Return TRUE if the current time is past "tm". - */ - int -profile_passed_limit(proftime_T *tm) -{ - proftime_T now; - -# ifdef MSWIN - if (tm->QuadPart == 0) /* timer was not set */ - return FALSE; - QueryPerformanceCounter(&now); - return (now.QuadPart > tm->QuadPart); -# else - if (tm->tv_sec == 0) /* timer was not set */ - return FALSE; - gettimeofday(&now, NULL); - return (now.tv_sec > tm->tv_sec - || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec)); -# endif -} - -/* - * Set the time in "tm" to zero. - */ - void -profile_zero(proftime_T *tm) -{ -# ifdef MSWIN - tm->QuadPart = 0; -# else - tm->tv_usec = 0; - tm->tv_sec = 0; -# endif -} - -# endif /* FEAT_PROFILE || FEAT_RELTIME */ - # if defined(FEAT_TIMERS) || defined(PROTO) static timer_T *first_timer = NULL; static long last_timer_id = 0; @@ -603,270 +395,11 @@ timer_free_all() # endif # endif -#if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT) && defined(FEAT_PROFILE) -# if defined(HAVE_MATH_H) -# include <math.h> -# endif - -/* - * Divide the time "tm" by "count" and store in "tm2". - */ - void -profile_divide(proftime_T *tm, int count, proftime_T *tm2) -{ - if (count == 0) - profile_zero(tm2); - else - { -# ifdef MSWIN - tm2->QuadPart = tm->QuadPart / count; -# else - double usec = (tm->tv_sec * 1000000.0 + tm->tv_usec) / count; - - tm2->tv_sec = floor(usec / 1000000.0); - tm2->tv_usec = vim_round(usec - (tm2->tv_sec * 1000000.0)); -# endif - } -} -#endif - # if defined(FEAT_PROFILE) || defined(PROTO) /* - * Functions for profiling. - */ -static void script_dump_profile(FILE *fd); -static proftime_T prof_wait_time; - -/* - * Add the time "tm2" to "tm". - */ - void -profile_add(proftime_T *tm, proftime_T *tm2) -{ -# ifdef MSWIN - tm->QuadPart += tm2->QuadPart; -# else - tm->tv_usec += tm2->tv_usec; - tm->tv_sec += tm2->tv_sec; - if (tm->tv_usec >= 1000000) - { - tm->tv_usec -= 1000000; - ++tm->tv_sec; - } -# endif -} - -/* - * Add the "self" time from the total time and the children's time. - */ - void -profile_self(proftime_T *self, proftime_T *total, proftime_T *children) -{ - /* Check that the result won't be negative. Can happen with recursive - * calls. */ -#ifdef MSWIN - if (total->QuadPart <= children->QuadPart) - return; -#else - if (total->tv_sec < children->tv_sec - || (total->tv_sec == children->tv_sec - && total->tv_usec <= children->tv_usec)) - return; -#endif - profile_add(self, total); - profile_sub(self, children); -} - -/* - * Get the current waittime. - */ - void -profile_get_wait(proftime_T *tm) -{ - *tm = prof_wait_time; -} - -/* - * Subtract the passed waittime since "tm" from "tma". - */ - void -profile_sub_wait(proftime_T *tm, proftime_T *tma) -{ - proftime_T tm3 = prof_wait_time; - - profile_sub(&tm3, tm); - profile_sub(tma, &tm3); -} - -/* - * Return TRUE if "tm1" and "tm2" are equal. - */ - int -profile_equal(proftime_T *tm1, proftime_T *tm2) -{ -# ifdef MSWIN - return (tm1->QuadPart == tm2->QuadPart); -# else - return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec); -# endif -} - -/* - * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2" - */ - int -profile_cmp(const proftime_T *tm1, const proftime_T *tm2) -{ -# ifdef MSWIN - return (int)(tm2->QuadPart - tm1->QuadPart); -# else - if (tm1->tv_sec == tm2->tv_sec) - return tm2->tv_usec - tm1->tv_usec; - return tm2->tv_sec - tm1->tv_sec; -# endif -} - -static char_u *profile_fname = NULL; -static proftime_T pause_time; - -/* - * ":profile cmd args" - */ - void -ex_profile(exarg_T *eap) -{ - char_u *e; - int len; - - e = skiptowhite(eap->arg); - len = (int)(e - eap->arg); - e = skipwhite(e); - - if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL) - { - vim_free(profile_fname); - profile_fname = expand_env_save_opt(e, TRUE); - do_profiling = PROF_YES; - profile_zero(&prof_wait_time); - set_vim_var_nr(VV_PROFILING, 1L); - } - else if (do_profiling == PROF_NONE) - emsg(_("E750: First use \":profile start {fname}\"")); - else if (STRCMP(eap->arg, "pause") == 0) - { - if (do_profiling == PROF_YES) - profile_start(&pause_time); - do_profiling = PROF_PAUSED; - } - else if (STRCMP(eap->arg, "continue") == 0) - { - if (do_profiling == PROF_PAUSED) - { - profile_end(&pause_time); - profile_add(&prof_wait_time, &pause_time); - } - do_profiling = PROF_YES; - } - else - { - /* The rest is similar to ":breakadd". */ - ex_breakadd(eap); - } -} - -/* Command line expansion for :profile. */ -static enum -{ - PEXP_SUBCMD, /* expand :profile sub-commands */ - PEXP_FUNC /* expand :profile func {funcname} */ -} pexpand_what; - -static char *pexpand_cmds[] = { - "start", -#define PROFCMD_START 0 - "pause", -#define PROFCMD_PAUSE 1 - "continue", -#define PROFCMD_CONTINUE 2 - "func", -#define PROFCMD_FUNC 3 - "file", -#define PROFCMD_FILE 4 - NULL -#define PROFCMD_LAST 5 -}; - -/* - * Function given to ExpandGeneric() to obtain the profile command - * specific expansion. - */ - char_u * -get_profile_name(expand_T *xp UNUSED, int idx) -{ - switch (pexpand_what) - { - case PEXP_SUBCMD: - return (char_u *)pexpand_cmds[idx]; - /* case PEXP_FUNC: TODO */ - default: - return NULL; - } -} - -/* - * Handle command line completion for :profile command. - */ - void -set_context_in_profile_cmd(expand_T *xp, char_u *arg) -{ - char_u *end_subcmd; - - /* Default: expand subcommands. */ - xp->xp_context = EXPAND_PROFILE; - pexpand_what = PEXP_SUBCMD; - xp->xp_pattern = arg; - - end_subcmd = skiptowhite(arg); - if (*end_subcmd == NUL) - return; - - if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) - { - xp->xp_context = EXPAND_FILES; - xp->xp_pattern = skipwhite(end_subcmd); - return; - } - - /* TODO: expand function names after "func" */ - xp->xp_context = EXPAND_NOTHING; -} - -/* - * Dump the profiling info. - */ - void -profile_dump(void) -{ - FILE *fd; - - if (profile_fname != NULL) - { - fd = mch_fopen((char *)profile_fname, "w"); - if (fd == NULL) - semsg(_(e_notopen), profile_fname); - else - { - script_dump_profile(fd); - func_dump_profile(fd); - fclose(fd); - } - } -} - -/* * Start profiling script "fp". */ - static void + void script_do_profile(scriptitem_T *si) { si->sn_pr_count = 0; @@ -918,31 +451,10 @@ script_prof_restore(proftime_T *tm) } } -static proftime_T inchar_time; - -/* - * Called when starting to wait for the user to type a character. - */ - void -prof_inchar_enter(void) -{ - profile_start(&inchar_time); -} - -/* - * Called when finished waiting for the user to type a character. - */ - void -prof_inchar_exit(void) -{ - profile_end(&inchar_time); - profile_add(&prof_wait_time, &inchar_time); -} - /* * Dump the profiling results for all scripts in file "fd". */ - static void + void script_dump_profile(FILE *fd) { int id; @@ -1016,19 +528,6 @@ script_dump_profile(FILE *fd) } } } - -/* - * Return TRUE when a function defined in the current script should be - * profiled. - */ - int -prof_def_func(void) -{ - if (current_sctx.sc_sid > 0) - return SCRIPT_ITEM(current_sctx.sc_sid).sn_pr_force; - return FALSE; -} - # endif #endif diff --git a/src/globals.h b/src/globals.h index 3562b5ee6c..0c2df36b8e 100644 --- a/src/globals.h +++ b/src/globals.h @@ -252,6 +252,9 @@ EXTERN int debug_backtrace_level INIT(= 0); /* breakpoint backtrace level */ # ifdef FEAT_PROFILE EXTERN int do_profiling INIT(= PROF_NONE); /* PROF_ values */ # endif +EXTERN garray_T script_items INIT(= {0 COMMA 0 COMMA sizeof(scriptitem_T) COMMA 4 COMMA NULL}); +#define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) +#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] /* * The exception currently being thrown. Used to pass an exception to diff --git a/src/profiler.c b/src/profiler.c new file mode 100644 index 0000000000..dab21bceb4 --- /dev/null +++ b/src/profiler.c @@ -0,0 +1,679 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * profiler.c: vim script profiler + */ + +#include "vim.h" + +#if defined(FEAT_EVAL) || defined(PROTO) +# if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO) +/* + * Store the current time in "tm". + */ + void +profile_start(proftime_T *tm) +{ +# ifdef MSWIN + QueryPerformanceCounter(tm); +# else + gettimeofday(tm, NULL); +# endif +} + +/* + * Compute the elapsed time from "tm" till now and store in "tm". + */ + void +profile_end(proftime_T *tm) +{ + proftime_T now; + +# ifdef MSWIN + QueryPerformanceCounter(&now); + tm->QuadPart = now.QuadPart - tm->QuadPart; +# else + gettimeofday(&now, NULL); + tm->tv_usec = now.tv_usec - tm->tv_usec; + tm->tv_sec = now.tv_sec - tm->tv_sec; + if (tm->tv_usec < 0) + { + tm->tv_usec += 1000000; + --tm->tv_sec; + } +# endif +} + +/* + * Subtract the time "tm2" from "tm". + */ + void +profile_sub(proftime_T *tm, proftime_T *tm2) +{ +# ifdef MSWIN + tm->QuadPart -= tm2->QuadPart; +# else + tm->tv_usec -= tm2->tv_usec; + tm->tv_sec -= tm2->tv_sec; + if (tm->tv_usec < 0) + { + tm->tv_usec += 1000000; + --tm->tv_sec; + } +# endif +} + +/* + * Return a string that represents the time in "tm". + * Uses a static buffer! + */ + char * +profile_msg(proftime_T *tm) +{ + static char buf[50]; + +# ifdef MSWIN + LARGE_INTEGER fr; + + QueryPerformanceFrequency(&fr); + sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart); +# else + sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec); +# endif + return buf; +} + +# if defined(FEAT_FLOAT) || defined(PROTO) +/* + * Return a float that represents the time in "tm". + */ + float_T +profile_float(proftime_T *tm) +{ +# ifdef MSWIN + LARGE_INTEGER fr; + + QueryPerformanceFrequency(&fr); + return (float_T)tm->QuadPart / (float_T)fr.QuadPart; +# else + return (float_T)tm->tv_sec + (float_T)tm->tv_usec / 1000000.0; +# endif +} +# endif + +/* + * Put the time "msec" past now in "tm". + */ + void +profile_setlimit(long msec, proftime_T *tm) +{ + if (msec <= 0) /* no limit */ + profile_zero(tm); + else + { +# ifdef MSWIN + LARGE_INTEGER fr; + + QueryPerformanceCounter(tm); + QueryPerformanceFrequency(&fr); + tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart); +# else + long usec; + + gettimeofday(tm, NULL); + usec = (long)tm->tv_usec + (long)msec * 1000; + tm->tv_usec = usec % 1000000L; + tm->tv_sec += usec / 1000000L; +# endif + } +} + +/* + * Return TRUE if the current time is past "tm". + */ + int +profile_passed_limit(proftime_T *tm) +{ + proftime_T now; + +# ifdef MSWIN + if (tm->QuadPart == 0) /* timer was not set */ + return FALSE; + QueryPerformanceCounter(&now); + return (now.QuadPart > tm->QuadPart); +# else + if (tm->tv_sec == 0) /* timer was not set */ + return FALSE; + gettimeofday(&now, NULL); + return (now.tv_sec > tm->tv_sec + || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec)); +# endif +} + +/* + * Set the time in "tm" to zero. + */ + void +profile_zero(proftime_T *tm) +{ +# ifdef MSWIN + tm->QuadPart = 0; +# else + tm->tv_usec = 0; + tm->tv_sec = 0; +# endif +} + +# endif /* FEAT_PROFILE || FEAT_RELTIME */ + +#if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT) && defined(FEAT_PROFILE) +# if defined(HAVE_MATH_H) +# include <math.h> +# endif + +/* + * Divide the time "tm" by "count" and store in "tm2". + */ + void +profile_divide(proftime_T *tm, int count, proft |