Что быстрее rust или c

от admin

rust vs c performance

I wanted to learn a bit about rust tasks, so I did a monte carlo computation of PI. Now my puzzle is why the single-threaded C version is 4 times faster than the 4-way threaded Rust version. Clearly I am doing something wrong, or my mental performance model is way off.

Here’s the C version:

The Rust version was not a line-by-line port:

Build and time the C version:

Build and time the Rust version:

qed's user avatar

2 Answers 2

The bottleneck, as Dogbert observed, was the random number generator. Here’s one that is fast and seeded differently on each thread

Meaningful benchmarks are a tricky thing, because you have all kinds of optimization options, etc. Also, the structure of the code can have a huge impact.

Comparing C and Rust is a little like comparing apples and oranges. We typically use compute-intensive algorithms like the one you dispicit above, but the real world can throw you a curve.

Having said that, in general, Rust can and does approach the peformance of C and C++, and most likey can do better on concurrency tasks in general.

Take a look at the benchmarks here:

I chose the Rust vs. C Clang benchmark comparasion, because both rely on the underlying LLVM.

enter image description here

On the other hand, a comparasion with C gcc yields different results:

enter image description here

And guess what? Rust still comes out ahead!

I entreat you to explore the Benchmark Game site in more detail. There are some cases where C will edge out Rust in some instances.

In general, when you are creating a real-world solution, you want to do performance benchmarks for your specific cases. Always do this, because you will often be surprised by the results. Never assume.

I think that too many times, benchmarks are used to forward the «my language is better than your langage» style of rwars. But as one who have used over 20 computer languages throughout his longish career, I always say that it is a matter of the best tool for the job.

C++ быстрее и безопаснее Rust, Yandex сделала замеры

Спойлер: C++ не быстрее и не медленнее и вообще смысл не в этом. Эта статья является продолжением славных традиций развенчания мифов крупных российских компаний о языке Rust. Предыдущая была «Go быстрее Rust, Mail.Ru Group сделала замеры».

Недавно я пытался заманить коллегу, сишника из соседнего отдела, на Тёмную сторону Rust. Но мой разговор с коллегой не задался. Потому что, цитата:

Антон Полухин является представителем России в ISO на международных заседаниях рабочей группы по стандартизации C++, автором нескольких принятых предложений к стандарту языка C++. Антон действительно крутой и авторитетный человек в вопросах по C++. Но доклад содержит несколько серьёзных фактических ошибок в отношении Rust. Давайте их разберём.

Речь идет об этом докладе с 13:00 по 22:35.

Оглавление

Миф №1. Арифметика в Rust ничуть не безопасней C++.

Для примера сравнения ассемблерного выхлопа Антон взял функцию возведения в квадрат(link:godbolt):

В самом деле, ассемблерный листинг арифметического умножения в обоих случаях выглядит одинаковым, но это только до поры до времени. Дело в том, что с точки зрения семантики языков, код делает разные вещи. Этот код определяет функции возведения числа в квадрат, но в случае Rust область определения [-2147483648, 2147483647], а в случае C++ это [-46340, 46340]. Как такое может быть? Магия?

Магические константы -46340 и 46340 — это максимальные по модулю аргументы, квадрат которых умещается в std::int32_t . Все что выше будет давать неопределенное поведение из-за signed overflow. Если не верите мне, послушайте PVS-Studio. И если вы достаточно удачливы, чтобы работать в командах, которые настроили себе CI с проверкой кода на определенное поведение, вы получите такое сообщение:

В Rust такая ситуация с неопределенным поведением в арифметике невозможна в принципе.

Давайте послушаем, что об этом думает Антон (13:58):

Я бы почитал, какие оптимизации не умеет Rust, особенно с учётом того, что в основе Rust лежит LLVM — тот же самый бэкенд, что и у Clang. Соответственно, Rust «бесплатно» получил и разделяет с C++ большую часть независящих от языка трансформаций кода и оптимизаций. И хотя в представленном примере мы и получили одинаковый ассемблер, на самом деле, это случайность. Хитрые оптимизации и наличие неопределённого поведения при переполнении знакового в языке C++ могут приводить к веселью и порой порождают такие статьи. Рассмотрим эту статью подробнее.

Дан код функции, вычисляющей полиномиальный хеш от строки с переполнением int’a:

Как подсказывает PVS-Studio, неопределенное поведение действительно не определено. Если посчитать 27752 в 3 степени, можно понять, почему хэш от двух букв считается нормально, а от трех уже с какими-то странными результатами.

