bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit 0221ed0275eae5a6fbcfb33d82b67bd6994e450f
parent 14ef848d116e7ab9178b8bff94fab25d118a89ff
Author: quantumish <freifeld.david@gmail.com>
Date:   Tue, 16 May 2023 14:43:00 -0700

Proper ish profiling!

Diffstat:
Mhttp.c | 12+++++++-----
Mutils/profile.c | 53+++++++++++++++++++++++++----------------------------
Mutils/profile.h | 9+++++++++
3 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/http.c b/http.c @@ -16,7 +16,6 @@ #include <sys/socket.h> #include <sys/types.h> #include <sys/ptrace.h> -#include <sys/wait.h> #include <sys/fcntl.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -27,6 +26,7 @@ #include "utils/sync.h" #include "utils/html.h" #include "utils/compress.h" +#include "utils/profile.h" #include "http/response.h" #include "http/request.h" @@ -289,12 +289,14 @@ int main() { struct conn_ctxt* ctxt = shitvec_get(&conns, i); char msg[8] = {0}; if (read(ctxt->fd, &msg, 8) != 8 || strcmp(msg, "profile") != 0) continue; - shitvec_t nodes = shitvec_new(sizeof(struct tree_node)); + struct profile_node prof_res = profile_res_new(); while(true) { - profile(ctxt->pid); - usleep(10); - if (read(ctxt->fd, &msg, 5) == 5 && strcmp(msg, "stop") == 0) break; + shitvec_t stack = profile(ctxt->pid); + profile_proc_stack(&prof_res, &stack); + usleep(3); + if (read(ctxt->fd, &msg, 5) == 5 && strcmp(msg, "stop") == 0) break; } + profile_dump(&prof_res, -1); } } } diff --git a/utils/profile.c b/utils/profile.c @@ -1,5 +1,10 @@ #include <string.h> #include <errno.h> +#include <stdio.h> + +#include <sys/types.h> +#include <signal.h> +#include <unistd.h> #include <sys/ptrace.h> #include <sys/wait.h> @@ -12,19 +17,10 @@ #include "log.h" #include "profile.h" -struct profile_node { - char symbol[MAX_SYMLEN]; - unsigned int samples; - shitvec_t children; -}; - shitvec_t profile(pid_t tid) { shitvec_t stack = shitvec_new(MAX_SYMLEN); errno = 0; - log_debug("Tracing %d", tid); - if (ptrace(PTRACE_ATTACH, tid) < 0) { - log_error("ptrace() fail, errno %d", errno); - } + ptrace(PTRACE_ATTACH, tid); kill(tid, SIGSTOP); waitpid(tid, NULL, 0); void* ui = _UPT_create(tid); @@ -35,7 +31,6 @@ shitvec_t profile(pid_t tid) { unw_word_t offset; char fname[MAX_SYMLEN] = {0}; int resp = unw_get_proc_name(&c, fname, sizeof(fname), &offset); - log_trace("%s (code %d, errno %d)", fname, resp, errno); shitvec_push(&stack, fname); } while(unw_step(&c) > 0); _UPT_resume(as, &c, ui); @@ -56,8 +51,8 @@ struct profile_node profile_node_new(char* name) { return out; } -shitvec_t profile_res_new() { - return shitvec_new(sizeof(shitvec_t)); +struct profile_node profile_res_new() { + return profile_node_new(""); } int cmp_prof_node(void* _a, void* _b) { @@ -66,27 +61,29 @@ int cmp_prof_node(void* _a, void* _b) { return strcmp(a->symbol, b->symbol); } -void profile_proc_stack(shitvec_t* prof_res, shitvec_t* stack) { - if (stack->vec_sz == 0) return; - // NOTE maybe just have a fake root node (would make this base case not needed) - int index = shitvec_check(prof_res, shitvec_get(stack, 0), cmp_prof_node); - if (index == -1) { - struct profile_node new = profile_node_new(shitvec_get(stack, 0)); - shitvec_push(prof_res, &new); - index = prof_res->vec_sz - 1; - } - struct profile_node* node = shitvec_get(prof_res, index); - node->samples += 1; - - for (int i = 0; i < stack->vec_sz; i++) { +void profile_proc_stack(struct profile_node* prof_res, shitvec_t* stack) { + if (stack->vec_sz == 0) return; + struct profile_node* node = prof_res; + for (int i = stack->vec_sz-1; i > 0; i--) { char* sym = shitvec_get(stack, i); int index = shitvec_check(&node->children, sym, cmp_prof_node); if (index == -1) { struct profile_node new = profile_node_new(sym); - shitvec_push(prof_res, &new); - index = prof_res->vec_sz - 1; + shitvec_push(&node->children, &new); + index = node->children.vec_sz - 1; } node = shitvec_get(&node->children, index); node->samples += 1; } } + +void profile_dump(struct profile_node* prof_res, int indent) { + struct profile_node* node = prof_res; + if (indent >= 0) { + for (int i = 0; i < indent; i++) printf(" "); + printf("%s (%d) \n", node->symbol, node->samples); + } + for (int i = 0; i < node->children.vec_sz; i++) { + profile_dump(shitvec_get(&node->children, i), indent+1); + } +} diff --git a/utils/profile.h b/utils/profile.h @@ -8,5 +8,14 @@ #define MAX_SYMLEN 32 shitvec_t profile(pid_t pid); +struct profile_node { + char symbol[MAX_SYMLEN]; + unsigned int samples; + shitvec_t children; +}; + +struct profile_node profile_res_new(); +void profile_proc_stack(struct profile_node* prof_res, shitvec_t* stack); +void profile_dump(struct profile_node* prof_res, int indent); #endif