Optimizations and profiling (fix draw line numbers, coroutines)

This commit is contained in:
krzosa
2025-12-23 13:18:41 +01:00
parent 74ae806978
commit 28308f58b2
7 changed files with 72 additions and 33 deletions

View File

@@ -1,11 +1,13 @@
- What precise workflow do I need for me to be viable to use this?
- From a user (novice) point of view, how does it look like?
- Optimization:
- Show what process/coroutines are running and allow to kill (active process buffer?)
- ctrl + p like in VSCode (without special buffers)
- I THINK WE NEED A SPECIAL VIEW, this is too slow
- Move to the top so that it can be progressively expanded using coroutines by appending at the end
- Maybe 2 windows?
- Database idea: use special buffers to store information
- Editing the buffer doesn't seem to be the slow part rather, accessing the data and putting it into the buffer (potentially hitting many different memory locations) I have a crazy idea to use buffers in order to store the names in a serialized format
- non editable buffers (raw ops ok, non-raw no op)
- Guide on the first page for new users with links to configs, tutorials
- Why constraint that name of buffer needs to be unique? For Open() and default behavior but is this required?

View File

@@ -193,6 +193,13 @@ API String GetExeDir(Allocator al) {
return result;
}
API uint64_t GetTimeNanos(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
uint64_t ts = ((uint64_t)spec.tv_sec * 1000000000ull) + (uint64_t)spec.tv_nsec;
return ts;
}
API double GetTimeMicros(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
@@ -565,6 +572,19 @@ API FileIter IterateFiles(Allocator alo, String path) {
return it;
}
API uint64_t GetTimeNanos(void) {
static double invfreq;
if (!invfreq) {
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
invfreq = 1000000000.0 / frequency.QuadPart;
}
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
uint64_t ts = (uint64_t)((double)counter.QuadPart * invfreq);
return ts;
}
API double GetTimeMicros(void) {
static double invfreq;
if (!invfreq) {
@@ -1047,6 +1067,13 @@ API String GetExeDir(Allocator al) {
return result;
}
API uint64_t GetTimeNanos(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
uint64_t ts = ((uint64_t)spec.tv_sec * 1000000000ull) + (uint64_t)spec.tv_nsec;
return ts;
}
API double GetTimeMicros(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);

View File

@@ -674,11 +674,7 @@ void Coro_OpenCode(mco_coro *co) {
}
}
if ((i%32) == 0) {
CoYield(co);
}
i += 1;
CoYield(co);
}
}
Release(&arena);

View File

