Skip to content

Commit

Permalink
Avoid allocating tag names in a loop
Browse files Browse the repository at this point in the history
  • Loading branch information
w4 committed Oct 17, 2024
1 parent 9bd568f commit 8ecc2c5
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/database/schema/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl CommitTree {
};

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)
Expand Down
17 changes: 12 additions & 5 deletions src/database/schema/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct TagTree {
prefix: RepositoryId,
}

pub type YokedString = Yoked<&'static str>;
pub type YokedTag = Yoked<&'static <Tag as Archive>::Archived>;

impl TagTree {
Expand Down Expand Up @@ -88,7 +89,7 @@ impl TagTree {
.collect())
}

pub fn fetch_all(&self) -> anyhow::Result<Vec<(String, YokedTag)>> {
pub fn fetch_all(&self) -> anyhow::Result<Vec<(YokedString, YokedTag)>> {
let cf = self
.db
.cf_handle(TAG_FAMILY)
Expand All @@ -99,9 +100,15 @@ impl TagTree {
.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))
})
Expand All @@ -111,7 +118,7 @@ impl TagTree {
})?;
Ok((name, value))
})
.collect::<anyhow::Result<Vec<(String, YokedTag)>>>()?;
.collect::<anyhow::Result<Vec<(YokedString, YokedTag)>>>()?;

res.sort_unstable_by(|a, b| {
let a_tagger = a.1.get().tagger.as_ref().map(ArchivedAuthor::time);
Expand Down
3 changes: 1 addition & 2 deletions src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,7 @@ impl OpenRepository {
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(
Expand Down
3 changes: 2 additions & 1 deletion src/methods/repo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use self::{
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,
Expand Down Expand Up @@ -192,5 +193,5 @@ impl IntoResponse for Error {

pub struct Refs {
heads: BTreeMap<String, YokedCommit>,
tags: Vec<(String, YokedTag)>,
tags: Vec<(YokedString, YokedTag)>,
}
23 changes: 13 additions & 10 deletions src/methods/repo/refs.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
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::{
filters,
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")]
Expand All @@ -28,17 +28,20 @@ pub async fn handle(
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()?) {
Expand All @@ -47,7 +50,7 @@ pub async fn handle(
}
}

let tags = repository.get().tag_tree(db).fetch_all()?;
let tags = repository.tag_tree(db).fetch_all()?;

Ok(into_response(View {
repo,
Expand Down
4 changes: 2 additions & 2 deletions templates/repo/macros/refs.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
<tbody>
{% for (name, tag) in tags -%}
<tr>
<td><a href="/{{ repo.display() }}/tag/?h={{ name }}">{{- name -}}</a></td>
<td><a href="/{{ repo.display() }}/snapshot?h={{ name }}">{{- name -}}.tar.gz</a></td>
<td><a href="/{{ repo.display() }}/tag/?h={{ name.get() }}">{{- name.get() -}}</a></td>
<td><a href="/{{ repo.display() }}/snapshot?h={{ name.get() }}">{{- name.get() -}}.tar.gz</a></td>
<td>
{% if let Some(tagger) = tag.get().tagger.as_ref() -%}
<img src="{{ tagger.email|gravatar }}" width="13" height="13">
Expand Down

0 comments on commit 8ecc2c5

Please sign in to comment.