However, it doesn't seem to have more than a minor effect. ➜ gitoxide git:(main) ✗ cargo run --no-default-features --features lean --bin gixp --release -- -v pack-create -r ../../torvalds/linux dd860052c99b1e088352bdd4fb7aef46f8d2ef47 > /dev/null Compiling git-odb v0.15.0 (/Users/byron/dev/github.com/Byron/gitoxide/git-odb) Compiling gitoxide-core v0.9.0 (/Users/byron/dev/github.com/Byron/gitoxide/gitoxide-core) Compiling gitoxide v0.7.0 (/Users/byron/dev/github.com/Byron/gitoxide) Finished release [optimized] target(s) in 31.72s Running `target/release/gixp -v pack-create -r ../../torvalds/linux dd860052c99b1e088352bdd4fb7aef46f8d2ef47` 15:16:19 counting done 8.1M objects in 47.27s (171.6k objects/s) pack-create 3 of 3 steps [================================>----------------] creating entries entries written writing 1.2GB |259.8MB/s| [ === === === === === === === === ] Compared to about 48 to 49s before.
Unified · Split
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | use crate::pack::bundle::Location; |
| 2 | 2 | use crate::{compound, data::Object, find::PackEntry, linked, pack}; |
| 3 | 3 | use git_hash::oid; |
| 4 | −use std::convert::TryInto; | |
| 5 | 4 | |
| 6 | 5 | impl crate::Find for linked::Db { |
| 7 | 6 | type Error = compound::find::Error; |
| @@ -46,16 +45,21 @@ impl crate::Find for linked::Db { · 38 unmodified lines | ||
| 46 | 45 | let pack_offset = bundle.index.pack_offset_at_index(entry_index); |
| 47 | 46 | let entry = bundle.pack.entry(pack_offset); |
| 48 | 47 | |
| 49 | − buf.resize(entry.decompressed_size.try_into().expect("representable szie"), 0); | |
| 50 | − return bundle | |
| 51 | − .pack | |
| 52 | − .decompress_entry(&entry, buf) | |
| 53 | − .ok() | |
| 54 | − .map(|entry_size| pack::bundle::Location { | |
| 55 | − pack_id: bundle.pack.id, | |
| 56 | − index_file_id: entry_index, | |
| 57 | − entry_size: entry.header_size() + entry_size, | |
| 58 | − }); | |
| 48 | + let offset_index = bundle | |
| 49 | + .sorted_offsets | |
| 50 | + .binary_search(&pack_offset) | |
| 51 | + .expect("a perfect match") | |
| 52 | + + 1; | |
| 53 | + let entry_size = if offset_index == bundle.pack.num_objects() as usize { | |
| 54 | + bundle.pack.pack_end() as u64 | |
| 55 | + } else { | |
| 56 | + bundle.sorted_offsets[offset_index] | |
| 57 | + } - entry.data_offset; | |
| 58 | + Some(pack::bundle::Location { | |
| 59 | + pack_id: bundle.pack.id, | |
| 60 | + index_file_id: entry_index, | |
| 61 | + entry_size: entry.header_size() + entry_size as usize, | |
| 62 | + }); | |
| 59 | 63 | } |
| 60 | 64 | } |
| 61 | 65 | None |
| @@ -75,6 +75,7 @@ pub struct Bundle { · 74 unmodified lines | ||
| 75 | 75 | pub pack: pack::data::File, |
| 76 | 76 | /// The index file corresponding to `pack` |
| 77 | 77 | pub index: pack::index::File, |
| 78 | + pub(crate) sorted_offsets: Vec<u64>, | |
| 78 | 79 | } |
| 79 | 80 | |
| 80 | 81 | /// Initialization |
| @@ -97,15 +98,31 @@ impl TryFrom<&Path> for Bundle { · 16 unmodified lines | ||
| 97 | 98 | .and_then(|e| e.to_str()) |
| 98 | 99 | .ok_or_else(|| Error::InvalidPath(path.to_owned()))?; |
| 99 | 100 | Ok(match ext { |
| 100 | − "idx" => Self { | |
| 101 | − index: pack::index::File::at(path)?, | |
| 102 | − pack: pack::data::File::at(path.with_extension("pack"))?, | |
| 103 | − }, | |
| 104 | − "pack" => Self { | |
| 105 | − pack: pack::data::File::at(path)?, | |
| 106 | − index: pack::index::File::at(path.with_extension("idx"))?, | |
| 107 | − }, | |
| 101 | + "idx" => { | |
| 102 | + let index = pack::index::File::at(path)?; | |
| 103 | + let sorted_offsets = offsets_from_index(&index); | |
| 104 | + Self { | |
| 105 | + index, | |
| 106 | + pack: pack::data::File::at(path.with_extension("pack"))?, | |
| 107 | + sorted_offsets, | |
| 108 | + } | |
| 109 | + } | |
| 110 | + "pack" => { | |
| 111 | + let index = pack::index::File::at(path.with_extension("idx"))?; | |
| 112 | + let sorted_offsets = offsets_from_index(&index); | |
| 113 | + Self { | |
| 114 | + pack: pack::data::File::at(path)?, | |
| 115 | + index, | |
| 116 | + sorted_offsets, | |
| 117 | + } | |
| 118 | + } | |
| 108 | 119 | _ => return Err(Error::InvalidPath(path.to_owned())), |
| 109 | 120 | }) |
| 110 | 121 | } |
| 111 | 122 | } |
| 123 | + | |
| 124 | +fn offsets_from_index(index: &pack::index::File) -> Vec<u64> { | |
| 125 | + let mut out = index.iter().map(|e| e.pack_offset).collect::<Vec<_>>(); | |
| 126 | + out.sort(); | |
| 127 | + out | |
| 128 | +} | |