Skip to content

Commit

Permalink
nydus-image: optimize the way to generate tarfs
Browse files Browse the repository at this point in the history
Optimize the way to generate tarfs from tar file, to reduce memory
and time consumption.

Signed-off-by: Jiang Liu <[email protected]>
  • Loading branch information
jiangliu authored and imeoer committed Apr 23, 2023
1 parent d9fe6d8 commit 27fa973
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 89 deletions.
3 changes: 1 addition & 2 deletions rafs/src/builder/core/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ impl Bootstrap {
if parent.is_dir() {
// Sort children list by name, so that we can improve performance in fs read_dir using
// binary search.
tree.children
.sort_by_key(|child| child.node.name().to_os_string());
tree.children.sort_by_key(|child| child.name.clone());
parent.inode.set_child_count(tree.children.len() as u32);
if ctx.fs_version.is_v5() {
parent.inode.set_child_index(index);
Expand Down
31 changes: 21 additions & 10 deletions rafs/src/builder/core/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! lower tree (MetadataTree).
//! - Traverse the merged tree (OverlayTree) to dump bootstrap and data blobs.
use std::ffi::OsStr;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::sync::Arc;

Expand All @@ -36,15 +36,18 @@ use crate::metadata::{Inode, RafsInodeExt, RafsSuper};
pub struct Tree {
/// Filesystem node.
pub node: Node,
pub name: OsString,
/// Children tree nodes.
pub children: Vec<Tree>,
}

impl Tree {
/// Create a new instance of `Tree` from a filesystem node.
pub fn new(node: Node) -> Self {
let name = node.name().to_owned();
Tree {
node,
name,
children: Vec::new(),
}
}
Expand Down Expand Up @@ -86,6 +89,17 @@ impl Tree {
Ok(())
}

/// Get index of child node with specified `name`.
#[allow(clippy::manual_find)]
pub fn get_child_idx(&self, name: &OsStr) -> Option<usize> {
for idx in 0..self.children.len() {
if self.children[idx].name == name {
return Some(idx);
}
}
None
}

/// Apply new node (upper layer) to node tree (lower layer).
///
/// Support overlay defined in OCI image layer spec
Expand Down Expand Up @@ -133,7 +147,7 @@ impl Tree {
for idx in 0..self.children.len() {
let child = &mut self.children[idx];
// Skip if path component name not match
if target_paths[depth] != child.node.name() {
if target_paths[depth] != child.name {
continue;
}
// Modifications: Replace the node
Expand All @@ -154,13 +168,10 @@ impl Tree {
}

// Additions: Add new node to children
if depth == target_paths_len - 1 && target_paths[depth - 1] == self.node.name() {
if depth == target_paths_len - 1 && target_paths[depth - 1] == self.name {
let mut node = target.clone();
node.overlay = Overlay::UpperAddition;
self.children.push(Tree {
node,
children: Vec::new(),
});
self.children.push(Tree::new(node));
return Ok(true);
}

Expand Down Expand Up @@ -202,7 +213,7 @@ impl Tree {
// Handle Removals
if depth == target_paths_len - 1
&& whiteout_type.is_removal()
&& origin_name == Some(child.node.name())
&& origin_name == Some(&child.name)
{
// Remove the whole lower node
self.children.remove(idx);
Expand All @@ -215,7 +226,7 @@ impl Tree {
&& depth == target_paths_len - 2
{
if let Some(parent_name) = parent_name {
if parent_name == child.node.name() {
if parent_name == child.name {
child.node.overlay = Overlay::UpperOpaque;
// Remove children of the lower node
child.children.clear();
Expand All @@ -224,7 +235,7 @@ impl Tree {
}
} else if whiteout_type == WhiteoutType::OverlayFsOpaque
&& depth == target_paths_len - 1
&& target.name() == child.node.name()
&& target.name() == child.name
{
// Remove all children under the opaque directory
child.node.overlay = Overlay::UpperOpaque;
Expand Down
10 changes: 5 additions & 5 deletions rafs/src/builder/core/v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,14 @@ impl Node {
let mut d_size = 0;

// Sort all children if "." and ".." are not at the head after sorting.
if !tree.children.is_empty() && tree.children[0].node.name() < ".." {
if !tree.children.is_empty() && tree.children[0].name < *".." {
let mut children = Vec::with_capacity(tree.children.len() + 2);
let dot = OsString::from(".");
let dotdot = OsString::from("..");
children.push(dot.as_os_str());
children.push(dotdot.as_os_str());
for child in tree.children.iter() {
children.push(child.node.name());
children.push(&child.name);
}
children.sort_unstable();

Expand All @@ -187,7 +187,7 @@ impl Node {
+ "..".as_bytes().len()
+ size_of::<RafsV6Dirent>()) as u64;
for child in tree.children.iter() {
let len = child.node.name().as_bytes().len() + size_of::<RafsV6Dirent>();
let len = child.name.as_bytes().len() + size_of::<RafsV6Dirent>();
// erofs disk format requires dirent to be aligned to block size.
if (d_size % block_size) + len as u64 > block_size {
d_size = round_up(d_size as u64, block_size);
Expand Down Expand Up @@ -604,13 +604,13 @@ impl Bootstrap {
trace!(
"{:?} child {:?} offset {}, mode {}",
node.name(),
child.node.name(),
child.name,
child.node.v6_offset,
child.node.inode.mode()
);
node.v6_dirents.push((
child.node.v6_offset,
child.node.name().to_os_string(),
child.name.to_os_string(),
child.node.inode.mode(),
));
if child.node.is_dir() {
Expand Down
Loading

0 comments on commit 27fa973

Please sign in to comment.