From: Mark Jamsek Subject: Re: tog: 100% cpu usage after search in full-screen mode To: Mikhail Cc: gameoftrees@openbsd.org Date: Wed, 8 Feb 2023 17:57:00 +1100 On 23-02-07 09:23PM, Mikhail wrote: > I spent a little bit time on this, but wasn't able to get a clue: > > run tog in got repo > wait 10 secs > > F > /whatever > > look in 'top' how tog slowly starts eating whole CPU. Nice find! Thanks, Mikhail :) This is indeed a weird one! I think it's because we unset our 1s refresh rate when entering view_search_start(), and because fast_refresh is now 0, we never meet that condition in view_input() to reset it back to 1s again. Whereas if we follow the recipe without waiting 10s, fast_refresh will still be > 0 thus the 1s refresh rate will still be set in view_input(). > I dug it to view_loop, which starts cycling like crazy. Pressing 'q' > while in full-screen cpu-eating mode makes tog back to normal cpu usage. > > Inlined patch fixes the issue for me, but it's "monkey see - monkey do" > kind of patch, can't propose it like a solution: While the diff does indeed fix the problem, I don't think we want to call halfdelay() every iteration. We could make it a global, but it's only used in now two locations, so let's pass it as an argument instead. diff /home/mark/src/got commit - ec218e165dfd906f44ad491671127ca4b6979ed0 path + /home/mark/src/got blob - a6351da680ffacc2f47bf1a42b494d77af0b4a3a file + tog/tog.c --- tog/tog.c +++ tog/tog.c @@ -1288,7 +1288,7 @@ view_search_start(struct tog_view *view) } static const struct got_error * -view_search_start(struct tog_view *view) +view_search_start(struct tog_view *view, int fast_refresh) { const struct got_error *err = NULL; struct tog_view *v = view; @@ -1321,6 +1321,8 @@ view_search_start(struct tog_view *view) cbreak(); noecho(); nodelay(v->window, TRUE); + if (!fast_refresh) + halfdelay(10); if (ret == ERR) return NULL; @@ -1488,7 +1490,7 @@ view_input(struct tog_view **new, int *done, struct to static const struct got_error * view_input(struct tog_view **new, int *done, struct tog_view *view, - struct tog_view_list_head *views) + struct tog_view_list_head *views, int fast_refresh) { const struct got_error *err = NULL; struct tog_view *v; @@ -1683,7 +1685,7 @@ view_input(struct tog_view **new, int *done, struct to case '/': view->count = 0; if (view->search_start) - view_search_start(view); + view_search_start(view, fast_refresh); else err = view->input(new, view, ch); break; @@ -1775,7 +1777,7 @@ view_loop(struct tog_view *view) if (fast_refresh && --fast_refresh == 0) halfdelay(10); /* switch to once per second */ - err = view_input(&new_view, &done, view, &views); + err = view_input(&new_view, &done, view, &views, fast_refresh); if (err) break; > diff /home/misha/work/got > commit - 704b1cf77bf5aa6f9aeed7bca0b34c53cc2183c2 > path + /home/misha/work/got > blob - a6351da680ffacc2f47bf1a42b494d77af0b4a3a > file + tog/tog.c > --- tog/tog.c > +++ tog/tog.c > @@ -1747,7 +1747,6 @@ view_loop(struct tog_view *view) > struct tog_view_list_head views; > struct tog_view *new_view; > char *mode; > - int fast_refresh = 10; > int done = 0, errcode; > > mode = getenv("TOG_VIEW_SPLIT_MODE"); > @@ -1771,9 +1770,7 @@ view_loop(struct tog_view *view) > doupdate(); > while (!TAILQ_EMPTY(&views) && !done && !tog_thread_error && > !tog_fatal_signal_received()) { > - /* Refresh fast during initialization, then become slower. */ > - if (fast_refresh && --fast_refresh == 0) > - halfdelay(10); /* switch to once per second */ > + halfdelay(10); > > err = view_input(&new_view, &done, view, &views); > if (err) > -- Mark Jamsek GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68