Аналогичный код на Rust будет вести себя корректно(link:playground):

Выполнение этого кода отличается в Debug и Release по понятным причинам, а для унификации поведения можно воспользоваться семейством функций: wrapping*, saturating*, overflowing* и checked*.

Как видите, документированное поведение и отсутствие неопределённого поведения при переполнении знакового действительно делают жизнь легче.

Вычисление квадрата числа — это отличный пример того, как можно выстрелить себе в ногу с помощью C++ в трех строчках кода. Зато быстро и с оптимизациями. Если от обращения к неинициализированной памяти ещё можно откреститься вдумчивым взглядом, то проблема с арифметикой в том, что беда может прийти совершенно внезапно и на «голом» арифметическом коде, где ломаться на первый взгляд нечему.

Миф №2. Плюсы Rust только в анализе времени жизни объектов.

В качестве примера приводится следующий код(link:godbolt):

Здесь мы наблюдаем бесконечную рекурсию. Опять-таки код компилируется в одинаковый ассемблерный выхлоп, то есть NOP для функции bar как в C++, так и в Rust. Но это баг LLVM.

Если вывести LLVM IR кода с бесконечной рекурсией, то мы увидим(link:godbolt):

code
asm
IR

ret i32 undef — и есть ошибка, сгенерированная LLVM.

В самом LLVM бага живет с 2006 года. И это важный вопрос, ведь необходимо иметь возможность пометить бесконечные цикл или рекурсию так, чтобы LLVM не мог оптимизировать это в ноль. К счастью, есть прогресс. В LLVM 6 добавили интринсик llvm.sideeffect, а в 2019 году в rustc был добавлен флаг -Z insert-sideeffect , который добавляет llvm.sideeffect в бесконечные циклы и рекурсии. И бесконечная рекурсия становится действительно бесконечной(link:godbolt). Надеюсь, что в скором времени этот флаг перейдет и в stable rustc по умолчанию.

В C++ бесконечная рекурсия и цикл без побочных эффектов считаются неопределённым поведением, так что от этой баги LLVM страдают только Rust и C.

Итак, после того, как мы разобрались с ошибкой LLVM, давайте перейдем к главному заявлению: «его безопасность заключается только в анализе времени жизни объектов». Это заявление ложно, так как безопасное подмножество Rust защищает от ошибок, связанных с многопоточностью, гонками данных и выстрелами по памяти.

Миф №3. Вызовы функций в Rust бездумно трогают память.

Вывод ассемблера для Rust длинный, но мы разберемся в причинах такой разницы. В этом примере Антон использует флаги -ftrapv для C++ и -C overflow-checks=on для Rust, чтобы включить проверку на переполнение знаковых. При переполнении C++ прыгает на инструкцию ud2 , которая приводит к «Illegal instruction (core dumped)», а Rust прыгает на вызов функции core::panicking::panic , подготовка к которой занимает половину ассемблерного кода. В случае переполнения core::panicking::panic дает нам красивое объяснение падения:

Так откуда взялись эти «лишние» инструкции, которые трогают память? Соглашение о вызове функции x86-64 требует, чтобы стек был выравнен до 16 байт, инструкция call кладёт 8-байтовый адрес возврата на стек, что ломает выравнивание. Чтобы это исправить, компиляторы кладут всякие инструкции типа push rax. И так делает не только Rust, но и C++(link:godbolt):

И C++, и Rust сгенерировали одинаковый выхлоп ассемблера, оба добавили push rbx для выравнивания стека. Q.E.D.

Самое интересное заключается в том, что именно C++ нуждается в деоптимизации кода путём добавления аргумента -ftrapv , чтобы ловить неопределенное поведение при переполнении знаковых. Выше я уже показал, что Rust будет вести себя корректно даже без флага -C overflow-checks=on , так что можете сравнить сами(link:godbolt) стоимость корректного кода на C++, либо почитайте статью на эту тему. К тому же -ftrapv в gcc сломан с 2008 года.

Миф №4. Rust медленнее C++.

На протяжении всего доклада Антон выбирает примеры, написанные на Rust’е, которые компилируются в чуть больший ассемблер. Не только примеры выше, которые «трогают» память, но и пример на 17:30(link:godbolt):

Складывается впечатление, что весь этот анализ ассемблерного выхлопа был нужен лишь для того, чтобы сказать, что больше асма → медленнее язык.

