TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам. Вопрос в качестве оптимизации по сути, ничего врожденного.
Здравствуйте, vsb, Вы писали:
vsb>TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам. Вопрос в качестве оптимизации по сути, ничего врожденного.
Интересно, но корректность более чем сомнительна, так как брался совершенно разный код для C++ "LLVM и Clang" для раста "rustc". Наличие не только clang но и llvm сильно уменьшает достоверность.
vsb>Интересный сайт: https://arewestackefficientyet.com/
vsb>TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам. Вопрос в качестве оптимизации по сути, ничего врожденного.
Т.к. руст компилируется через LLVM, виноват LLVM.
/thread
Здравствуйте, σ, Вы писали:
vsb>>TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам. Вопрос в качестве оптимизации по сути, ничего врожденного.
σ>Т.к. руст компилируется через LLVM, виноват LLVM. σ>/thread
Здравствуйте, vsb, Вы писали:
vsb>Интересный сайт: https://arewestackefficientyet.com/
vsb>TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам. Вопрос в качестве оптимизации по сути, ничего врожденного.
Чтобы не копаться в куче кода можно привести простой пример на плюсах и расте с пояснением что именно происходит?
Или там просто средние по больнице замеры специальной версией LLVM какого-то кода на плюсах и какого-то кода на расте?
vsb>TLDR у Rust-а есть проблема в избыточном насиловании стека в типовых программах, он уступает C++ по некоторым метрикам.
Не читал но согласен, в Расте большинство объектов by value. Одно спасает — std::move при передачи в/из функции там по умолчанию (кстате moving любого объекта в Расте (из тех что не Pin<>) помоему это всегда memcpy). В правильно написанной С++ программе за этим тоже нужно следить, чтобы толстые объекты не копировались.
Если нужна куча, в Расте нужно писать Box<>. Т.е. в оптимизированной Rust программе программист должен следить за этим сам и навставлять где нужно.
Т.е. грамотно написанная программа и в С++ и в Расте требует некоторых интеллектуальных усилий, которые потом должны привести к сравнимым производительностям.
Здравствуйте, johny5, Вы писали:
J>Не читал но согласен, в Расте большинство объектов by value. Одно спасает — std::move при передачи в/из функции там по умолчанию (кстате moving любого объекта в Расте (из тех что не Pin<>) помоему это всегда memcpy). В правильно написанной С++ программе за этим тоже нужно следить, чтобы толстые объекты не копировались.
не понятно, что значит by-value. Вроде полная аналогия с С++ Также по-умолчанию производится копирование. И только если не реализован трейт Copy производится перемещение. К тому же в Rust перемещение более толковое кмк — объект вовсе исключается из рассмотрения. По нему после перемещения никаких действий не производится. В C++, наоборот, все перемещённые объекты надо ещё "удалить" (вызвать деструкторы) что в большинстве случаев — просто нагрев процессора.
В общем пока проблемы не понял совсем
SP>не понятно, что значит by-value. Вроде полная аналогия с С++ Также по-умолчанию производится копирование. И только если не реализован трейт Copy производится перемещение.
Резонно.
Мне кажется это из за смены привычек. В С++ ссылки и указатели свободно передаются и возвращаются из функций. Работа со стековой памятью и кучей единообразна, хошь — аллоцируй, не хошь не аллоцируй. Не нужен какой то там специальный Box<> тип чтобы держать объект в куче.
В Расте, из-за верифицируемой политики единого владельца ресурсом, компилятор часто даёт по рукам если начинать фривольно раздавать ссылки на объекты. В результате часто объекты, вместо того чтобы быть переданными по ссылке будут moved в функцию (чтобы не возиться с lifetime и mutable borrows).
Я не знаю, возможно тут моя неопытность меня кусает. Но я признаю что в Расте мне гораааздо проще писать если у тебя все объекты идут по значению. Просто тасуешь данные с места на место.
Здравствуйте, sergii.p, Вы писали:
SP>не понятно, что значит by-value. Вроде полная аналогия с С++ Также по-умолчанию производится копирование.
В расте же по умолчание перемещение:
#[derive(Debug)]
struct Tst(i32);
fn main() {
let a = Tst(123);
let b = a;
dbg!(a); // ошибка a переместился.
}
SP>И только если не реализован трейт Copy производится перемещение.
Нужны трейты Clone и Copy и они не реализуются по умолчанию. То есть чтобы было копирование нужно специально озаботиться, за исключением примитивных встроенных типов.
В С++ и copy и move есть по умолчанию, но могут работать не так как хотелось бы.
SP>К тому же в Rust перемещение более толковое кмк — объект вовсе исключается из рассмотрения. По нему после перемещения никаких действий не производится. В C++, наоборот, все перемещённые объекты надо ещё "удалить" (вызвать деструкторы) что в большинстве случаев — просто нагрев процессора.
Это да. Но в сабже и для раста недостаток найден, если многие функции принимают по значению, то будет такой же бестолковой нагрев из-за более частого копирования (перемещение в стеке сводится к копированию) стековой памяти.
Здравствуйте, FR, Вы писали:
FR>В расте же по умолчание перемещение:
больше вопрос терминологии, но наверное соглашусь.
FR>Это да. Но в сабже и для раста недостаток найден, если многие функции принимают по значению, то будет такой же бестолковой нагрев из-за более частого копирования (перемещение в стеке сводится к копированию) стековой памяти.
а тут не понял. В чём отличие от С++? Если в С++ принимать по значению, также будет копирование на стеке. Из названия темы я так понял, существует идентичный код на Rust и С++ и в первом производится лишнее стековое копирование. Вот и хотелось бы взглянуть на этот код.
Здравствуйте, sergii.p, Вы писали:
FR>>Это да. Но в сабже и для раста недостаток найден, если многие функции принимают по значению, то будет такой же бестолковой нагрев из-за более частого копирования (перемещение в стеке сводится к копированию) стековой памяти.
SP>а тут не понял. В чём отличие от С++? Если в С++ принимать по значению, также будет копирование на стеке. Из названия темы я так понял, существует идентичный код на Rust и С++ и в первом производится лишнее стековое копирование. Вот и хотелось бы взглянуть на этот код.
В том, как уже выше обсуждали, что в расте как раз удобнее получить по значению, чтобы не возится с ссылками и лайфтаймами.
А так разницы с C++ нет, только вопрос предпочитаемого стиля.
Здравствуйте, ArtDenis, Вы писали:
AD>Чтобы не копаться в куче кода можно привести простой пример на плюсах и расте с пояснением что именно происходит?
AD>Или там просто средние по больнице замеры специальной версией LLVM какого-то кода на плюсах и какого-то кода на расте?
Там идёт сравнение компиляции непосредственно самого llvm (проект на C++) и rustc (проект на Rust). Статистика считается по первым 20 миллионам выполненных команд машинного кода.
Здравствуйте, ArtDenis, Вы писали:
AD>Или там просто средние по больнице замеры специальной версией LLVM какого-то кода на плюсах и какого-то кода на расте?
Пожалуйста:
Перед тем как положить объект в куче, Rust обязан сначала создать его на стеке, а потом скопировать в кучу.
Здравствуйте, _NN_, Вы писали:
_NN>Пожалуйста: _NN>Перед тем как положить объект в куче, Rust обязан сначала создать его на стеке, а потом скопировать в кучу.
В релизной сборке stack overflow не будет, так как все соптимизируется.
Тут проблема в том, что в отладочной без оптимизаций все делается тупо с созданием на стеке так как Box::new по сути самая обычная функция, а тут все-таки уже нужно ключевое слово, которое (box) даже есть в нестабильных сборках компилятора, но которое почему-то стабилизировать не хотят.
Но на замеры именно в сабже это багофича повлиять не должна, так-как прекрасно оптимизируется (надеюсь тестировали не отладочную сборку).
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, _NN_, Вы писали:
_NN>>Пожалуйста: _NN>>Перед тем как положить объект в куче, Rust обязан сначала создать его на стеке, а потом скопировать в кучу.
FR>В релизной сборке stack overflow не будет, так как все соптимизируется. FR>Тут проблема в том, что в отладочной без оптимизаций все делается тупо с созданием на стеке так как Box::new по сути самая обычная функция, а тут все-таки уже нужно ключевое слово, которое (box) даже есть в нестабильных сборках компилятора, но которое почему-то стабилизировать не хотят.
Это был просто пример кода где Rust ест стек, а C++ нет.
Я не спорю, что есть оптимизация, которую компилятор проводит.
Получается, что есть вероятность где невозможно будет применить отладочную сборку из-за этого эфекта, например при сборке модуля ядра.
FR>Но на замеры именно в сабже это багофича повлиять не должна, так-как прекрасно оптимизируется (надеюсь тестировали не отладочную сборку).
Это уже вопросы к замерам, чем там меряются