Download raw body.
tog is sluggish with FreeBSD src.git
On Fri, Dec 25, 2020 at 12:38:23AM +0100, Stefan Sperling wrote: > On Thu, Dec 24, 2020 at 04:39:29PM +0100, Christian Weisgerber wrote: > > Stefan Sperling: > > > It looks like we'll need to populate a cache of reference names which > > > is indexed by commit ID, ideally while reading references from the repo? > > > > got_ref_tree()? Something along those lines, I guess. > > Can you try this? Merry christmas <3 Here is another patch (which applies on top of the previous patch) that shows how we can avoid the delay caused by reading references from disk when opening a diff view from the log view. The same idea could be applied to other views, e.g. the blame view could also pass a list of references to the diff view. Once this has spread to all tog views, reading the reference list of the FreeBSD repo becomes a 1x start-up cost for tog. We could even optimize got_ref_list() itself if this start-up overhead is not acceptable. The got_ref_list() function currently traverses the entire list every time a new ref is added, which is obviously suboptimal. diff b1700e6f9a5e50cb46002b7775c0a5ac9059b6fc refs/heads/object_id_map blob - 8a7ddd1fed280c5ace7be5e759d1b7ef2c6cc784 blob + 86bb696e9930246f8970ea7067581e1b5751136e --- include/got_reference.h +++ include/got_reference.h @@ -110,6 +110,13 @@ const struct got_error *got_ref_list(struct got_reflis /* Free all references on a ref list. */ void got_ref_list_free(struct got_reflist_head *); +/* + * Deep-copy all elements of a reference list to another reference list. + * The destination list must already have been initialized with SIMPLEQ_INIT. + */ +const struct got_error *got_ref_list_copy(struct got_reflist_head *, + struct got_reflist_head *); + /* Indicate whether the provided reference is symbolic (points at another * refernce) or not (points at an object ID). */ int got_ref_is_symbolic(struct got_reference *); blob - d9f1596591be3332b0a51e1ec4e6c77a90720fae blob + b84f193dae6dedc72bf14c332337b51f036cbfb6 --- lib/reference.c +++ lib/reference.c @@ -1021,6 +1021,24 @@ got_ref_list_free(struct got_reflist_head *refs) } +const struct got_error * +got_ref_list_copy(struct got_reflist_head *src, struct got_reflist_head *dst) +{ + const struct got_error *err = NULL; + struct got_reflist_entry *re, *new; + + SIMPLEQ_FOREACH(re, src, entry) { + err = got_reflist_entry_dup(&new, re); + if (err) { + got_ref_list_free(dst); + return err; + } + SIMPLEQ_INSERT_TAIL(dst, new, entry); + } + + return NULL; +} + int got_ref_is_symbolic(struct got_reference *ref) { blob - a28a00571d687d94f4f9215df59a0fe82423e7c9 blob + 68bd070d1013a0af0dd554d233924ced3235b42e --- tog/tog.c +++ tog/tog.c @@ -495,7 +495,7 @@ struct tog_view { static const struct got_error *open_diff_view(struct tog_view *, struct got_object_id *, struct got_object_id *, const char *, const char *, int, int, int, struct tog_view *, - struct got_repository *); + struct got_reflist_head *, struct got_repository *); static const struct got_error *show_diff_view(struct tog_view *); static const struct got_error *input_diff_view(struct tog_view **, struct tog_view *, int); @@ -1820,7 +1820,8 @@ log_scroll_down(struct tog_view *view, int maxscroll) static const struct got_error * open_diff_view_for_commit(struct tog_view **new_view, int begin_x, struct got_commit_object *commit, struct got_object_id *commit_id, - struct tog_view *log_view, struct got_repository *repo) + struct tog_view *log_view, struct got_reflist_head *refs, + struct got_repository *repo) { const struct got_error *err; struct got_object_qid *parent_id; @@ -1832,7 +1833,7 @@ open_diff_view_for_commit(struct tog_view **new_view, parent_id = SIMPLEQ_FIRST(got_object_commit_get_parent_ids(commit)); err = open_diff_view(diff_view, parent_id ? parent_id->id : NULL, - commit_id, NULL, NULL, 3, 0, 0, log_view, repo); + commit_id, NULL, NULL, 3, 0, 0, log_view, refs, repo); if (err == NULL) *new_view = diff_view; return err; @@ -2474,7 +2475,7 @@ input_log_view(struct tog_view **new_view, struct tog_ begin_x = view_split_begin_x(view->begin_x); err = open_diff_view_for_commit(&diff_view, begin_x, s->selected_entry->commit, s->selected_entry->id, - view, s->repo); + view, &s->refs, s->repo); if (err) break; view->focussed = 0; @@ -3409,7 +3410,8 @@ static const struct got_error * open_diff_view(struct tog_view *view, struct got_object_id *id1, struct got_object_id *id2, const char *label1, const char *label2, int diff_context, int ignore_whitespace, int force_text_diff, - struct tog_view *log_view, struct got_repository *repo) + struct tog_view *log_view, struct got_reflist_head *refs, + struct got_repository *repo) { const struct got_error *err; struct tog_diff_view_state *s = &view->state.diff; @@ -3507,7 +3509,11 @@ open_diff_view(struct tog_view *view, struct got_objec } } - err = got_ref_list(&s->refs, repo, NULL, got_ref_cmp_by_name, NULL); + if (refs) + err = got_ref_list_copy(refs, &s->refs); + else + err = got_ref_list(&s->refs, repo, NULL, got_ref_cmp_by_name, + NULL); if (err) { free(s->id1); s->id1 = NULL; @@ -3871,7 +3877,7 @@ cmd_diff(int argc, char *argv[]) goto done; } error = open_diff_view(view, id1, id2, label1, label2, diff_context, - ignore_whitespace, force_text_diff, NULL, repo); + ignore_whitespace, force_text_diff, NULL, NULL, repo); if (error) goto done; error = view_loop(view); @@ -4624,7 +4630,7 @@ input_blame_view(struct tog_view **new_view, struct to break; } err = open_diff_view(diff_view, pid ? pid->id : NULL, - id, NULL, NULL, 3, 0, 0, NULL, s->repo); + id, NULL, NULL, 3, 0, 0, NULL, NULL, s->repo); got_object_commit_close(commit); if (err) { view_close(diff_view);
tog is sluggish with FreeBSD src.git