В 2019 на конференции CppCon был интересный доклад There Are No Zero-cost Abstractions от Chandler Carruth. Вот он там на 17:30 сильно страдает из-за того, что std::unique_ptr стоит дороже сырых указателей (link:godbolt). И чтобы хоть как-то приблизиться к ассемблерному выхлопу кода на сырых указателях ему приходится добавлять noexcept , rvalue ссылки, и использовать std::move . А на Rust всё будет работать без дополнительных усилий. Давайте сравним два кода и ассемблер. В примере на Rust мне пришлось дополнительно извратиться с extern «Rust» и unsafe , чтобы компилятор не заинлайнил вызовы (link:godbolt):

При меньших трудозатратах Rust генерирует меньше ассемблера. И не нужны подсказки компилятору в виде noexcept , rvalue ссылок и std::move . В сравнениях языков нужны нормальные бенчмарки. Нельзя вытащить понравившийся пример, и утвержать, что один язык медленнее другого.

В декабре 2019 Rust превосходил по производительности C++ согласно результатам Benchmarks Game. С тех пор C++ немного укрепил свои позиции. Но на таких синтетических бенчмарках языки будут раз за разом обходить друг друга. Я бы не отказался посмотреть нормальные бенчмарки.

Миф №5. C → С++ — noop, C → Rust — PAIN.

Вот тут Антон смешал в одну кучу объявление сишных функций и их последующее использование.

Действительно, объявление сишных функций в Rust требует либо их ручного объявления, либо автоматической генерации, потому что это разные языки программирования. Подробнее можно прочитать в моей статье про бота для Starcraft, либо посмотреть на пример генерации этих оберток.

К счастью, у языка Rust есть пакетный менеджер cargo, который позволяет один раз сгенерировать объявления и поделиться ими со всем миром. Как вы понимаете, люди делятся не только сырыми объявлениями, но и безопасными и идиоматичными обёртками. На 2020 год в реестре пакетов crates.io находится около 40 000 крейтов.

Ну а само использование сишной библиотеки занимает буквально одну строчку в вашем конфиге:

Всю работу по компиляции и линковке с учетом версий зависимостей cargo выполнит автоматически. Пример с flate2 примечателен тем, что в начале своего существования этот крейт использовал сишную библиотеку miniz, написанную на C, но со временем сообщество переписало сишный код на Rust. И flate2 стал работать быстрее.

Миф №6. unsafe отключает все проверки Rust.

Данный пункт является продолжением темы про интеграцию сишных библиотек в Rust’овый код.

Увы, мнение об отключении всех проверок в unsafe — это типичное заблуждение, потому что в документации к языку Rust сказано, что unsafe позволяет:

  1. Разыменовывать сырой указатель;
  2. Вызывать и объявлять unsafe функции;
  3. Читать или измененять статическую изменяемую переменную;
  4. Реализовывать и объявлять unsafe типаж;
  5. Получать доступ к полям union .

Ни о каких отключениях всех проверок Rust здесь и речи не идет. Если у вас ошибка с lifetime-ами, то просто добавление unsafe не поможет коду скомпилироваться. Внутри этого блока компилятор продолжает проверять код на соответствие системы типов, отслеживать время жизни переменных, корректность на потокобезопасность и многое-многое другое. Подробнее можно прочитать в статье You can’t «turn off the borrow checker» in Rust.

К unsafe не стоит относиться как «я делаю, что хочу». Это указание компилятору, что вы берете на себя ответственность за вполне конкретный набор инвариантов, которые компилятор самостоятельно проверить не может. Например, разыменование сырого указателя. Это мы с вами знаем, что сишный malloc возвращает NULL или указатель на аллоцированный кусок неинициализированной памяти, а компилятор Rust об этой семантике ничего не знает. Поэтому для работы с сырым указателем, который вернул, к примеру, malloc , вы должны сказать компилятору: «я знаю, что делаю; я проверил, там не нулл, память правильно выравнена для этого типа данных». Вы берете на себя ответственность за этот указатель в блоке unsafe .

Миф №7. Rust не поможет с сишными библиотеками.

По статистике Microsoft, 70% уязвимостей связаны с нарушениями безопасности доступа к памяти и с другими классами ошибок, которые Rust предотвращает ещё на этапе компиляции. Это ошибки, которые физически невозможно совершить в безопасном подмножестве Rust.

