aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/profile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/profile.c')
-rw-r--r--src/nvim/profile.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index 53ff57dacb..b88b08d3f0 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -15,11 +15,11 @@
#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/keycodes.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -36,7 +36,7 @@
#endif
/// Struct used in sn_prl_ga for every line of a script.
-typedef struct sn_prl_S {
+typedef struct {
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
@@ -45,6 +45,7 @@ typedef struct sn_prl_S {
#define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
static proftime_T prof_wait_time;
+static char *startuptime_buf = NULL; // --startuptime buffer
/// Gets the current time.
///
@@ -255,7 +256,7 @@ void profile_reset(void)
size_t todo = functbl->ht_used;
hashitem_T *hi = functbl->ht_array;
- for (; todo > (size_t)0; hi++) {
+ for (; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
ufunc_T *uf = HI2UF(hi);
@@ -798,7 +799,7 @@ void script_line_start(void)
if (si->sn_prof_on && SOURCING_LNUM >= 1) {
// Grow the array before starting the timer, so that the time spent
// here isn't counted.
- (void)ga_grow(&si->sn_prl_ga, SOURCING_LNUM - si->sn_prl_ga.ga_len);
+ ga_grow(&si->sn_prl_ga, SOURCING_LNUM - si->sn_prl_ga.ga_len);
si->sn_prl_idx = SOURCING_LNUM - 1;
while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
&& si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) {
@@ -907,7 +908,7 @@ void time_start(const char *message)
// initialize the global variables
g_prev_time = g_start_time = profile_start();
- fprintf(time_fd, "\n\ntimes in msec\n");
+ fprintf(time_fd, "\ntimes in msec\n");
fprintf(time_fd, " clock self+sourced self: sourced script\n");
fprintf(time_fd, " clock elapsed: other lines\n\n");
@@ -944,3 +945,47 @@ void time_msg(const char *mesg, const proftime_T *start)
g_prev_time = now;
fprintf(time_fd, ": %s\n", mesg);
}
+
+/// Initializes the `time_fd` stream for the --startuptime report.
+///
+/// @param fname startuptime report file path
+/// @param process_name name of the current Nvim process to write in the report.
+void time_init(const char *fname, const char *process_name)
+{
+ const size_t bufsize = 8192; // Big enough for the entire --startuptime report.
+ time_fd = fopen(fname, "a");
+ if (time_fd == NULL) {
+ semsg(_(e_notopen), fname);
+ return;
+ }
+ startuptime_buf = xmalloc(sizeof(char) * (bufsize + 1));
+ // The startuptime file is (potentially) written by multiple Nvim processes concurrently. So each
+ // report is buffered, and flushed to disk (`time_finish`) once after startup. `_IOFBF` mode
+ // ensures the buffer is not auto-flushed ("controlled buffering").
+ int r = setvbuf(time_fd, startuptime_buf, _IOFBF, bufsize + 1);
+ if (r != 0) {
+ XFREE_CLEAR(startuptime_buf);
+ fclose(time_fd);
+ time_fd = NULL;
+ ELOG("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
+ semsg("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
+ return;
+ }
+ fprintf(time_fd, "--- Startup times for process: %s ---\n", process_name);
+}
+
+/// Flushes the startuptimes to disk for the current process
+void time_finish(void)
+{
+ if (time_fd == NULL) {
+ return;
+ }
+ assert(startuptime_buf != NULL);
+ TIME_MSG("--- NVIM STARTED ---\n");
+
+ // flush buffer to disk
+ fclose(time_fd);
+ time_fd = NULL;
+
+ XFREE_CLEAR(startuptime_buf);
+}