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 | use crate::pack::bundle::Location; | 1 | use crate::pack::bundle::Location; |
| 2 | use crate::{compound, data::Object, find::PackEntry, linked, pack}; | 2 | use crate::{compound, data::Object, find::PackEntry, linked, pack}; |
| 3 | use git_hash::oid; | 3 | use git_hash::oid; |
| 4 | use std::convert::TryInto; | ||
| 5 | 4 | ||
| 6 | impl crate::Find for linked::Db { | 5 | impl crate::Find for linked::Db { |
| 7 | type Error = compound::find::Error; | 6 | type Error = compound::find::Error; |
| @@ -46,16 +45,21 @@ impl crate::Find for linked::Db { · 38 unmodified lines | |||
| 46 | let pack_offset = bundle.index.pack_offset_at_index(entry_index); | 45 | let pack_offset = bundle.index.pack_offset_at_index(entry_index); |
| 47 | let entry = bundle.pack.entry(pack_offset); | 46 | let entry = bundle.pack.entry(pack_offset); |
| 48 | 47 | ||
| 49 | buf.resize(entry.decompressed_size.try_into().expect("representable szie"), 0); | 48 | let offset_index = bundle |
| 50 | return bundle | 49 | .sorted_offsets |
| 51 | .pack | 50 | .binary_search(&pack_offset) |
| 52 | .decompress_entry(&entry, buf) | 51 | .expect("a perfect match") |
| 53 | .ok() | 52 | + 1; |
| 54 | .map(|entry_size| pack::bundle::Location { | 53 | let entry_size = if offset_index == bundle.pack.num_objects() as usize { |
| 55 | pack_id: bundle.pack.id, | 54 | bundle.pack.pack_end() as u64 |
| 56 | index_file_id: entry_index, | 55 | } else { |
| 57 | entry_size: entry.header_size() + entry_size, | 56 | bundle.sorted_offsets[offset_index] |
| 58 | }); | 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 | None | 65 | None |
| @@ -75,6 +75,7 @@ pub struct Bundle { · 74 unmodified lines | |||
| 75 | pub pack: pack::data::File, | 75 | pub pack: pack::data::File, |
| 76 | /// The index file corresponding to `pack` | 76 | /// The index file corresponding to `pack` |
| 77 | pub index: pack::index::File, | 77 | pub index: pack::index::File, |
| 78 | pub(crate) sorted_offsets: Vec<u64>, | ||
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | /// Initialization | 81 | /// Initialization |
| @@ -97,15 +98,31 @@ impl TryFrom<&Path> for Bundle { · 16 unmodified lines | |||
| 97 | .and_then(|e| e.to_str()) | 98 | .and_then(|e| e.to_str()) |
| 98 | .ok_or_else(|| Error::InvalidPath(path.to_owned()))?; | 99 | .ok_or_else(|| Error::InvalidPath(path.to_owned()))?; |
| 99 | Ok(match ext { | 100 | Ok(match ext { |
| 100 | "idx" => Self { | 101 | "idx" => { |
| 101 | index: pack::index::File::at(path)?, | 102 | let index = pack::index::File::at(path)?; |
| 102 | pack: pack::data::File::at(path.with_extension("pack"))?, | 103 | let sorted_offsets = offsets_from_index(&index); |
| 103 | }, | 104 | Self { |
| 104 | "pack" => Self { | 105 | index, |
| 105 | pack: pack::data::File::at(path)?, | 106 | pack: pack::data::File::at(path.with_extension("pack"))?, |
| 106 | index: pack::index::File::at(path.with_extension("idx"))?, | 107 | sorted_offsets, |
| 107 | }, | 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 | _ => return Err(Error::InvalidPath(path.to_owned())), | 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 | } | ||