С другой стороны, существует и unsafe подмножество Rust, которое позволяет разыменовывать сырые указатели, вызывать сишные функции… и прочие небезопасные вещи, которые могут сломать вашу программу, если ими пользоваться неправильно. В общем, именно то, что делает Rust системным языком программирования.

И, казалось бы, можно поймать себя на мысли, что если в Rust и в C++ надо следить за корректностью вызовов сишных функций, то Rust ничуть не выигрывает. Но особенностью Rust является возможность разграничения кода на безопасный и потенциально опасный с последующей инкапсуляцией последнего. А если на текущем уровне гарантировать корректность семантики не удаётся, то unsafe надо делегировать вызывающему коду.

На практике делегация unsafe наверх выглядит вот так:

slice::get_unchecked — это стандартная unsafe функция, которая получает элемент по индексу без проверок индекса на выход за границы. Так как в нашей функции get_elem_by_index мы тоже не проверяем индекс, а передаем его как есть, то наша функция потенциально опасна. И любое обращение к такой функции требует явного указания unsafe (link:playground):

Если вы передадите индекс, выходящий за границы, то получите обращение к неинициализированной области памяти. И сделать вы это сможете только в unsafe .

Тем не менее, с помощью этой unsafe функции мы можем построить безопасную версию(link:playground):

И эта безопасная версия никогда не выстрелит по памяти, какие бы аргументы вы туда не передали. Если что, я не призываю вас писать подобный код на Rust (есть функция slice::get ), я показываю, как можно перейти из unsafe подмножества Rust в безопасное подмножество с сохранением гарантий безопасности. На месте нашей unchecked_get_elem_by_index могла быть аналогичная функция, написанная на C.

Благодаря межъязыковой LTO вызов сишной функции может быть абсолютно бесплатен:

C
Rust
asm

Я выложил проект с флагами компилятора на гитхаб. Результирующий выхлоп ассемблера аналогичен коду, написанному на чистом C(link:godbolt), но имеет гарантии кода, написанного на Rust.

Миф №8. Безопасность Rust не доказана.

В 2018 году доказали, что система типов Rust, механизмы заимствования, владения, времён жизни и многопоточности корректны. Так же было доказано, что если мы используем семантически правильный код из библиотек внутри unsafe и смешаем это с синтаксически правильным safe кодом, мы получим семантически правильный код, который не позволяет стрелять по памяти или делать гонки данных.

Из этого следует, что если вы подключаете и используете крейт(библиотеку), которая содержит unsafe, но предоставляет правильные безопасные обертки, то ваш код от этого не станет небезопасным.

В качестве практического применения своей модели авторы доказали корректность некоторых примитивов стандартной библиотеки, включая Mutex, RwLock, thread::spawn. А они используют сишные функции. Таким образом, в Rust невозможно случайно расшарить переменную между потоков без примитивов синхронизации; а, используя Mutex из стандартной библиотеки, доступ к переменной всегда будет корректен, несмотря на то, что их реализация опирается на сишные функции. Круто? Круто.

Заключение

Объективно обсуждать относительные преимущества того или иного языка сложно, особенно если вам сильно нравится один язык и не нравится другой. Весьма часто новый апологет очередного «новоявленного языка-убийцы C++» делает громкие заявления, не разобравшись толком с C++, за что ожидаемо получает по рукам.

Однако от признанных экспертов я ожидаю взвешенного освещения ситуации, которое, как минимум, не содержит грубых фактических ошибок.

Большое спасибо Дмитрию Кашицыну и Алексею Кладову за ревью статьи.

в rustc был добавлен. И бесконечная рекурсия становится действительно бесконечной(link:godbolt). Надеюсь, что в скором времени этот флаг перейдет и в stable rustc по умолчанию.

Си — это сэнсэй черепашек-ниндзя

Си — это императивный язык программирования общего назначения и один из старейших (создаваться он начал в 1969 году). Его отцом-основателем является Деннис Ритчи. В 1989 году Американский национальный институт стандартов и Международная организация по стандартизации разработали новые консенсусные стандарты для Си. Будучи простым, низкоуровневым языком программирования, который работает на различных платформах, он и сейчас остаётся универсальным и по-прежнему широко используется.

Бытовые приборы, такие как микроволновые печи, стиральные машины и цифровые фотокамеры, с каждым днём становятся всё более совершенными. Об этом свидетельствует наличие в них микропроцессора, операционной системы и программного обеспечения. Эти программы должны работать эффективно, задействуя при этом небольшой объём памяти. Неудивительно, что они пишутся на Си.

