Skip to content

[bug] v2: Copying multiple files through the copyFile API is very slow and CPU usage is very high. #1464

@CoolTea001

Description

@CoolTea001

Describe the bug

When I used copyFile to copy a lot of audio files (around 5GB), I had to wait a long time and the CPU usage was up to 99%. But when I implemented it in Rust on the backend, it was almost instantaneous, with no big fluctuations in CPU usage.

copyFile API

async function startImport() {
    if (importMethod.value === 'file') {
        const selected = await open({
            multiple: true,
            filters: [
                {
                    name: 'Files',
                    extensions: [
                        ...SUPPORTED_FORMATS.music,
                        ...SUPPORTED_FORMATS.video,
                        ...SUPPORTED_FORMATS.lyrics,
                    ],
                },
            ],
        });

        if (selected && selected.length) {
            importLoading.value = true;

            try {
                if (!(await exists('music', { baseDir: BaseDirectory.AppLocalData }))) {
                    await mkdir('music', {
                        baseDir: BaseDirectory.AppLocalData,
                    });
                }

                for (const [index, file] of selected.entries()) {
                    importButtonText.value = `正在导入(${index + 1}/${selected.length})`;
                    await copyFile(file.path, 'music/' + file.name, {
                        toPathBaseDir: BaseDirectory.AppLocalData,
                    });
                }

                importDialogOpen.value = false;
                getMusicList();
            } catch (error) {
                console.error(error);
            } finally {
                importLoading.value = false;
                importButtonText.value = '确定';
            }
        }
    }
}

backend rust

#[tauri::command]
async fn import_music_by_files(
    files: Vec<String>,
    target_dir: String,
    music_formats: Vec<String>,
) -> Vec<String> {
    let mut copy_files = Vec::new();

    make_dir(&target_dir);

    for file in files {
        let file_name = get_file_name(&file);
        let target_path = format!("{}/{}", target_dir, file_name);

        match std::fs::copy(&file, &target_path) {
            Ok(_) => {
                if music_formats.contains(&file.split('.').last().unwrap().to_lowercase()) {
                    save_picture(target_path.clone());
                }

                copy_files.push(target_path);
            }
            Err(e) => {
                eprintln!("Error: {}", e);
            }
        }
    }

    copy_files
}

### Reproduction

_No response_

### Expected behavior

_No response_

### Full `tauri info` output

```text
Nothing.

Stack trace

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: fsIncludes former "fs-extra" and "fs-watch" pluginstype: bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions