LINUX.ORG.RU

Rust 1.24

 


3

9

Команда Rust рада сообщить о выпуске Rust 1.24.0. Rust — это системный язык программирования, нацеленный на безопасность, быстрое и параллельное исполнение программ.

Если у вас уже установлена предыдущая версия через rustup, для обновления просто выполните

$ rustup update stable

Для новой установки скачайте rustup и не забудьте прочитать примечания к выпуску 1.24.0 на GitHub.

Что нового в Rust 1.24.0?

rustfmt

Несколько лет мы ждали инструмент для автоматического приведения исходного кода на Rust в «стандартный вид». Встречайте предварительную версию rustfmt! Чтобы попробовать, просто выполните

$ rustup component add rustfmt-preview

Нужно отметить два важных момента: во-первых, вы должны использовать именно rustup component add, а не cargo install. Если вы ранее использовали rustfmt через cargo install, вам необходимо предварительно его удалить. Во-вторых, не забывайте о том, что rustfmt ещё не достиг версии 1.0. Некоторые детали пока в разработке, а баги в процессе исправления. Как только rustfmt достигнет версии 1.0, компонент rustfmt-preview будет объявлен устаревшим и заменён на rustfmt.

В ближайшее время мы планируем написать отдельный пост об этой стратегии выпусков. Для дополнительной информации смотрите страницу rustfmt на GitHub.

Пошаговая сборка

Ещё в сентябре 2016 года мы подробно писали об этом в нашем блоге. Идея пошаговой компиляции довольна проста: если поддерживается этот механизм, то пересобираться будет только тот код, который был изменён с момента предыдущей компиляции. Это намного быстрее, чем полностью собирать весь проект, даже если изменения исходного кода достаточно малы. Начиная с версии 1.24, пошаговая компиляция включена по умолчанию. Не забудьте о cargo check, если будете пытаться достигнуть минимально возможного времени сборки.

Важно отметить, что и работа над производительностью компилятора в целом, и над пошаговой сборкой в частности, будет продолжена. Кое-что доступно уже в этом выпуске 1.24.0 — значение codegen-units теперь 16 по умолчанию. Одно небольшое замечание об этом изменении: оно делает компиляцию быстрее, но исполняемый файл получается немного медленнее. Для максимальной скорости программы выставьте codegen-units в 1 в вашем Cargo.toml.

Другие изменения

Есть ещё одно изменение, о котором мы хотели бы поговорить: неопределённое поведение (undefined behavior). Как правило, Rust старается избегать неопределённого поведения, исключив его полностью из безопасного (safe) кода, и сведя к минимуму в небезопасном (unsafe) коде. Одним местом, где вы всё ещё могли получить неопределённое поведение, была ситуация, когда вызов panic! проходит через FFI.

extern "C" fn panic_in_ffi() {
        panic!("Test");
}

Это не может работать, поскольку точный механизм работы паник должен быть согласован с тем, как работает "C" ABI в этом примере, или любой другой ABI в других случаях.

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

Стабилизация библиотек

Если вы любитель функции str::find, которая используется для нахождения char в &str, вы будете рады узнать, что она стала быстрее в 10 раз! Этого удалось достигнуть использованием memchr. [u8]::contains теперь также его использует, хотя прирост скорости оказался более умеренным.

Несколько новых API были стабилизированы в этом выпуске:

Следующие функции теперь могут быть использованы в постоянных выражениях (constant expressions), например при инициализации static:

  • new функции для Cell, RefCell и UnsafeCell
  • new функции для различных целочисленных Atomic типов
  • {integer}::min_value и max_value
  • size_of и align_of для mem
  • ptr::null и null_mut

Смотрите примечания к выпуску для более подробной информации.

>>> Подробности



Проверено: jollheef ()
Ответ на: Вопрос растоманам от anonymous

Насколько я понимаю, тут статически компонуются всего лишь библиотеки ввода и вывода, но почему компилятор раста создаёт бинарник, который весит в 6 раз больше?

