From 8ecc2c5a51717c83614410c9c67cb1346e238d22 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 17 Oct 2024 18:49:14 +0100 Subject: [PATCH] Avoid allocating tag names in a loop --- src/git.rs | 3 +-- src/database/schema/commit.rs | 2 +- src/database/schema/tag.rs | 17 +++++++++++++++-- src/methods/repo/mod.rs | 3 ++- src/methods/repo/refs.rs | 23 ++++++++++++++++++----- templates/repo/macros/refs.html | 4 ++-- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/git.rs b/src/git.rs index d5dd2b4..aa26a9b 100644 --- a/src/git.rs +++ a/src/git.rs @@ -216,8 +216,7 @@ while let Ok(Some(Ok(item))) = object .try_into_tree() .iter() - .map(gix::Tree::iter) - .flatten() + .flat_map(gix::Tree::iter) .at_most_one() { let nested_object = item.object().context( diff --git a/src/database/schema/commit.rs b/src/database/schema/commit.rs index 567568b..4cd97af 100644 --- a/src/database/schema/commit.rs +++ a/src/database/schema/commit.rs @@ -166,7 +166,7 @@ }; Yoke::try_attach_to_cart(Box::from(value), |value| { - rkyv::access::<_, rkyv::rancor::Error>(&value) + rkyv::access::<_, rkyv::rancor::Error>(value) }) .context("Failed to deserialize commit") .map(Some) diff --git a/src/database/schema/tag.rs b/src/database/schema/tag.rs index 60cf53c..e57dfa9 100644 --- a/src/database/schema/tag.rs +++ a/src/database/schema/tag.rs @@ -34,6 +34,7 @@ prefix: RepositoryId, } +pub type YokedString = Yoked<&'static str>; pub type YokedTag = Yoked<&'static ::Archived>; impl TagTree { @@ -88,7 +89,7 @@ .collect()) } - pub fn fetch_all(&self) -> anyhow::Result> { + pub fn fetch_all(&self) -> anyhow::Result> { let cf = self .db .cf_handle(TAG_FAMILY) @@ -99,9 +100,15 @@ .prefix_iterator_cf(cf, self.prefix.to_be_bytes()) .filter_map(Result::ok) .filter_map(|(name, value)| { - let name = String::from_utf8_lossy(name.strip_prefix(&self.prefix.to_be_bytes())?) - .strip_prefix("refs/tags/")? - .to_string(); + let name = Yoke::try_attach_to_cart(name, |data| { + let data = data + .strip_prefix(&self.prefix.to_be_bytes()) + .ok_or(())? + .strip_prefix(b"refs/tags/") + .ok_or(())?; + simdutf8::basic::from_utf8(data).map_err(|_| ()) + }) + .ok()?; Some((name, value)) }) @@ -111,7 +118,7 @@ })?; Ok((name, value)) }) - .collect::>>()?; + .collect::>>()?; res.sort_unstable_by(|a, b| { let a_tagger = a.1.get().tagger.as_ref().map(ArchivedAuthor::time); diff --git a/src/methods/repo/mod.rs b/src/methods/repo/mod.rs index 6ed5cdb..43ac306 100644 --- a/src/methods/repo/mod.rs +++ a/src/methods/repo/mod.rs @@ -37,6 +37,7 @@ tag::handle as handle_tag, tree::handle as handle_tree, }; +use crate::database::schema::tag::YokedString; use crate::{ database::schema::{commit::YokedCommit, tag::YokedTag}, layers::UnwrapInfallible, @@ -192,5 +193,5 @@ pub struct Refs { heads: BTreeMap, - tags: Vec<(String, YokedTag)>, + tags: Vec<(YokedString, YokedTag)>, } diff --git a/src/methods/repo/refs.rs b/src/methods/repo/refs.rs index 8af9651..f81b062 100644 --- a/src/methods/repo/refs.rs +++ a/src/methods/repo/refs.rs @@ -1,10 +1,5 @@ use std::{collections::BTreeMap, sync::Arc}; -use anyhow::Context; -use askama::Template; -use axum::{response::IntoResponse, Extension}; -use rkyv::string::ArchivedString; - use crate::{ into_response, methods::{ @@ -12,6 +7,11 @@ repo::{Refs, Repository, Result}, }, }; +use anyhow::Context; +use askama::Template; +use axum::{response::IntoResponse, Extension}; +use rkyv::string::ArchivedString; +use yoke::Yoke; #[derive(Template)] #[template(path = "repo/refs.html")] @@ -28,17 +28,20 @@ tokio::task::spawn_blocking(move || { let repository = crate::database::schema::repository::Repository::open(&db, &*repo)? .context("Repository does not exist")?; + let repository = repository.get(); + + let heads_db = repository.heads(&db)?; + let heads_db = heads_db.as_ref().map(Yoke::get); let mut heads = BTreeMap::new(); - if let Some(heads_db) = repository.get().heads(&db)? { - for head in heads_db - .get() + if let Some(archived_heads) = heads_db { + for head in archived_heads .0 .as_slice() .iter() .map(ArchivedString::as_str) { - let commit_tree = repository.get().commit_tree(db.clone(), head); + let commit_tree = repository.commit_tree(db.clone(), head); let name = head.strip_prefix("refs/heads/"); if let (Some(name), Some(commit)) = (name, commit_tree.fetch_latest_one()?) { @@ -47,7 +50,7 @@ } } - let tags = repository.get().tag_tree(db).fetch_all()?; + let tags = repository.tag_tree(db).fetch_all()?; Ok(into_response(View { repo, diff --git a/templates/repo/macros/refs.html b/templates/repo/macros/refs.html index d054429..bcaeee2 100644 --- a/templates/repo/macros/refs.html +++ a/templates/repo/macros/refs.html @@ -40,8 +40,8 @@ {% for (name, tag) in tags -%} - {{- name -}} - {{- name -}}.tar.gz + {{- name.get() -}} + {{- name.get() -}}.tar.gz {% if let Some(tagger) = tag.get().tagger.as_ref() -%} -- rgit 0.1.3