Основные части популярных операционных систем, таких как Windows, UNIX и Linux, написаны на Си. Ведь даже сегодня по производительности языку Си нет равных, хотя это не означает, что так будет всегда. Кроме того, если требуется расширить операционную систему для работы с новыми устройствами, нужны программы-драйверы устройств. И эти программы тоже пишутся исключительно на Си.

Язык Си оказывает огромное влияние на сферу информационных технологий и по-прежнему играет здесь жизненно важную роль.

Rust — потенциальный конкурент во всех областях

Rust — это мультипарадигмальный язык программирования с упором на производительность и безопасность, и особенно на безопасный параллелизм. С точки зрения синтаксиса Rust аналогичен языку C++. А что касается безопасности при работе с памятью, Rust обходится без сборки мусора: вместо неё здесь система проверки заимствования.

Разработка Rust была начата Грейдоном Хором в сообществе Mozilla Research.

В Rust основной акцент сделан на:

Безопасность при работе с памятью

Основное преимущество Rust: он гарантирует, что во время компиляции приложение будет избавлено от разыменования нулевых или висячих указателей. К тому же, Rust затрудняет возникновение утечки памяти.

Производительность

В языке Rust сборщик мусора не предусмотрен. Rust узнаёт о том, когда переменная выходит из области видимости или когда её время жизни заканчивается, во время компиляции. После чего вводит соответствующие команды ассемблера/LLVM для освобождения памяти. Это повышает производительность во время выполнения.

Многопоточность

Потоки в Rust автоматически «изолируются» друг от друга благодаря такому понятию, как владение. Запись происходит, только когда поток имеет изменяемый доступ — либо владея данными, либо имея изменяемое заимствование. В обоих случаях поток гарантированно будет единственным, имеющим доступ в любой момент времени.

Поддержка Web Assembly

Web Assembly помогает выполнять алгоритмы с большим объёмом вычислений в браузере, на встроенных устройствах или где-либо ещё. Он запускается со скоростью машинного кода. Rust компилируется в Web Assembly с целью быстрого и надежного выполнения.

Сравнение скорости Си и Rust

Методология

Для сравнения скорости этих двух языков применятся такой подход: пишутся самые популярные алгоритмы сортировки, которые запускаются для различных диапазонов элементов. При этом оценивается, у какого языка сортировка элементов заняла больше времени.

Используются следующие алгоритмы сортировки:

Колонки со сложностью в худшем случае (Worst Case) позволяют примерно определить, какой метод сортировки будет выполняться хуже всех.

Для сортировки пузырьком сложность в худшем случае составит O(N²). Это будет худшее выполнение по сравнению с другими методами сортировки. Будет сгенерирована итоговая матрица, которая поможет определить временную сложность в худшем случае. Для этого надо сравнить время, необходимое для сортировки элементов.

Таким образом пишутся все пять алгоритмов на Си и на Rust. Для цели ввода используется массив целых чисел, заполняемый случайными числами с помощью функции-генератора случайных чисел rand() на Си и rand::Rng на Rust. Этот массив задаётся в качестве входных данных для алгоритмов сортировки, а выходные данные записываются в матрицу. Дальше тестируется производительность алгоритмов для трёх диапазонов: 1000, 10 000 и 100 000 элементов.

Такой набор значений запускается в течение 100 итераций, а для генерации матрицы выходных данных выполняется усреднение.

Читать:
Debian как сменить раскладку клавиатуры

Конфигурация для сравнения производительности

Конфигурация системы, в которой был запущен и выполнен подсчёт значений:

ОС: macOS Catalina.

Машина: MacBook Pro (16 дюймов, 2019 года).

Процессор: 2,3 ГГц 8-ядерный Intel Core i9.

Память: 16 Гб 2667 МГц DDR4.

Версия clang 12.0.0 (флаг оптимизации -O3).

rustc 1.45.2 (флаг оптимизации — release).

Статистика производительности

Ниже приводятся сгенерированные матрицы выходных данных:

Матрица выходных данных показывает примерно равные результаты. Для каждого метода сортировки и каждого диапазона входных массивов в каких-то случаях Rust работает лучше, а в каких-то случаях лучше работает Си. В нижних диапазонах (1000 элементов), за исключением сортировки вставками, Rust работает лучше. В диапазоне 10 000 элементов Cи работает лучше во всех методах сортировки.

Гистограммы тоже показывают, что результаты почти одинаковы во всех случаях.

