Forwarded from ☕️ Мерлин заваривает τσάι 🐌
Я так люблю, когда программисты оптимизируют количество нажатий клавиш. Подозреваю, что сэкономленное время они тратят на саморазвитие
❤19😁4👍1🔥1
#prog #rust #rustreleasenotes
Вышла версия Rust 1.72.0! Как обычно, тут только то, что интересует меня, а полный ченджлог тут.
▪️Офигенно полезная вещь: компилятор теперь говорит о том, что имена не определены из-за того, что определяющий их код находится под неактивным
▪️Компилятор теперь не имеет ограничения на время вычисления const fn (технически ограничено включённым по умолчанию линтом, но его можно и отключить). При этом он всё ещё выдаёт предупреждения, если код из-за этого долго компилируется, но интервал между ними удваивается после каждого вывода, чтобы не спамить в консоль.
▪️Несколько линтов из Clippy втащили в компилятор, а именно:
🔹undropped_manually_drops (warn по умолчанию) — попытка явно дропнуть
🔹invalid_utf8_in_unchecked — разделив при этом на две:
🔹cmp_nan как invalid_nan_comparisons (warn по умолчанию) — явное сравнение с NaN (такое сравнение всегда возвращает ложь)
🔹cast_ref_to_mut — при кастах из
▪️Для указания трейт-объектов теперь не нужно выписывать ассоциированные типы, на которых есть ограничение
▪️Отправляющая половинка mpsc-канала из std наконец-то реализует
▪️Уточнено поведение
▪️Как я уже говорил,
▪️Опять-таки, как я уже рассказывал,
▪️Стабилизирован
Вышла версия Rust 1.72.0! Как обычно, тут только то, что интересует меня, а полный ченджлог тут.
▪️Офигенно полезная вещь: компилятор теперь говорит о том, что имена не определены из-за того, что определяющий их код находится под неактивным
#[cfg]
.▪️Компилятор теперь не имеет ограничения на время вычисления const fn (технически ограничено включённым по умолчанию линтом, но его можно и отключить). При этом он всё ещё выдаёт предупреждения, если код из-за этого долго компилируется, но интервал между ними удваивается после каждого вывода, чтобы не спамить в консоль.
▪️Несколько линтов из Clippy втащили в компилятор, а именно:
🔹undropped_manually_drops (warn по умолчанию) — попытка явно дропнуть
ManuallyDrop
.🔹invalid_utf8_in_unchecked — разделив при этом на две:
🔸invalid_utf8_in_unchecked
(deny по умолчанию) при вызове std::str::from_utf8_unchecked{, _mut}
на невалидном UTF-8 — это всегда неопределённое поведение🔸invalid_from_utf8
(warn по умолчанию) при вызове std::str::from_utf8{, _mut}
на невалидном UTF-8 — такой вызов всегда возвращает ошибку🔹cmp_nan как invalid_nan_comparisons (warn по умолчанию) — явное сравнение с NaN (такое сравнение всегда возвращает ложь)
🔹cast_ref_to_mut — при кастах из
&T
в &mut T
. allow по умолчанию, но исключительно из-за наличия false positive, к следующему релизу планируют сделать уже deny по умолчанию.▪️Для указания трейт-объектов теперь не нужно выписывать ассоциированные типы, на которых есть ограничение
Self: Sized
. Это консистентно с where Self: Sized
на методах, наличие которых не влияет на object safety, но которые нельзя вызвать на трейт-объектах. Отмечу, что указывать остальные типы для трейт-объектов всё также надо.▪️Отправляющая половинка mpsc-канала из std наконец-то реализует
Sync
.▪️Уточнено поведение
HashSet::insert
: если ключ уже есть в множестве, то он не заменяется, а переданный ключ дропается.▪️Как я уже говорил,
select_nth_unstable
теперь имеет реальную задокументированную линейную сложность.▪️Опять-таки, как я уже рассказывал,
ptr_eq
на счётчиках ссылок теперь сравнивает лишь адреса.▪️Стабилизирован
impl TryFrom<&OsStr> for &str
▪️В const-контексте теперь можно использовать CStr::from_bytes_with_nul, CStr::to_bytes, CStr::to_bytes_with_nul и CStr::to_str.👍8🔥2
Некоторые говорят писать
unsigned int
, большинство говорят писать просто unsigned
, я же говорю писать на Rust👌11😁6
Интересные мысли о том, как можно было "дописать" древнегреческую мифологию
https://t.iss.one/figaning_ideas/2438
https://t.iss.one/figaning_ideas/2438
Telegram
Офигительные идеи🦄
(Можете читать с жирного капса, там весело, а тут всё прелюдия.)
В греческой мифологии много меньше, чем в иных известных, какой-то борьбы добра со злом (или иных сходных начал), эсхатологии, "эпического итога", чего-то такого. Для сравнения. В скандинавской…
В греческой мифологии много меньше, чем в иных известных, какой-то борьбы добра со злом (или иных сходных начал), эсхатологии, "эпического итога", чего-то такого. Для сравнения. В скандинавской…
Вечерний Даня (danya.ru)
Погодите, это правильные пчелы? Или неправильные?
Напоминает спиральный рост кристаллов. И причина, видимо, схожая: винтовая дислокация решётки (атомов кристалла и отдельных сот соответственно)
🙏4🤡1
#prog
Подписчики, я обескуражен.
По идее,
Я решил замерить разницу при помощи кода, который для нескольких количеств страниц выделяет память: сначала при помощи
Код выглядит так:
А вот какой результат я получаю на своём ноутбуке, который на Windows:
Посему вопрос: откуда такая разница в поведении? Существенна ли тут разница в OS или ещё играет роль (очевидная) разница в железе? Размер страниц памяти, если что, одинаковый, я проверял.
Подписчики, я обескуражен.
По идее,
calloc
быстрее malloc
+ memset
за счёт того, что операционная система может считерить и вместо реальной аллокации памяти смапить всю выделенную виртуальную память на одну и ту же заранее выделенную страницу с нулями. С другой стороны, при последующей работе обращение к странице вызовет дорогостоящий page fault, который заставит операционную систему реально выделить память.Я решил замерить разницу при помощи кода, который для нескольких количеств страниц выделяет память: сначала при помощи
calloc
и читает по первому байту из каждой выделенной страницы, а потом при помощи malloc
и перезаписывает всё нулями.Код выглядит так:
fn get_page_size() -> usize {Когда я запускаю этот код на Rust playground (который, я напомню, на Linux), я получаю такие результаты (примерно, потому что конкретные цифры от запуска к запуску, разумеется, разнятся):
// платформо-специфичный код
}
use std::alloc::{alloc, alloc_zeroed, dealloc, Layout};
use std::time::Instant;
fn main() {
let page_size = get_page_size();
println!("page size = {page_size} bytes\n");
for n_pages in (0..5).map(|p| 2 * 10_usize.pow(p)) {
let layout = Layout::from_size_align(page_size * n_pages, 1).unwrap();
println!("n pages = {n_pages}");
let start = Instant::now();
let ptr = unsafe { alloc(layout) };
assert!(!ptr.is_null());
unsafe {
std::hint::black_box(ptr).write_bytes(0, layout.size());
}
unsafe { dealloc(ptr, layout) }
let duration = start.elapsed();
println!("with alloc + memset:\t{duration:?}");
let start = Instant::now();
let ptr = unsafe { alloc_zeroed(layout) };
assert!(!ptr.is_null());
std::hint::black_box(ptr);
for n in 0..n_pages {
std::hint::black_box(unsafe { ptr.add(n * page_size).read() });
}
unsafe { dealloc(ptr, layout) }
let duration = start.elapsed();
println!("with calloc:\t\t{duration:?}");
println!();
}
}
n pages = 2
with alloc + memset: 4.061µs
with calloc: 660ns
n pages = 20
with alloc + memset: 28.651µs
with calloc: 2.27µs
n pages = 200
with alloc + memset: 728.031µs
with calloc: 236.287µs
n pages = 2000
with alloc + memset: 3.009318ms
with calloc: 1.227636ms
n pages = 20000
with alloc + memset: 27.395091ms
with calloc: 9.131857ms
Видно, что calloc
хоть и явно не бесплатный (даже не смотря на то, что лишь читаем, а не пишем), но всё равно быстрее malloc
+ memset
даже на двух страницах памяти.А вот какой результат я получаю на своём ноутбуке, который на Windows:
n pages = 2Видно, что
with alloc + memset: 11.3µs
with calloc: 1.5µs
n pages = 20
with alloc + memset: 38.4µs
with calloc: 4.7µs
n pages = 200
with alloc + memset: 392.2µs
with calloc: 55.5µs
n pages = 2000
with alloc + memset: 2.6747ms
with calloc: 1.8153ms
n pages = 20000
with alloc + memset: 37.8768ms
with calloc: 24.9391ms
calloc
и тут быстрее, но уже далеко не так сильно. Более того, если выделять по 200 000 страниц памяти (что не получается сделать на playground из-за квот по памяти, видимо), то получается что-то вроде такого:n pages = 200000То есть относительная разница, кажется, стремится к нулю (а в некоторых запусках
with alloc + memset: 345.1817ms
with calloc: 318.5761ms
calloc
даже медленнее).Посему вопрос: откуда такая разница в поведении? Существенна ли тут разница в OS или ещё играет роль (очевидная) разница в железе? Размер страниц памяти, если что, одинаковый, я проверял.
❤10
Блог*
#prog Подписчики, я обескуражен. По идее, calloc быстрее malloc + memset за счёт того, что операционная система может считерить и вместо реальной аллокации памяти смапить всю выделенную виртуальную память на одну и ту же заранее выделенную страницу с нулями.…
И ещё: если сначала вызывать
calloc
, а потом malloc
, то разница по времени становится больше, но общая картина не меняется