Потому, что бинарники таскают батарейки в себе. jemalloc, libbacktrace, отладочные символы... Всё это, правда, можно выкинуть, если очень нужно.

quantum-troll ★★★★★ ()
Ответ на: комментарий от AntonyRF

Пока я ковырял в носу, продвинутые ребята оказались не так уж и заняты. Меня тем временем мучает вопрос, в чём соль вопроса:

Вот как получить экземпляр типажа из ARC, чтобы можно было вызвать его метод?

если объект из Arc вытаскивается обычным разыменованием.

Virtuos86 ★★★★★ ()
Ответ на: комментарий от AntonyRF

Затык на 220 строке. Код: https://github.com/sinitcin/poll_engine

Если я правильно понял, то нужно:

        let parent = self.parent();
        let mut parent_borrowed = parent.borrow_mut();
        parent_borrowed.read();
Ну и тип парента сменить на Arc<RefCell<ILinkChannel>>.

По другому никак: описав у функции read self как мутабл, вы потребовали, чтоб раст гарантировал, что рид вызовется только в эксклюзивном режиме. Арк - это многопоточная хрень, никаких гарантий от состояния гонки нет. Соответственно, нужно запаковать в рефцелл и проверять правила займа динамически. Ну и да, читайте доку к refcell'у, этот код может запаниковать. Возможно, стоит поменять на мутекс какой.

khrundel ()
Последнее исправление: khrundel (всего исправлений: 1)
Ответ на: комментарий от khrundel

Возможно, стоит поменять на мутекс какой.

Не «возможно», а нужно. RefCell работает только в одном потоке. Если попробовать передать Arc<RefCell<T>> в другой поток, будет ошибка компиляции.

red75prim ()
Ответ на: комментарий от khrundel

Если я правильно понял, то нужно:

Ёшкин кот, ты просто красавчик!!!!! Я себе неделю мозг ломал, даже Cell использовал по аналогии с твоим примером, но не допёр заюзать RefCell итить колотить как всё сложилось хорошо =) Огромное спасибо)))

AntonyRF ()
Ответ на: комментарий от vblats

vblats ★ (17.02.2018 18:25:07) «Я рад что ты гуру питона, и рад что у питона есть свой синтаксис и парадигма, но я создал тему, ПОТОМУ ЧТО МЛЯТЬ НЕ ПРОГРАММИСТ, с целью спросить НА КАКОМ ЯЗЫКЕ ЛУЧШЕ ВСЕГО ПИСАТЬ GTK.»

duraki ★★ ()
Ответ на: комментарий от khrundel

В итоге получаем поиск по ключу (основная операция для хэштаблицы!) O(n), притом насилующий кэши

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

anonymous ()
Ответ на: комментарий от pftBest

А ты не забыл удалить отладочную информацию командой strip?

Ты о чём? Просмотрел

man rustc[/rust], там нет ключа типа [strip]--strip[/strip] Там наоборот написано, для того чтобы дебажная инфа вставлялась в бинарь надо доплнительно прописать ключик -g. Хотя, если честно, компиляция с ключиком -g даёт тот же размер бинарника.

Видимо размер бинарника 3.3 Мегабайта из-за того, что в rust 

println![/rust] -- это макрос. В Си же 
printf[/rust] -- это библиотека.

Кто-нибудь сравнивал размеры бинарников Си и Rust работающих как демоны скомпилированных без функций и макросов ввода-вывода?
anonymous ()
Ответ на: комментарий от anonymous

Я о том что берешь программу strip из пакета binutis и даешь ей бинарь:

$ cargo build --release
$ strip target/release/helloworld
$ ls -lh target/release/helloworld
-rwxr-xr-x 2 user user 440K Feb 19 11:48 target/release/helloworld

Еще можно динамически слинковаться со стандартной библиотекой:

$ RUSTFLAGS="-C prefer_dynamic" cargo build --release
$ ls -lh target/release/helloworld
-rwxr-xr-x 2 user user 15K Feb 19 11:43 target/release/helloworld