Можете попробовать, что получится на вашем компьютере.

Вот ссылка на Github проекта.

Заключение

Сложно сказать, какой язык быстрее, потому что это зависит от конкретного случая. Но Rust может составить конкуренцию в скорости языку Cи: он быстрее, чем многие другие популярные языки, такие как Java и Python. Помимо скорости, в Rust акцент сделан на таких функциональных возможностях, как безопасная работа с памятью и параллелизм. А кроме того, у него открытый исходный код, так что Rust используют для создания самых разнообразных программных продуктов, например игровых движков, операционных систем, файловых систем, браузерных компонентов, а также машин для моделирования виртуальной реальности. Так что в ближайшее время Rust наверняка будет уже везде.

When Speed Matters: Rust Vs C++ Performance

C++ is a venerable programming language with over thirty-six years, can the newcomer Rust match its versatility and speed?

By Michael Warren

Business Development Executive Michael Warren drives BairesDev's sales further by nurturing existing client relationships and acquiring new customers.

Featured image

C++ is a venerable programming language with more than 36 years in its long history. It is a staple in the programming scene, and most individuals, even those who don’t work or dabble in the technology space, have probably heard of it at one point or another.

So, can the newcomer Rust, released in the early 2010s, match the versatility, speed, and other qualities of C++, its much older counterpart? In contrast to C++, Rust is not nearly as well known. But, of course, that could very well change.

Today, there are many Rust developers who swear by the language, just as there are many programmers who swear by C++. And the two languages are often compared, thanks to certain overlapping features that the languages both possess. Here, we will assess the key features Rust offers and C++ offers and present a clearer picture of Rust vs C++ overall, particularly in terms of the performance they each can provide.

C++ in a Nutshell

First, let’s take a look at C++ and how and why developers use it today. And no discussion of C++ is complete without mentioning C and the C family in general.

C and its object-oriented cousin C++ are 2 of the most well-known and venerable programming languages on the market. When speed is the main factor in software development or when resource management is an issue, these 2 languages are still the default go-to, even decades after their creation. In fact, C dates back even further than C++, its offshoot, to 1978.

Every few years or so, an individual or group of developers will try to build and release what has come to be known as “C killers,” programming languages designed from the ground up to provide the same benefits as the C family, while attempting to reckon with some of the most well-known issues associated with the C family at the same time. These would-be C killers are generally met with mixed success.

Just as an example, we have Java and C#, both of which are amazing and have built great resources and communities. And if you take into account the mobile market, Java has probably become the most used programming language in the world.

Rust in a Nutshell

Rust, as we have noted, is a much newer language. It was introduced as a powerful, all-purpose, very fast programming language that is focused both on safety and performance. Rust is an example of one of the latest languages that have been touted as a “C-killer.”

Unfortunately for those eager to see the C family gone forever, it doesn’t seem like Rust will necessarily be the chosen one, although it has still emerged as a great and useful language in its own right.

Moreover, Rust does a lot of things right, and it is an amazing alternative for people who are looking for powerful programming languages with modern sensibilities. We will take a look at some of its capabilities and qualities below.

A Quick Note

Before we go any further, a word of caution: here, in evaluating these two languages, we are not just thinking about speed. Objectively comparing the speed of languages is difficult, as there are many variables involved, from how each language handles certain tasks to the experience and inventiveness of the developer who is writing the code. However, we can use some metrics to compare speed and performance in an unbiased manner. We will illuminate this a bit further below.

A quick example: Python is considered one of the slowest languages on the market, but an advanced Python developer can make faster programs than a person who is working on C for the first time.

This is something that is important to keep in mind while you are reviewing the section on benchmarking information and the table that we have provided below. Unbiased benchmarking metrics, while difficult to evaluate when you are comparing Rust code and C++ code, give a clearer picture of overall speed and performance.

Now that we got that out of the way, let’s dive into Rust’s features and compare them to C++ to determine which one is the better language for your project.

Rust Vs C++ Performance Benchmarks

While it is quite difficult to benchmark the Rust language and C++ for performance, it is possible, and it starts with looking at the source code. Here is an excellent resource for understanding the C++ and Rust comparison in terms of performance benchmarks further, and you can take a closer look at the table below to better understand them.

In a nutshell, while Rust code and C++ code are comparable in terms of overall speed and performance, Rust often outranks C++ in multiple instances when we consider unbiased benchmarking.

High-Level and Low-Level

