Skip to content

Commit c144c26

Browse files
committed
Reduce allocations in fs::copy_files_except_ext
Above mentioned function copies files (recursively) from a source to a destination directory. For that, file/directory paths have to be created repeatedly. This allocates as directory and file names are concatenated into an owning path structure. The number of allocations can be reduced by creating file/directory paths only once and borrowing them instead of cloning/recreating them. In bigger projects, this reduces execution time noticeably. Please note that file system operations are dominant from performance POV.
1 parent bd323fb commit c144c26

File tree

1 file changed

+19
-52
lines changed

1 file changed

+19
-52
lines changed

src/utils/fs.rs

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,12 @@ pub fn create_file(path: &Path) -> Result<File> {
7272

7373
/// Removes all the content of a directory but not the directory itself
7474
pub fn remove_dir_content(dir: &Path) -> Result<()> {
75-
for item in fs::read_dir(dir)? {
76-
if let Ok(item) = item {
77-
let item = item.path();
78-
if item.is_dir() {
79-
fs::remove_dir_all(item)?;
80-
} else {
81-
fs::remove_file(item)?;
82-
}
75+
for item in fs::read_dir(dir)?.flatten() {
76+
let item = item.path();
77+
if item.is_dir() {
78+
fs::remove_dir_all(item)?;
79+
} else {
80+
fs::remove_file(item)?;
8381
}
8482
}
8583
Ok(())
@@ -108,72 +106,41 @@ pub fn copy_files_except_ext(
108106
}
109107

110108
for entry in fs::read_dir(from)? {
111-
let entry = entry?;
109+
let entry = entry?.path();
112110
let metadata = entry
113-
.path()
114111
.metadata()
115-
.with_context(|| format!("Failed to read {:?}", entry.path()))?;
112+
.with_context(|| format!("Failed to read {entry:?}"))?;
113+
114+
let entry_file_name = entry.file_name().unwrap();
115+
let target_file_path = to.join(entry_file_name);
116116

117117
// If the entry is a dir and the recursive option is enabled, call itself
118118
if metadata.is_dir() && recursive {
119-
if entry.path() == to.to_path_buf() {
119+
if entry == to.as_os_str() {
120120
continue;
121121
}
122122

123123
if let Some(avoid) = avoid_dir {
124-
if entry.path() == *avoid {
124+
if entry == *avoid {
125125
continue;
126126
}
127127
}
128128

129129
// check if output dir already exists
130-
if !to.join(entry.file_name()).exists() {
131-
fs::create_dir(&to.join(entry.file_name()))?;
130+
if !target_file_path.exists() {
131+
fs::create_dir(&target_file_path)?;
132132
}
133133

134-
copy_files_except_ext(
135-
&from.join(entry.file_name()),
136-
&to.join(entry.file_name()),
137-
true,
138-
avoid_dir,
139-
ext_blacklist,
140-
)?;
134+
copy_files_except_ext(&entry, &target_file_path, true, avoid_dir, ext_blacklist)?;
141135
} else if metadata.is_file() {
142136
// Check if it is in the blacklist
143-
if let Some(ext) = entry.path().extension() {
137+
if let Some(ext) = entry.extension() {
144138
if ext_blacklist.contains(&ext.to_str().unwrap()) {
145139
continue;
146140
}
147141
}
148-
debug!(
149-
"creating path for file: {:?}",
150-
&to.join(
151-
entry
152-
.path()
153-
.file_name()
154-
.expect("a file should have a file name...")
155-
)
156-
);
157-
158-
debug!(
159-
"Copying {:?} to {:?}",
160-
entry.path(),
161-
&to.join(
162-
entry
163-
.path()
164-
.file_name()
165-
.expect("a file should have a file name...")
166-
)
167-
);
168-
copy(
169-
entry.path(),
170-
&to.join(
171-
entry
172-
.path()
173-
.file_name()
174-
.expect("a file should have a file name..."),
175-
),
176-
)?;
142+
debug!("Copying {entry:?} to {target_file_path:?}");
143+
copy(&entry, &target_file_path)?;
177144
}
178145
}
179146
Ok(())

0 commit comments

Comments
 (0)