pftBest ★★★ ()
Последнее исправление: pftBest (всего исправлений: 1)
Ответ на: комментарий от pftBest

Спасибо, но это как-бы «внештатные рецепты» облегчения.

Должно быть честно. Только: исходник --> трансляция ---> связывание ---> бинарь. И всё!

Выше видел ссылку на английском языке. Честно говоря я не очень в этот язык вхож. Там вроде тоже описаны рецепты облегчения бинарей.

Вот только мой фундаментальный вопрос так и остался без ответа. Почему по-умолчанию хелоуворд бинарника весит 3,3 Мегабайта? Да, println! — это макрос, но ведь не до такой же степени надо разбухать. Я тут не для того чтобы тролить, но когда увидел размер бинари я просто офигел.

anonymous ()
Ответ на: комментарий от anonymous

Так он не три мегабайта весит, а 400 килобайт. Три мегабайта это отладочная информация стандартной библиотеки которая не нужна если не будешь отладчиком подключаться. Эта инфа позволяет заходить отладчиком внутрь стандартной библиотеки и ходить там по шагам.

Когда-то давно релизные сборки не содержали отладочную инфу, но разработчики фаерфокса попросили чтобы она всегда была. Если пользователь этого не хочет, то он может вырезать ее командой strip, и это не будет «внештатным рецептом» а официальной рекомендацией.

pftBest ★★★ ()
Ответ на: комментарий от pftBest

Три мегабайта это отладочная информация стандартной библиотеки которая не нужна если не будешь отладчиком подключаться. Эта инфа позволяет заходить отладчиком внутрь стандартной библиотеки и ходить там по шагам.

И печатать красивые трейсы.

tailgunner ★★★★★ ()
Ответ на: комментарий от MyTrooName

Ну я всё же немного ошибался т.к. Rc/Arc - реализует изменяемость содержимого при неизменяемости самой ячейки.

Arc<RefCell<MyTrait>> - позволил при динамической диспетчеризации дёргать методы объектов реализующих MyTrait.

AntonyRF ()
Ответ на: комментарий от khrundel

Арк - это многопоточная хрень, никаких гарантий от состояния гонки нет. Соответственно, нужно запаковать в рефцелл

Плохой совет: это тоже никак не гарантирует отсутствие состояния гонки.

В этом случае либо многопоток не нужен и можно использовать Rc<RefCell<T>> либо он нужен, и надо использовать Sync контейнер, обеспечивающий внутреннюю мутируемость, например Mutex. Полный тип то есть будет Arc<Mutex<T>>.

mersinvald ★★★★ ()
Последнее исправление: mersinvald (всего исправлений: 1)
Ответ на: комментарий от vblats

И рассуждения о том, как надо разрабатывать программные продукты, от МЛЯТЬ НЕ ПРОГРАММИСТА выглядят тупым троллингом.

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

И рассуждения о том, как надо разрабатывать программные продукты, от МЛЯТЬ НЕ ПРОГРАММИСТА выглядят тупым троллингом.

Нет, скорее твоя апелляция к «сперва добейся» выглядит тупым троллингом.

Или ты когда тыкаешь официанта в недожаренный шашлык, или в салат куда забыли положить майонез - ты светишь корочкой повара-профессионала ? Сомневаюсь.

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

vblats ()
Ответ на: комментарий от vblats

Или ты когда тыкаешь официанта в недожаренный шашлык, или в салат куда забыли положить майонез - ты светишь корочкой повара-профессионала?

vblats> При реализации крупного проекта, его вначале проектируют на бумаге, учитывают все риски и целесообразности, а только затем начинают воплощать в жизнь. Сразу видно что ты бездельник, никогда не работал в организации крупнее ООО «Вектор».

Ты учишь повара жарить шашлык.

мое утверждение не относится к программированию аж никак.

Вот здесь ты прав.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Ты учишь повара жарить шашлык.

Нет, я констатирую факт, что если повар говорит что сегодня шашлык в 20 раз лучше чем вчера (и это правда) - то повар дебил, и такой ресторан с таким поваром я буду обходить десятой дорогой. Могу конечно вдогонку посоветовать читать книжки, прежде чем начинать готовить, но это вроде и так ясно.