Both C++ and Rust are considered “low-level” languages, or at least lower-level than other popular high-level languages like Javascript or the aforementioned Python. But what does that mean exactly?

Computers follow arithmetic and logical instructions to accomplish whatever task they have been programmed to accomplish. For example, to display the text you are reading right now, your CPU is sending it a signal via electrical currents giving instructions on the color of each pixel, creating the image you are seeing.

A computer doesn’t know what the letter A is, but by following mathematical instructions it can draw it on a screen. Those instructions are called machine code. At the other end of the spectrum, you have natural language, the way we humans speak, read, write, and otherwise communicate with one another.

A programming language basically serves as an intermediary between machine code and human language. It is the way in which we communicate with machines, and therefore, it can be more or less difficult to translate and comprehend. Developers, essentially, are giving machines sets of instructions on how to act and behave through programming languages — but we don’t have the same vocabulary, and that is why these languages are necessary.

To summarize, then: when someone says that a language is low level, what they are saying is that it is closer to machine code than to the way we speak and communicate.

The higher level a language is, the more it looks like human language, but at the same time the more processing power it takes to turn that program into machine code. That is why languages like Python are very readable but are also slow and unoptimized.

Suffice it to say, Rust and C++ fill a very similar need, that is, a code that it is readable but that can run fast enough for heavy-lifting software like operating systems or drivers.

Rust: Security First

Rust was created in 2010 by the Mozilla Foundation. It started as a side project of one of the developers that quickly grew as the foundation realized the potential it had for developing their software. THis was an assessment that proved to be true since in its short lifespan, Rust has become one of the most loved languages by developers.

One of the biggest reasons why that happened is that Rust has 2 killer features that make it stand out among its peers: safe concurrency and memory safety.

Concurrency is the ability of a program or software to execute several of its parts out of order and/or in a partial order, which in turn means that you can have parallel execution of concurrent processes.

Let’s say that you have a program with 10 instructions. Instead of having to run each one at a time, you can have several processors running several instructions concurrently reaching the same result in less time.

While other languages leave the threading up to the developer, manual threading requires a level of knowledge that not every developer has. Rust checks for Ownership statically to make sure that a developer isn’t inadvertently creating a bug by having the program access information when it shouldn’t.

The same goes for memory management. Typically, memory is either handled by the developer directly or left to what is known as garbage collecting, that is, letting the computer figure out what information is no longer being used, and freeing up the memory.

While garbage collecting is amazing, it can be pretty slow and expert developers often find it constraining. Instead of GC, Rust avoids null pointers, dangling pointers, or data races all together with safe code. Fewer bugs all around imply faster development times.

To put it simply, Rust is like driving a racing car with a safety belt: it’s a lifesaver for someone who is just learning how to drive and it’s a good safety measure for an expert driver, even if they are unlikely to crash. That’s what memory safety is all about.

C++: The Tinkerer’s Dream

C++ is 36 years old, and in that time it has garnered thousands upon thousands of libraries as well as a knowledge base that it’s simply baffling. No matter how crazy or out there your idea is, odds are that someone has already done something like it in C++.

Additionally, C++ is a tinkerer’s dream come true. Few languages give as much freedom to the developer as the C family. Like a finely-tuned Stradivarius, it’s a tool that in the hands of a maestro can truly create a work of art.

Do you have Windows OS? You are using C++. Do you like YouTube? That’s the language that handles the video processing. Ever played a game made in the Unreal engine? That’s running on C++ as well. There isn’t a better poster child for the concept of multipurpose language.

As a company looking for developers, the talent pool for C++ programmers is a thousand times bigger than Rust, at least for now. Who knows what the distribution will look like in 10 years?

More libraries mean less development time as there are more tools out there to be freely used by developers and, all in all, there is plenty of evidence that points out that C++ is still the fastest object-oriented language available.

C++ vs. Rust – Ease of Use

There is no question that Rust is far easier to use than C++. It also has a significantly lower learning curve, along with extensive community support, libraries, tools, documentation, and additional resources that newcomers to Rust can take advantage of when they are first learning how to use the language.

In contrast to the Rust language, C++ is widely considered to be a difficult and complex language to tackle, with only very experienced developers turning to the language on a frequent basis. For one, C++ includes a multitude of diverse dialects that developers are required to learn before they can fully utilize C++.

Bear in mind, too, that Rust frequently ranks as one of the most-loved languages in the world in Stack Overflow’s annual Developer Survey, while C++ generally sits squarely on the most-dreaded list. This should hardly come as a surprise to developers, many of whom have turned away from C++ in recent years, often in favor of Rust as a better alternative.

