add performance logging

This commit is contained in:
Squibid 2025-11-14 10:54:10 -05:00
parent 73c2acd37e
commit 1f96830f10
Signed by: squibid
GPG key ID: BECE5684D3C4005D
5 changed files with 71 additions and 1 deletions

View file

@ -2,7 +2,7 @@ include config.mk
# flags and incs # flags and incs
PKGS = $(GITLIB) PKGS = $(GITLIB)
CFLAGS = -DVERSION=\"$(VERSION)\" -Wall -pedantic -O3 $(GIT) $(GITHASH) $(ERR) $(EXPLAIN) CFLAGS = -DVERSION=\"$(VERSION)\" -Wall -pedantic -O3 $(GIT) $(GITHASH) $(ERR) $(PERF) $(EXPLAIN)
LIBS = `$(PKG_CONFIG) --libs --cflags $(PKGS)` LIBS = `$(PKG_CONFIG) --libs --cflags $(PKGS)`
all: XD all: XD

32
XD.c
View file

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#ifdef ERR #ifdef ERR
#include <errno.h> #include <errno.h>
@ -31,6 +32,7 @@
char char
*find_git_repo(void) *find_git_repo(void)
{ {
PS();
char path[PATH_MAX] = ".", fstr[PATH_MAX], *rpath, *res; char path[PATH_MAX] = ".", fstr[PATH_MAX], *rpath, *res;
struct stat s; struct stat s;
FILE *f; FILE *f;
@ -40,6 +42,7 @@ char
rpath = realpath(path, NULL); rpath = realpath(path, NULL);
if (!rpath) { if (!rpath) {
L("realpath: %s", strerror(errno)); L("realpath: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
for (i = c = 0; i < strlen(rpath); i++) { for (i = c = 0; i < strlen(rpath); i++) {
@ -56,22 +59,26 @@ char
/* if there seems to be a git directory return the directory it was found in */ /* if there seems to be a git directory return the directory it was found in */
if (stat(path, &s) == 0) { if (stat(path, &s) == 0) {
if (S_ISDIR(s.st_mode)) { if (S_ISDIR(s.st_mode)) {
PE();
return realpath(path, NULL); return realpath(path, NULL);
} else if (S_ISREG(s.st_mode)) { } else if (S_ISREG(s.st_mode)) {
/* we do some special magic here to check if we're in a submodule */ /* we do some special magic here to check if we're in a submodule */
f = fopen(path, "r"); f = fopen(path, "r");
if (!f) { if (!f) {
L("fopen: %s", strerror(errno)); L("fopen: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
res = fgets(fstr, PATH_MAX, f); res = fgets(fstr, PATH_MAX, f);
fclose(f); fclose(f);
if (!res) { if (!res) {
L("fgets: %s", strerror(errno)); L("fgets: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
if (strncmp(fstr, "gitdir: ", strlen("gitdir: ")) == 0) { if (strncmp(fstr, "gitdir: ", strlen("gitdir: ")) == 0) {
fstr[strlen(fstr) - 1] = '\0'; fstr[strlen(fstr) - 1] = '\0';
PE();
return realpath(fstr + strlen("gitdir: "), NULL); return realpath(fstr + strlen("gitdir: "), NULL);
} }
} }
@ -82,6 +89,7 @@ char
memset(&path[strlen(path) - 2], 0, 2); memset(&path[strlen(path) - 2], 0, 2);
} }
PE();
return NULL; return NULL;
} }
@ -93,11 +101,13 @@ char
git_repository git_repository
*init_git(void) *init_git(void)
{ {
PS();
char *buf; char *buf;
git_repository *repo; git_repository *repo;
/* check for a repo before loading libgit2 */ /* check for a repo before loading libgit2 */
if ((buf = find_git_repo()) == NULL) { if ((buf = find_git_repo()) == NULL) {
PE();
return NULL; return NULL;
} }
@ -113,17 +123,20 @@ git_repository
/* initialize the git library and repository */ /* initialize the git library and repository */
if (git_libgit2_init() < 0) { if (git_libgit2_init() < 0) {
L("Failed to initalize libgit2, proceeding without git functionality enabled."); L("Failed to initalize libgit2, proceeding without git functionality enabled.");
PE();
return NULL; return NULL;
} }
if (git_repository_open(&repo, buf) < 0) { if (git_repository_open(&repo, buf) < 0) {
L("Failed to open git repo: %s", git_error_last()->message); L("Failed to open git repo: %s", git_error_last()->message);
free(buf); free(buf);
PE();
return NULL; return NULL;
} }
/* get rid of object containing git repo path and return the repo */ /* get rid of object containing git repo path and return the repo */
free(buf); free(buf);
PE();
return repo; return repo;
} }
@ -136,20 +149,24 @@ git_repository
int int
has_stashes(git_repository *repo) has_stashes(git_repository *repo)
{ {
PS();
git_reference *stash = NULL; git_reference *stash = NULL;
int e; int e;
e = git_reference_lookup(&stash, repo, "refs/stash"); e = git_reference_lookup(&stash, repo, "refs/stash");
if (e == GIT_ENOTFOUND) { if (e == GIT_ENOTFOUND) {
PE();
return 0; return 0;
} else if (e < 0) { } else if (e < 0) {
L("Error looking up stash reference: %s", git_error_last()->message); L("Error looking up stash reference: %s", git_error_last()->message);
PE();
return 0; return 0;
} else { } else {
e = 1; e = 1;
} }
git_reference_free(stash); git_reference_free(stash);
PE();
return e; return e;
} }
@ -162,6 +179,7 @@ has_stashes(git_repository *repo)
int int
has_untracked(git_repository *repo) has_untracked(git_repository *repo)
{ {
PS();
git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_options opts = GIT_STATUS_OPTIONS_INIT;
git_status_list *list = NULL; git_status_list *list = NULL;
repohash *storedhash; repohash *storedhash;
@ -173,6 +191,7 @@ has_untracked(git_repository *repo)
&& storedhash->hash == newhash) { && storedhash->hash == newhash) {
r = storedhash->changes; r = storedhash->changes;
free(storedhash); free(storedhash);
PE();
return r; return r;
} }
#endif #endif
@ -187,6 +206,7 @@ has_untracked(git_repository *repo)
if (git_status_list_new(&list, repo, &opts) < 0) { if (git_status_list_new(&list, repo, &opts) < 0) {
L("Error checking for untracked changes: %s", git_error_last()->message); L("Error checking for untracked changes: %s", git_error_last()->message);
PE();
return 0; return 0;
} }
@ -197,6 +217,7 @@ has_untracked(git_repository *repo)
#endif #endif
git_status_list_free(list); git_status_list_free(list);
PE();
return r; return r;
} }
@ -209,6 +230,7 @@ has_untracked(git_repository *repo)
int int
has_staged(git_repository *repo) has_staged(git_repository *repo)
{ {
PS();
git_status_entry entry; git_status_entry entry;
git_status_list *list = NULL; git_status_list *list = NULL;
git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_options opts = GIT_STATUS_OPTIONS_INIT;
@ -219,6 +241,7 @@ has_staged(git_repository *repo)
if (git_status_list_new(&list, repo, &opts) < 0) { if (git_status_list_new(&list, repo, &opts) < 0) {
L("Error checking for staged changes: %s", git_error_last()->message); L("Error checking for staged changes: %s", git_error_last()->message);
PE();
return 0; return 0;
} }
@ -237,6 +260,7 @@ has_staged(git_repository *repo)
} }
git_status_list_free(list); git_status_list_free(list);
PE();
return r; return r;
} }
#endif #endif
@ -244,17 +268,20 @@ has_staged(git_repository *repo)
inline unsigned inline unsigned
numcat(unsigned x, unsigned y) numcat(unsigned x, unsigned y)
{ {
PS();
unsigned pow = 10; unsigned pow = 10;
while(y >= pow) { while(y >= pow) {
pow *= 10; pow *= 10;
} }
PE();
return (x * pow) + y; return (x * pow) + y;
} }
int int
str_to_int(char *str) str_to_int(char *str)
{ {
PS();
int res = -1; int res = -1;
char *c; char *c;
@ -266,17 +293,20 @@ str_to_int(char *str)
} }
} }
PE();
return res; return res;
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
PS();
int code = -1; int code = -1;
/* print version information */ /* print version information */
if (argc > 1 && strcmp(argv[1], "-v") == 0) { if (argc > 1 && strcmp(argv[1], "-v") == 0) {
printf("XD [number] %s\n", VERSION); printf("XD [number] %s\n", VERSION);
PE();
return 0; return 0;
#ifdef EXPLAIN #ifdef EXPLAIN
} else if (argc > 1 && strcmp(argv[1], "-e") == 0) { } else if (argc > 1 && strcmp(argv[1], "-e") == 0) {
@ -328,6 +358,7 @@ main(int argc, char *argv[])
code = str_to_int(argv[argc - 1]); code = str_to_int(argv[argc - 1]);
if (code < 0) { if (code < 0) {
L("Return code, %d, not valid", code); L("Return code, %d, not valid", code);
PE();
exit(1); exit(1);
} }
} }
@ -361,5 +392,6 @@ main(int argc, char *argv[])
P("|"); /* no code info */ P("|"); /* no code info */
} }
PE();
return code; return code;
} }

View file

@ -18,6 +18,10 @@ ERR =
# uncomment to enable errors # uncomment to enable errors
# ERR = -DERR # ERR = -DERR
PERF =
# uncomment to enable performance logging
# PERF = -DPERF
EXPLAIN = EXPLAIN =
# comment to disable explinations # comment to disable explinations
EXPLAIN = -DEXPLAIN EXPLAIN = -DEXPLAIN
@ -36,6 +40,11 @@ ifeq ($(ERR),)
else else
VERSION := $(VERSION)"\\nerrors enabled" VERSION := $(VERSION)"\\nerrors enabled"
endif endif
ifeq ($(PERF),)
VERSION := $(VERSION)"\\nperformance logging disabled"
else
VERSION := $(VERSION)"\\nperformance logging enabled"
endif
ifeq ($(EXPLAIN),) ifeq ($(EXPLAIN),)
VERSION := $(VERSION)"\\nexplinations disabled" VERSION := $(VERSION)"\\nexplinations disabled"
else else

21
hash.c
View file

@ -15,41 +15,49 @@
static uint64_t static uint64_t
murmur64(uint64_t k) murmur64(uint64_t k)
{ {
PS();
k ^= k >> 33; k ^= k >> 33;
k *= 0xff51afd7ed558ccdLLU; k *= 0xff51afd7ed558ccdLLU;
k ^= k >> 33; k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53LLU; k *= 0xc4ceb9fe1a85ec53LLU;
k ^= k >> 33; k ^= k >> 33;
PE();
return k; return k;
} }
uint64_t uint64_t
generate_hash(git_repository *repo) generate_hash(git_repository *repo)
{ {
PS();
struct stat dir, index; struct stat dir, index;
char path[PATH_MAX] = { 0 }; char path[PATH_MAX] = { 0 };
const char *gitpath = git_repository_path(repo); const char *gitpath = git_repository_path(repo);
if (strlen(gitpath) + strlen("/..") > PATH_MAX - 1) { if (strlen(gitpath) + strlen("/..") > PATH_MAX - 1) {
L("strlen: %s", strerror(errno)); L("strlen: %s", strerror(errno));
PE();
return -1; return -1;
} }
strcat(path, gitpath); strcat(path, gitpath);
if (stat(path, &index) < 0) { if (stat(path, &index) < 0) {
PE();
return -1; return -1;
} }
strcat(path, "/.."); strcat(path, "/..");
if (stat(path, &dir) < 0) { if (stat(path, &dir) < 0) {
PE();
return -1; return -1;
} }
PE();
return murmur64(dir.st_mtim.tv_nsec ^ index.st_mtim.tv_nsec); return murmur64(dir.st_mtim.tv_nsec ^ index.st_mtim.tv_nsec);
} }
repohash repohash
*read_hash(git_repository *repo) *read_hash(git_repository *repo)
{ {
PS();
FILE *f; FILE *f;
uint64_t data; uint64_t data;
uint8_t changes; uint8_t changes;
@ -59,6 +67,7 @@ repohash
const char *gitpath = git_repository_path(repo); const char *gitpath = git_repository_path(repo);
if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) { if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) {
L("strlen: %s", strerror(errno)); L("strlen: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
strcat(path, gitpath); strcat(path, gitpath);
@ -67,39 +76,46 @@ repohash
f = fopen(path, "r"); f = fopen(path, "r");
if (!f) { if (!f) {
L("fopen: %s", strerror(errno)); L("fopen: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
if (fread(&data, sizeof(uint64_t), 1, f) != 1) { if (fread(&data, sizeof(uint64_t), 1, f) != 1) {
L("fread: %s", strerror(errno)); L("fread: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) { if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) {
L("fseek: %s", strerror(errno)); L("fseek: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
if (fread(&changes, sizeof(uint8_t), 1, f) != 1) { if (fread(&changes, sizeof(uint8_t), 1, f) != 1) {
L("fread: %s", strerror(errno)); L("fread: %s", strerror(errno));
PE();
return NULL; return NULL;
} }
fclose(f); fclose(f);
hash->hash = data; hash->hash = data;
hash->changes = changes; hash->changes = changes;
PE();
return hash; return hash;
} }
int int
write_hash(git_repository *repo, repohash hash) write_hash(git_repository *repo, repohash hash)
{ {
PS();
FILE *f; FILE *f;
char path[PATH_MAX] = { 0 }; char path[PATH_MAX] = { 0 };
const char *gitpath = git_repository_path(repo); const char *gitpath = git_repository_path(repo);
if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) { if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) {
L("strlen: %s", strerror(errno)); L("strlen: %s", strerror(errno));
PE();
return 1; return 1;
} }
strcat(path, gitpath); strcat(path, gitpath);
@ -108,25 +124,30 @@ write_hash(git_repository *repo, repohash hash)
f = fopen(path, "wb"); f = fopen(path, "wb");
if (!f) { if (!f) {
L("fopen: %s", strerror(errno)); L("fopen: %s", strerror(errno));
PE();
return 1; return 1;
} }
if (fwrite(&hash.hash, sizeof(uint64_t), 1, f) != 1) { if (fwrite(&hash.hash, sizeof(uint64_t), 1, f) != 1) {
L("fwrite: %s", strerror(errno)); L("fwrite: %s", strerror(errno));
PE();
return 1; return 1;
} }
if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) { if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) {
L("fseek: %s", strerror(errno)); L("fseek: %s", strerror(errno));
PE();
return 1; return 1;
} }
if (fwrite(&hash.changes, sizeof(uint8_t), 1, f) != 1) { if (fwrite(&hash.changes, sizeof(uint8_t), 1, f) != 1) {
L("fwrite: %s", strerror(errno)); L("fwrite: %s", strerror(errno));
PE();
return 1; return 1;
} }
fclose(f); fclose(f);
PE();
return 0; return 0;
} }
#endif #endif

View file

@ -18,3 +18,11 @@ extern int explain;
#else #else
#define E(...) #define E(...)
#endif #endif
#ifdef PERF
#define PS() long __start = clock()
#define PE() l("%s: %fs", __func__, ((double) (clock() - __start)) / CLOCKS_PER_SEC)
#else
#define PS()
#define PE()
#endif