@@ -1,6 +1,7 @@
typedef void CoroutineProc(mco_coro *co);
mco_coro *CoAdd(CoroutineProc *proc) {
#define CoAdd(x) CoAddEx(x, #x)
mco_coro *CoAddEx(CoroutineProc *proc, String name) {
mco_desc desc = mco_desc_init(proc, 0);
mco_coro *coro = NULL;
@@ -11,32 +12,35 @@ mco_coro *CoAdd(CoroutineProc *proc) {
}
mco_resume(coro);
Add(&ActiveCoroutines, coro);
Add(&ActiveCoroutines, {coro, name});
return coro;
}
void CoUpdate(Event *event) {
ProfileFunction();
double start = GetTimeSeconds();
IterRemove(ActiveCoroutines) {
IterRemovePrepare(ActiveCoroutines);
for (;ActiveCoroutines.len;) {
IterRemove(ActiveCoroutines) {
IterRemovePrepare(ActiveCoroutines);
ProfileScopeEx(it.name);
mco_state status = mco_status(it);
if (status == MCO_DEAD) {
mco_destroy(it);
remove_item = true;
} else {
mco_push(it, &event, sizeof(Event *));
mco_result ok = mco_resume(it);
if (ok != MCO_SUCCESS) {
ReportWarningf("failed to resume coroutine %d", ok);
mco_destroy(it);
mco_state status = mco_status(it.co);
if (status == MCO_DEAD) {
mco_destroy(it.co);
remove_item = true;
} else {
mco_push(it.co, &event, sizeof(Event *));
mco_result ok = mco_resume(it.co);
if (ok != MCO_SUCCESS) {
ReportWarningf("failed to resume coroutine %d", ok);
mco_destroy(it.co);
remove_item = true;
}
}
}
double took = GetTimeSeconds() - start;
if (took > 0.01) {
if (took > (0.016666 / 3.0)) {
break;
}
}
@@ -53,7 +57,12 @@ Event *CoYield(mco_coro *co) {
return event;
}
void CoRemove(mco_coro *co) {
UnorderedRemove(&ActiveCoroutines, co);
mco_destroy(co);
void CoRemove(String name) {
IterRemove(ActiveCoroutines) {
IterRemovePrepare(ActiveCoroutines);
if (it.name == name) {
mco_destroy(it.co);
remove_item = true;
}
}
}

View File

@@ -235,7 +235,7 @@ void DrawWindow(Window *window, Event &event) {
// Draw caret "|" markings
if (is_active) {
BeginProfileScope(draw_carets);
ProfileScope(DrawCarets);
For(view->carets) {
Int front = GetFront(it);
XY fxy = PosToXY(buffer, front);
@@ -244,17 +244,17 @@ void DrawWindow(Window *window, Event &event) {
DrawCaret(window, fxy, 0.3f, main_caret ? color_main_caret : color_sub_caret);
}
}
EndProfileScope();
}
// Draw line numbers
if (window->draw_line_numbers) {
ProfileScope(DrawLineNumbers);
Scratch scratch;
SetScissor(window->line_numbers_rect);
Rect2I vlines = GetVisibleCells(window);
for (Int line = vlines.min.y; line <= visible.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) {
Scratch scratch;
Vec2I pos = {0, line * window->font->line_spacing};
Vec2I pos = {0, line * window->font->line_spacing};
pos.y -= view->scroll.y;
pos += window->line_numbers_rect.min;
String s = Format(scratch, "%lld", (long long)line + 1ll);
@@ -270,6 +270,7 @@ void DrawWindow(Window *window, Event &event) {
// Draw scrollbar
if (window->draw_scrollbar) {
ProfileScope(DrawScrollbar);
SetScissor(window->scrollbar_rect);
DrawRect(window->scrollbar_rect, ColorScrollbarBackground);
Scroller scroller = ComputeScrollerRect(window);
@@ -281,12 +282,14 @@ void DrawWindow(Window *window, Event &event) {
// color the floating object to make it stand out
if (window->z >= 1) {
ProfileScope(ColorFloating);
SetScissor(window->total_rect);
DrawRect(window->total_rect, {255, 255, 255, 25});
}
// darken the inactive windows
if (!is_active) {
ProfileScope(DarkenInactiveRect);
SetScissor(screen_rect);
DrawRect(window->total_rect, ColorInactiveWindow);
}

View File

@@ -81,7 +81,9 @@ Array<Variable> Variables;
Array<Process> ActiveProcesses = {};
Array<String> ProcessEnviroment = {};
Array<mco_coro *> ActiveCoroutines;
struct CoData { mco_coro *co; String name; };
Array<CoData> ActiveCoroutines;
///////////////////////////////

View File

@@ -364,7 +364,7 @@ SPALL_FN bool spall_buffer_name_process(SpallProfile *ctx, SpallBuffer *wb, cons
static SpallProfile spall_ctx;
static SpallBuffer spall_buffer;
double GetTimeMicros(void);
uint64_t GetTimeNanos(void);
void BeginProfiler() {
spall_init_file("te.spall", 1, &spall_ctx);
@@ -386,14 +386,14 @@ void _BeginProfileScope(const char *name, int len) {
spall_buffer_begin(&spall_ctx, &spall_buffer,
name, // name of your name
len, // name len minus the null terminator
(uint64_t)GetTimeMicros() // timestamp in microseconds -- start of your timing block
GetTimeNanos() // timestamp in microseconds -- start of your timing block
);
}
#define BeginProfileScope(name) _BeginProfileScope(#name, sizeof(#name) - 1)
void EndProfileScope() {
spall_buffer_end(&spall_ctx, &spall_buffer,
(uint64_t)GetTimeMicros() // timestamp in microseconds -- end of your timing block
GetTimeNanos() // timestamp in microseconds -- end of your timing block
);
}
#define ProfileScopeEx(name) ProfileScopeClass PROFILE_SCOPE_VAR_((name).data, (int)(name).len)