The Future Of Rust & C++

As you can see, there are many pros and cons to using both Rust and C++. And you may be wondering: what does the future of these two somewhat similar languages look like?

The fact is, of course, none of us has that answer. C++ outranks Rust in terms of longevity, but, as we know so well, it is not so difficult for languages to wain in popularity and even be retired altogether. And yet C++ continues to have extensive community support.

Meanwhile, Rust comes with a lot of advantages, such as ease of use and a low learning curve. That means that it is more likely to attract a greater number of programmers, particularly those who are beginners in the space, in the coming years. It also shines in the case of memory footprint and has fewer memory safety issues. That said, it does have a much smaller community, perhaps due to its young age. And, of course, that could very well change in the future.

So, can we predict what will come of Rust and C++? It seems unlikely that either will disappear in the near future. C++, along with its family of C languages, remains a staple in the programming space and is even the first choice developers turn to when working on certain types of projects.

And while Rust is a newer language, it is only gaining popularity. In 2022, it was crowned the most-loved language in Stack Overflow’s Developer Survey, marking its seventh year in a row in this position. So, it is also clear that Rust is on an upward climb.

In short, we can expect long, illustrious paths for both of these important languages.

Which One to Pick?

This comparison is quite a toss-up, and it would be a disservice to point at one language and declare it a winner. Fortunately, there doesn’t have to be one: Rust and C++ are very similar and integration between them is possible. Both languages have proven themselves invaluable assets in software development.

If your project requires speed then you can’t go wrong with either choice — it is simply a preference between the safety of Rust or the customizability of C++, along with other features that come with the two options.

What to Consider

That said, we have reviewed the qualities and limitations of both of these languages, and you can judge for yourself which one is the better choice for your project or projects. After all, as you have probably gleaned, developers apply Rust and C++ to different types of work and in different ways, although there is often some overlap in terms of the projects that are appropriate for the two.

So, when you think about the best choice between Rust vs C++, think about features like:

  • The experience and seniority of your developers or developer bases you can tap into
  • The importance of high performance code to your project
  • Memory safety and memory management
  • Community support and resources available
  • Your current stacks
  • The operating systems you want your program or system to run on
  • The necessary functions you need to perform
  • The types of and complexity of the projects you typically work on at your organization
  • Any other factors you deem important for you and your company

These, of course, are just a few of the many factors that will go into your decision. A lot depends on the unique product or project you are devising. Suffice it to say, there are some cases when both C++ and Rust will appear in a business’ stacks, particularly when they have a large, varied product catalog and arsenal.

Rust Vs C++ FAQ

Is C++ faster than Rust?

C++ is not necessarily faster than Rust. It is difficult to compare the two languages in terms of speed and performance directly. Generally speaking, Rust and C++ are comparable in terms of overall speed and performance, but when we take into account unbiased benchmarking, there are many instances in which Rust will perform even better than its counterpart.

Why is Rust slower than C++?

Many developers believe that Rust is slower than C++, but that is not necessarily true. At face value, it may seem like Rust is slower than C++, but that is only when you’re looking at the overall picture, not the unbiased benchmarking data that is essential to consider when directly comparing Rust to C++ in terms of performance.

In fact, while developers can sometimes write and execute C++ programs more quickly than they can Rust programs, in doing so, they are ignoring many of the fundamental errors in the language, which will likely lead to more extensive problems down the line.

Is Rust easier than C++ to learn?

Rust is widely considered easier to learn than C++. C++ is notoriously difficult, with experienced and senior developers turning to it for the most part. Meanwhile, Rust is thought to have a low learning curve. It is also easy to use and has a number of resources to help developers who are new to the language get started. That said, C++ does have a wide community of support available for assistance when need be.

Is Rust growing in popularity?

Rust is growing in popularity every year. In 2022, it marked its seventh year in a row as the most-loved language in Stack Overflow’s annual Developer Survey, with 87% of survey respondents saying that they were planning to continue using it. Meanwhile, it was tied with Python as the most-wanted technology in the same survey. So, it is fair to say that Rust is already popular and continuing an upward climb.

By Michael Warren

Business Development Executive Michael Warren is responsible for the development of BairesDev's growth through increased customer acquisition and overall sales. Michael helps drive sales forward by nurturing existing customer relationships and generating new ones through different channels.

Related Posts