مقایسه C، Go، و Rust برای عملکرد ساده I/O

Summarize this content to 400 words in Persian Lang
وقتی با دستگاهی به قدرتمندی AMD Ryzen Threadripper PRO 5975WX کار می کنید، انتظار دارید همه چیز به سرعت پیش برود. با 32 هسته، 64 پردازنده مجازی و 251 گیگابایت رم، به ندرت سخت افزار مشکل ساز است. معمولا این نرم افزار است.
این آزمایش سه زبان سیستمی محبوب – C، Go و Rust – را در یک کار ساده در برابر یکدیگر قرار می دهد: نوشتن 100000 خط در یک فایل. سوال این است که کدام یک از این وظایف اولیه ورودی/خروجی بهتر انجام میدهند؟ هر زبان نقاط قوت خود را دارد: C به دلیل سرعت خام و دسترسی مستقیم به سیستم شناخته شده است، Go همزمانی را ساده می کند و Rust امنیت حافظه را بدون به خطر انداختن عملکرد نوید می دهد.
ما نگاهی به عملکرد هر یک از این زبان ها با ردیابی تماس های سیستمی آنها، اندازه گیری زمان اجرای آنها و شناسایی محل برخورد آنها با snags خواهیم داشت.
راه اندازی
برای این آزمایش، هر برنامه بر روی یک ماشین در حال اجرا اجرا می شود اوبونتو 22.04 LTS با مشخصات زیر:
CPU: AMD Ryzen Threadripper PRO 5975WX (32 هسته، 64 رشته)
حافظه: 251 گیگابایت
دیسک: فضای زیادی وجود دارد، بنابراین موضوع اینجا نیست.
هر زبان وظیفه نوشتن 100000 خط در یک فایل را داشت و ما از آن استفاده کردیم خط کشی برای پیگیری تماس های سیستمی و زمان برای اندازه گیری مدت زمان آن
نتایج
در اینجا اعداد به دست آمد:
زبان
زمان I/O
زمان تماس سیستم
تعداد write تماس می گیرد
سی
0.007426 ثانیه
0.001266 ثانیه
267
برو
0.230 ثانیه
0.140 ثانیه
3,102
زنگ زدگی
5.47 ثانیه
1.35 ثانیه
300001
C به طرز عجیبی سریع است، که جای تعجب نیست. Go خوب است اما تقریباً به این سرعت نیست. از طرف دیگر، Rust با عملکرد مشکل دارد – اما دلیل آن جالب است.
چرا C برنده می شود
عملکرد C به سادگی کاهش می یابد. مستقیماً با سیستم تعامل دارد و در این تست فقط می سازد 267 سیستم برای نوشتن 100000 خط تماس می گیرد. این بدان معناست که C کار خود را با حداقل هزینه انجام می دهد و داده ها را مستقیماً به فایل با تداخل بسیار کمی منتقل می کند. به همین دلیل است که زبان C هنوز هم زمانی که عملکرد حیاتی است، زبان اصلی است.
در دستگاه شما، با وجود تمام آن هستهها و حافظه فراوان برای عملیات بافر، C میتواند به طور کامل از پتانسیل سختافزار استفاده کند. شما نیازی به نگرانی در مورد امنیت همزمان یا حافظه ندارید – C فقط کار را با همان سرعتی که سخت افزار اجازه می دهد انجام می دهد.
Go's Ground
عملکرد Go قابل احترام اما کندتر است و دلیل اصلی آن سربار زمان اجرا است. برو استفاده می کند فوتکس فراخوانی سیستم برای مدیریت گوروتین ها، که رشته های سبک وزن هستند. در این تست 88 درصد از زمان تماس سیستمی Go صرف این موارد می شود فوتکس تماس می گیرد. در حالی که فوتکس Go را برای کارهای همزمان قدرتمند می کند، برای کارهای ساده ورودی/خروجی مانند این سربار اضافه می کند.
با این حال، Go فقط می سازد 3,102 write تماس ها، که بسیار بیشتر از C اما بسیار کمتر از Rust است. این به لطف ورودی/خروجی بافر شده Go است که تعداد دفعاتی که برنامه باید به سیستم وارد شود را کاهش می دهد.
Go ممکن است به سرعت C در I/O خام نباشد، اما برای برنامههای پیچیدهتر و دنیای واقعی که همزمانی اهمیت دارد، طراحی شده است. در سیستمی مانند سیستم شما، توانایی Go برای انجام چندین کار به طور همزمان در نوع متفاوتی از حجم کار می درخشد.
گلوگاه زنگ
زنگ در این آزمایش کندترین است و مشکل واضح است: باعث می شود 300001 write تماس های سیستمی این یک برای هر خط نوشته شده، به علاوه یک برای هر کاراکتر خط جدید است. این هزینه زیادی است و توضیح می دهد که چرا Rust در مقایسه با C و Go طولانی می شود.
با این حال، مشکلی که در اینجا وجود دارد ذاتی Rust نیست – بلکه این است که کد بهینه نشده است. به طور پیشفرض، Rust از ورودی/خروجی بافر استفاده نمیکند، به این معنی که هر نوشته مستقیماً به سیستم میرود. با برخی بهینه سازی های ساده، Rust می تواند به راحتی شکاف عملکرد را کاهش دهد.
رفع زنگ زدگی
در اینجا نحوه ساخت Rust سریعتر با استفاده از یک رایتر بافر آورده شده است:
use std::fs::File;
use std::io::{BufWriter, Write};
use std::time::Instant;
fn main() {
let start = Instant::now();
let file = File::create(“output_rust.txt”).expect(“Could not create file”);
let mut writer = BufWriter::new(file);
for i in 0..100000 {
writeln!(writer, “Line {}”, i).expect(“Could not write to file”);
}
let duration = start.elapsed();
println!(“Rust I/O Time: {:?}”, duration);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با این تغییر کوچک، Rust می تواند به طور چشمگیری تعداد تماس های سیستمی را کاهش دهد و منجر به افزایش عملکرد قابل توجهی شود. این یک مثال عالی از این است که چگونه ویژگیهای ایمنی Rust مجبور نیستند به قیمت سرعت تمام شوند، تا زمانی که کد خود را برای کار در دست بهینه سازی کنید.
نتیجه گیری
اگر به سرعت I/O خام نیاز دارید، سی همچنان برنده واضح است رویکرد مستقیم آن به تماس های سیستمی و کمبود سربار زمان اجرا، آن را به سریع ترین گزینه برای کارهایی مانند این تبدیل کرده است.
برو تعادل خوبی بین سهولت استفاده و عملکرد، به ویژه در برنامه هایی که نیاز به همزمانی وجود دارد، فراهم می کند. در سیستمهای پیچیدهتر که چندین کار به صورت موازی اجرا میشوند، Go به دلیل گوروتینهایش به راحتی میتواند از C بهتر باشد.
زنگ زدگی، در حالی که در این تست کند است، می توان آن را با I/O بافر بهینه کرد. تمرکز Rust بر ایمنی آن را در مواقعی که به محافظت از سرعت و حافظه نیاز دارید، آن را به یک انتخاب عالی تبدیل می کند، اما باید مراقب نحوه مدیریت I/O باشید.
در سیستم شما، با قدرت پردازش و حافظه بسیار زیاد، هر سه زبان را می توان برای عملکرد بسیار خوب بهینه کرد. عملکرد C با وظایف سطح پایین می درخشد، Go با همزمانی پیشرفت می کند، و Rust این پتانسیل را دارد که هر دو را با بهینه سازی مناسب مطابقت دهد.
وقتی با دستگاهی به قدرتمندی AMD Ryzen Threadripper PRO 5975WX کار می کنید، انتظار دارید همه چیز به سرعت پیش برود. با 32 هسته، 64 پردازنده مجازی و 251 گیگابایت رم، به ندرت سخت افزار مشکل ساز است. معمولا این نرم افزار است.
این آزمایش سه زبان سیستمی محبوب – C، Go و Rust – را در یک کار ساده در برابر یکدیگر قرار می دهد: نوشتن 100000 خط در یک فایل. سوال این است که کدام یک از این وظایف اولیه ورودی/خروجی بهتر انجام میدهند؟ هر زبان نقاط قوت خود را دارد: C به دلیل سرعت خام و دسترسی مستقیم به سیستم شناخته شده است، Go همزمانی را ساده می کند و Rust امنیت حافظه را بدون به خطر انداختن عملکرد نوید می دهد.
ما نگاهی به عملکرد هر یک از این زبان ها با ردیابی تماس های سیستمی آنها، اندازه گیری زمان اجرای آنها و شناسایی محل برخورد آنها با snags خواهیم داشت.
راه اندازی
برای این آزمایش، هر برنامه بر روی یک ماشین در حال اجرا اجرا می شود اوبونتو 22.04 LTS با مشخصات زیر:
- CPU: AMD Ryzen Threadripper PRO 5975WX (32 هسته، 64 رشته)
- حافظه: 251 گیگابایت
- دیسک: فضای زیادی وجود دارد، بنابراین موضوع اینجا نیست.
هر زبان وظیفه نوشتن 100000 خط در یک فایل را داشت و ما از آن استفاده کردیم خط کشی برای پیگیری تماس های سیستمی و زمان برای اندازه گیری مدت زمان آن
نتایج
در اینجا اعداد به دست آمد:
زبان | زمان I/O | زمان تماس سیستم | تعداد write تماس می گیرد |
---|---|---|---|
سی | 0.007426 ثانیه | 0.001266 ثانیه | 267 |
برو | 0.230 ثانیه | 0.140 ثانیه | 3,102 |
زنگ زدگی | 5.47 ثانیه | 1.35 ثانیه | 300001 |
C به طرز عجیبی سریع است، که جای تعجب نیست. Go خوب است اما تقریباً به این سرعت نیست. از طرف دیگر، Rust با عملکرد مشکل دارد – اما دلیل آن جالب است.
چرا C برنده می شود
عملکرد C به سادگی کاهش می یابد. مستقیماً با سیستم تعامل دارد و در این تست فقط می سازد 267 سیستم برای نوشتن 100000 خط تماس می گیرد. این بدان معناست که C کار خود را با حداقل هزینه انجام می دهد و داده ها را مستقیماً به فایل با تداخل بسیار کمی منتقل می کند. به همین دلیل است که زبان C هنوز هم زمانی که عملکرد حیاتی است، زبان اصلی است.
در دستگاه شما، با وجود تمام آن هستهها و حافظه فراوان برای عملیات بافر، C میتواند به طور کامل از پتانسیل سختافزار استفاده کند. شما نیازی به نگرانی در مورد امنیت همزمان یا حافظه ندارید – C فقط کار را با همان سرعتی که سخت افزار اجازه می دهد انجام می دهد.
Go's Ground
عملکرد Go قابل احترام اما کندتر است و دلیل اصلی آن سربار زمان اجرا است. برو استفاده می کند فوتکس فراخوانی سیستم برای مدیریت گوروتین ها، که رشته های سبک وزن هستند. در این تست 88 درصد از زمان تماس سیستمی Go صرف این موارد می شود فوتکس تماس می گیرد. در حالی که فوتکس Go را برای کارهای همزمان قدرتمند می کند، برای کارهای ساده ورودی/خروجی مانند این سربار اضافه می کند.
با این حال، Go فقط می سازد 3,102 write
تماس ها، که بسیار بیشتر از C اما بسیار کمتر از Rust است. این به لطف ورودی/خروجی بافر شده Go است که تعداد دفعاتی که برنامه باید به سیستم وارد شود را کاهش می دهد.
Go ممکن است به سرعت C در I/O خام نباشد، اما برای برنامههای پیچیدهتر و دنیای واقعی که همزمانی اهمیت دارد، طراحی شده است. در سیستمی مانند سیستم شما، توانایی Go برای انجام چندین کار به طور همزمان در نوع متفاوتی از حجم کار می درخشد.
گلوگاه زنگ
زنگ در این آزمایش کندترین است و مشکل واضح است: باعث می شود 300001 write
تماس های سیستمی این یک برای هر خط نوشته شده، به علاوه یک برای هر کاراکتر خط جدید است. این هزینه زیادی است و توضیح می دهد که چرا Rust در مقایسه با C و Go طولانی می شود.
با این حال، مشکلی که در اینجا وجود دارد ذاتی Rust نیست – بلکه این است که کد بهینه نشده است. به طور پیشفرض، Rust از ورودی/خروجی بافر استفاده نمیکند، به این معنی که هر نوشته مستقیماً به سیستم میرود. با برخی بهینه سازی های ساده، Rust می تواند به راحتی شکاف عملکرد را کاهش دهد.
رفع زنگ زدگی
در اینجا نحوه ساخت Rust سریعتر با استفاده از یک رایتر بافر آورده شده است:
use std::fs::File;
use std::io::{BufWriter, Write};
use std::time::Instant;
fn main() {
let start = Instant::now();
let file = File::create("output_rust.txt").expect("Could not create file");
let mut writer = BufWriter::new(file);
for i in 0..100000 {
writeln!(writer, "Line {}", i).expect("Could not write to file");
}
let duration = start.elapsed();
println!("Rust I/O Time: {:?}", duration);
}
با این تغییر کوچک، Rust می تواند به طور چشمگیری تعداد تماس های سیستمی را کاهش دهد و منجر به افزایش عملکرد قابل توجهی شود. این یک مثال عالی از این است که چگونه ویژگیهای ایمنی Rust مجبور نیستند به قیمت سرعت تمام شوند، تا زمانی که کد خود را برای کار در دست بهینه سازی کنید.
نتیجه گیری
اگر به سرعت I/O خام نیاز دارید، سی همچنان برنده واضح است رویکرد مستقیم آن به تماس های سیستمی و کمبود سربار زمان اجرا، آن را به سریع ترین گزینه برای کارهایی مانند این تبدیل کرده است.
برو تعادل خوبی بین سهولت استفاده و عملکرد، به ویژه در برنامه هایی که نیاز به همزمانی وجود دارد، فراهم می کند. در سیستمهای پیچیدهتر که چندین کار به صورت موازی اجرا میشوند، Go به دلیل گوروتینهایش به راحتی میتواند از C بهتر باشد.
زنگ زدگی، در حالی که در این تست کند است، می توان آن را با I/O بافر بهینه کرد. تمرکز Rust بر ایمنی آن را در مواقعی که به محافظت از سرعت و حافظه نیاز دارید، آن را به یک انتخاب عالی تبدیل می کند، اما باید مراقب نحوه مدیریت I/O باشید.
در سیستم شما، با قدرت پردازش و حافظه بسیار زیاد، هر سه زبان را می توان برای عملکرد بسیار خوب بهینه کرد. عملکرد C با وظایف سطح پایین می درخشد، Go با همزمانی پیشرفت می کند، و Rust این پتانسیل را دارد که هر دو را با بهینه سازی مناسب مطابقت دهد.