Sharp The Rusty Code
Once upon a time, in the land of curly braces, I, a devoted C# enthusiast, embarked on a daring adventure to explore the mysterious realm of Rust. Rust burst onto the scene like a supernova, capturing the hearts and minds of developers around the globe. Its focus on safety, performance, and concurrency has earned it a dedicated following, and even the Linux kernel couldn’t resist Rust’s allure. As Rust continues to make waves in the world of systems programming, C# watches from the sidelines, confidently flexing its newfound performance muscles and ready to take on any challenge that comes its way.
While Rust’s safety features and swift performance tempted me, its cryptic syntax and peculiar design choices soon had me pining for the familiar embrace of C#. Rumor had it that C# and .NET 7 had been hitting the performance gym, so I decided to rekindle our romance. In this blog post, I’ll chronicle my journey back to C# and compare its newfound strength with Rust using some good ol’ benchmarking results.
C# Sharpens Its Edge
It turns out that while I was flirting with Rust, C# had been diligently honing its edge like a master swordsmith. .NET devs had been forging tirelessly to improve C#’s performance and the .NET runtime, forging the razor-sharp .NET 7.
The Computer Language Benchmarks Game showcased the fruits of C#’s labor, revealing significant improvements in execution time and memory consumption. C# now slices through performance benchmarks alongside Rust, demonstrating that it’s no longer the blunt underdog in the performance arena.
Meanwhile, the TechEmpower web framework benchmarks crowned ASP.NET Core among the elite, proving that C# and .NET 7 can deliver high-performance web applications with the precision of a finely-crafted blade, rivaling Rust-based web frameworks like Axum.
C#’s “New” Superpower
During its time at the forge, C# discovered a new superpower: Ahead-of-Time (AOT) compilation. This newfound ability allows C# to compile code into native machine code before runtime, skipping the more leisurely Just-In-Time (JIT) compilation process.
AOT compilation not only reduces startup times but also enhances performance optimization. AOT and JIT compilations are like two superheroes with different origin stories, each with its own strengths and weaknesses. AOT, the more proactive of the two, compiles code into native machine code before runtime, flexing its muscles to reduce startup times and optimize performance. On the other hand, JIT, the more leisurely and contemplative hero, compiles code during runtime, taking its sweet time to optimize based on the application’s real-world usage.
C#, being the more application-driven and versatile chameleon that it is, initially chose JIT as its trusty sidekick. However, as C# realized it could cater to more performance-critical scenarios, like games, it embraced AOT, stepping out of its comfort zone and broadening its horizons.
- Java (mostly JIT, but can use AOT in specific cases)
- Both AOT and JIT
- Kotlin/Native (for native platforms)
The Rusty Side of the Coin
Rust is undeniably a fascinating language, boasting a focus on safety and exceptional performance. However, its syntax and design choices can sometimes feel like deciphering ancient hieroglyphics. With a slew of abbreviated keywords like
impl, Rust might as well be speaking in code.
In addition, Rust’s syntax deviates significantly from its more familiar counterparts like C# and Java. Rust’s concepts of lifetimes and ownership can leave developers accustomed to garbage-collected languages scratching their heads in bewilderment.
Check a box on which concept to you ever heard of:
- Lifetimes and Ownership
- Borrow Checker
- Pattern matching syntax with match and _ (wildcard)
- Option and Result types for error handling
- Trait-based generics
- Macros with a
Congratulations: you scored Zero points!
Meanwhile, C# retains its elegant simplicity, with meaningful keywords and design choices that prioritize readability and user-friendliness. Over time, C# has embraced modern features like pattern matching, nullable reference types, and async/await, all while maintaining its easy-going charm.
Back to The Future
My escapade into Rust was undoubtedly an eye-opening experience, allowing me to appreciate the powerful capabilities of both languages. However, Rust’s enigmatic syntax and design choices had me yearning for the warm, familiar comfort of C#. Returning to the latest C#, I discovered a language that had evolved and adapted, offering a potent combination of performance, elegance, and ease of use.
As C# and .NET 7 bask in the limelight, little do they know that .NET 8 is waiting in the wings, ready to dazzle us with even more breathtaking improvements. Rumor has it that .NET 8 will further incorporate functionalities from popular third-party libraries, making it an even more enticing one-stop shop for developers. With the pace of innovation accelerating, the future of C# and the .NET universe looks brighter than ever.
So, my fellow developers, let my tale be a testament to the importance of keeping an open mind and daring to explore new horizons. However, sometimes, the grass isn’t always greener on the other side. In my case, I found that C# was the perfect blend of power and familiarity that I had been seeking all along.
As you navigate the tumultuous seas of programming languages, remember to consider your project’s specific needs, performance requirements, and personal preferences. Each language has its quirks and charms, and the right fit will depend on your unique circumstances. In the end, it’s about finding the language that makes your heart sing and your code soar.