Но тебе ведь главное бесплатность, а не качество, поэтому ты будешь такое кушать, и просить добавки.

Чем это чревато - посмотришь сам спустя некоторое время.

vblats ()
Ответ на: комментарий от khrundel
Arc<RefCell<ILinkChannel>>

А может ктото сказать как такая конструкция размещается в памяти ? Сколько там malloc-ов и что ложится на стек ?

Насколько я понимаю Arc<T> - это уже два объекта + ссылка на стеке. Но вот как эти объекты хранятся ? В одном heap блоке композицией или в двух разных?

Анологичный вопрос по RefCell<T>?

zaz ★★★★ ()
Ответ на: комментарий от anonymous

Здесь не алгоритмическая сложность, здесь неучет особенностей современного x86 железа. Алгоритмическая сложность оценивается на абстрактной машине Тьюринга, а на реальном железе, например, пузырек работает быстрее quicksort на малых массивах.

unordered_map плохой потому что он не cache-friendly и легко разбрасывается по памяти и вырождается в односвязный список. Есть презентация от гуглера, «Efficiency with Algorithms, Performance with Data Structures», где он рассказывает, почему standard library плохой для задач, где нужна производительность.

Все, что не вектор - не работает в тесных циклах, потому как убивает кэш. Сейчас сам сижу, оптимизирую high-perf/low-latency софтину и на неправильном использовании кэша можно легко потерять половину производительности.

anonymous ()
Ответ на: комментарий от zaz

Даже в цпп, в котором мувы через жопу и есть возможность конструкции шаредптра из готового указателя, при нормальной практике (make_shared) выделяется только один блок и для счётчиков и для самого объекта. В расте все объекты перемещаемы простым побитовым копированием и рк/арк при создании просто перемещают объект внутрь управляющего блока. Таким образом, rc - это указатели «на стеке» + блок в хипе, содержащий кроме объекта ещё 2 счётчика (сильных и слабых ссылок). RefCell, вопреки названию, не содержит ссылку. *Cell в расте - это аналог mutable поля в cpp. Простой Cell - это просто обёртка, позволяющая только помещение/извлечение/замену значения целиком, а RefCell - получение указателя на внутренность для изменения на месте. По идее RefCell должен быть просто блоком, содержащим структуру + один счётчик. 0 означает RefCell свободен, -1 - эксклюзивно позаимствован, положительное число - количество шаредных заимствований. Как-то так.

khrundel ()
Ответ на: комментарий от zaz

Для такого кода:

trait ILinkChannel {
}

struct X {
    x: i64,
}

impl ILinkChannel for X {
}

fn main() {
    let a: Arc<RefCell<ILinkChannel>> = Arc::new(RefCell::new(X {x:13}));
    foo(&a);
}

Будет лежать два указателя на стеке (один на кучу а второй на vtable) и одна аллокация на куче размером 32 байта.

pftBest ★★★ ()
Ответ на: комментарий от tailgunner

7 лет уже, время подводить какие-никакие итоги...

Почему 7? Давай уже 12.

Гуня, а Гуня, таки почему тебе так нравится цифра 12? Она для тебя какая-то сакральная? 2011 год легко ищется на этом сайте в поиске новостей о язычке rust. (Да, семь лет - это много, и пора подводить неутешительные итоги.)

anonymous ()
Ответ на: комментарий от red75prim

Перемещаемы все (из-за этого, кстати, нельзя сделать структуру, содержащую ссылку на свою часть)

На самом деле (но это тонкая деталь) как раз не все, и можно:

struct SelfRef<'a>  // подсветка ' на LOR сломана
{
    foo: i32,
    self_ref: Cell<Option<&'a SelfRef<'a>>>
}

let s = SelfRef { foo: 12, self_ref: Cell::new(None) };
s.self_ref.set(Some(&s));

// нельзя переместить s
// drop(s);

Playground

anonymous ()