開発

[rust] mutexを使わないバージョン tokio版ディレクトリ再帰的取得

前回の続き。mutexを使わないバージョンで書き直してみました。

mutex以外も見直して変更をしましたがスッキリ書けました。処理速度も書き直す前と比べてそれほど変わらないです。

tokioを使ったバージョンはこれで終わりにしたいと思います。

次はtokioに代わりasync-stdを使って書き直してみます。

MeanStd.Dev.MinMedianMax
real3.1830.1663.0863.164.303
user2.4250.1092.2242.4222.776
sys8.5560.3728.2168.49410.922
VCPU=4
MeanStd.Dev.MinMedianMax
real4.5740.1694.3914.5475.648
user5.880.1825.5845.8666.665
sys11.0470.35810.44711.03313.08
VCPU=4, Worker=5000
MeanStd.Dev.MinMedianMax
real4.5040.3144.2584.466.557
user3.6780.1633.4123.6574.21
sys17.2840.95716.39117.14823.445
VCPU=6
MeanStd.Dev.MinMedianMax
real6.2040.4125.1536.1687.923
user9.2010.2458.7479.1729.887
sys23.8542.2216.86223.8630.093
VCPU=6, Worker=5000
use anyhow::Result; // 1.0.71
use clap::Parser; // 4.3.11

use tokio::fs; // 1.32.0
use tokio::task::JoinSet;

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// target directory
    #[arg(short, long, default_value_t = String::from(".") )]
    dir: String,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Args::parse();

    let dir_string = args.dir.to_string();
    println!("{}", dir_string);

    let mut list_from_thd: Vec<String> = vec![dir_string];

    // Like a do-while
    while !list_from_thd.is_empty() {
        let mut thds = JoinSet::new();

        for item in list_from_thd {
            thds.spawn(get_dirs(item));
        }

        let mut new_dir_list = Vec::<String>::new();
        while let Some(Ok(Ok(mut dir))) = thds.join_next().await {
            new_dir_list.append(&mut dir);
        }

        list_from_thd = new_dir_list;
    }

    Ok(())
}

async fn get_dirs(dir: String) -> Result<Vec<String>> {
    let mut entries = fs::read_dir(dir).await?;

    // Folder list
    let mut dirs = Vec::<String>::new();

    let mut thds = JoinSet::new();

    while let Some(entry) = entries.next_entry().await? {
        let metadata = entry.metadata().await?;
        let path = entry.path();
        let path_2 = path.clone();

        thds.spawn(async move {
            let path = path.display().to_string();
            if metadata.is_dir() {
                println!("{}", path);

                return path;
            }

            String::with_capacity(0)
        });

        thds.spawn(async move {
            let path = path_2;
            if let Ok(symlink) = fs::read_link(&path).await {
                if path.is_dir() {
                    println!("{}@ -> {}", path.display(), symlink.display());
                }
            }

            String::with_capacity(0)
        });
    }

    while let Some(Ok(dir)) = thds.join_next().await {
        if !dir.is_empty() {
            dirs.push(dir);
        }
    }

    Ok(dirs)
}
Code language: PHP (php)
管理人

Recent Posts

情報セキュリティマネジメント試験取得への道

スキルアップを図るべく情報セキ…

2か月 ago

ファイナンシャルプランナー3級試験取得への道

スキルアップを図るべくファイナ…

2か月 ago

[rust] New Type Patternを使ってみる

DDDの考えを取り入れることで…

5か月 ago

RustでDDDの要素を取り入れてみる

前回SOLID原則というものを…

5か月 ago

期間限定!書籍無料キャンペーン2025

「mdBookではじめるKin…

5か月 ago