LINUX.ORG.RU

Запилите кто-нибудь нормальный обзор Rust

 , ,


6

9

Коллеги, а не мог бы кто-нибудь из вас запилить нормальное сравнение Rust с плюсами? В последнее время rust то и дело упоминают как будущего убийцу с++, вот мне и стало интересно. Но изучать новый язык у меня сейчас времени нет, а все обзоры и сравнения (вот последнее на хабре: http://habrahabr.ru/post/225507/) сводятся к следующему:

Возьмем пример стандартного кода на с++

$ cat test.cpp
int main()
{
    *((int*)nullptr) = 0xdeadbeef;
}
Давайте его запустим, и посмотрим, что получится:
$ g++ -std=c++0x -o testcpp test.cpp && ./testcpp
Segmentation fault
Как видите, с++ позволяет выстрелить себе в ногу!
А теперь давайте посмотрим, что будет, если этот же код попытаться скомпилировать rust:
rust -o testrust test.cpp
test.cpp:1:1: 1:4 error: expected item but found `int`
test.cpp:1 int main()
           ^~~
Смотрите, компилятор rust не скомпилировал этот код и сохранил нам ногу! ergo, rust - убийца с++.

Очевидно, что сравнивая ошибки в синтетических двухстрочниках, ничего показать нельзя. Хотелось бы увидеть какую-нибудь задачу на примере из нескольких десятков строк, хорошо решенную на с++ (то есть без саботажа и попыток продемонстрировать убогость плюсов), краткий обзор проблем в коде, которые в с++ не решаются, потом реализация той же задачи на rust, в которой эти проблемы решены, а новых не добавилось.

Если где-то есть уже что-то подобное в сети, киньте ссылку.

UPD: нашел очень качественное сравнение с++ и go (http://kidoman.io/programming/go-getter.html).
tl;dr: товарищ сравнивал производительность, в качестве демонстрационной программы использовал трассировщик лучей. В первой серии go победил после множества оптимизацй, во второй серии с++ после таких же оптимизаций одолел go на одном ядре, в третьей серии в с++ впилили многопоточность, и он разорвал go пополам.
Стоит обратить внимание, что рейтрейсер на c++ в этом примере написан без единого new/delete.
Буду очень признателен, если кто-то напишет подобное сравнение с++ с rust, а еще лучше - если портирует трассировщик из примера выше на rust о объяснит, почему он лучше (там уже на несколько других языков портировали).



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

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

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

Валидный аргумент, иначе есть риск получить Ruby.

А что у Ruby с читаемостью не так?

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

избыточных, нерелевантных решению задачи символов

очевидный фикс

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

Я что-то не понял. Я был в свое время твоим энтузиазмом вдохновлен его потыкать, а теперь ты предал наши идеалы?!

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

Это был не хвостострел! Это авторский коллектив rust'а предал наши идеалы, братюнь!

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

Было бы что отнимать, я то думал ты шаришь и пытался даже дискутировать с тобой, на первой странице. А ты вон полтора года следишь за языком и хз написал ли даже Hello World на нем. Мне вот интересно кроме пхп то ты на чем то писал?

Впрочем, ты привлек в тему кого-то возможно полезного.

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

А ты вон полтора года следишь за языком и хз написал ли даже Hello World на нем

Ты слишком буквально понял «не пишу».

Мне вот интересно кроме пхп то ты на чем то писал?

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

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

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

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

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

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

По работе писал на PL/I, Си, Си++, REXX, VBA, Java, Python, shell, паре-тройке ассемблеров. JFF писал хелловорлды разной степени серьезности на... да всего уже и не упомню. На чем зафиксируешься? %)

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

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

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

Путём системного вызова clone() (man 2 clone), если мы про ассемблер в Linux. Если же про bare metal, то многопроцессорность реализуется путём APIC и IPI (межпроцессорных прерываний), а многопоточность — посредством написания кода, перекидывающего управление между потоками по таймеру.

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

Как реализуется многопоточность на уровне ассемблера?

Не понял вопроса.

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

А можно как нибудь совсем примитивно на псевдоасм коде (мне реально очень интересно, но я асм совсем не знаю)?

Управление потоками по таймеру на 1 ядре в принципе понятно, не понятно когда ядер больше одного.

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

То есть, ты про многопроцессорность? Там дело больше не в асме, а в конкретном железе — есть, грубо говоря, специальные порты ввода-вывода и специальные места в памяти, записывая в которые, можно сообщить второму (третьему, ...) процессору, что он должен проснуться и начать исполнять код из такого-то места в памяти.

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

Почти понял, грубо говоря пишем в какое то место памяти программу, потом кидаем указатель нужному ядру и оно исполняет?

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

Да. Ну, программа обычно уже в памяти. Потом некоторым специальным образом кидаем ядру адрес и оно начинает работать.

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

пишем в какое то место памяти программу, потом кидаем указатель нужному ядру и оно исполняет?

Да.

Если речь о юзерспейсе - вообще-то нет. clone работает как fork - выполнение продолжается от точки возврата.

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

Не помню, надо смотреть, как эти самые IPI работают. Ты же спрашиваешь про управление железом напрямую, без ОС?

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

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

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

Поэтому я и написал «если». Впрочем, в случае bare metal «кидаем и оно исполняет» - тоже слишком упрощенно, если речь не об учебной ОС.

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

Давай я скажу от чего шел, сначала я изучил эрланговскую многопоточность, там руками вообще ничего делать не надо, просто посылаешь сообщения и все. Далее я посмотрел на более низкоуровневые, там часто есть пул процессов (иногда с приоритетами) которые выполняются по очереди до выполнения, либо до переключения на другой процесс по таймеру. Сейчас вот я понимаю что можно передавать другому процессору(ядру) ссылку на место в памяти и он будет выполнять. Но я все равно полностью не понимаю как ОС, например, выполняет всю эту работу на самом низком уровне (в моем случае 8.1 винда, если важно) и как это программируется ручками. Вероятно уйдем и в управлением железом напрямую.

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

Чувак, ну это уже совсем оффтопик. Я, конечно, понимаю, что вы тут уже три дня пируете и все такое. Но надо же хоть немного совесть иметь.

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

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

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

В двух словах, чтобы закрыть эту тему.

Есть список задач (потоков). Дальше, если ядро одно: одна задача является текущей, вынимается из списка, и процессор начинает исполнять ее код. Приходит прерывание от таймера. Обработчик прерывания записывает текущие значения всех регистров и прочее состояние процессора в память, переключается на следующую задачу в списке, восстанавливает из памяти состояние процессора новой задачи, выходит. Предыдущая задача остановилась, новая задача продолжила выполняться. В результате, все задачи по очереди получают ненадолго процессор.
Если ядер много: список ожидающих выполнения задач общий, но каждое ядро имеет свою текущую задачу. Процедуры смены задачи те же самые, только добавляется код синхронизации при работе со списком задач (спинлок какой-нибудь, чтобы два ядра не пытались его одновременно менять).
Новый процесс создается путем добавления задачи в список. При завершении процесса задача из списка удаляется.

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

Про то, как происходит штатная работа, ddos3 уже написал.

А вот запуск всех ядер, кроме первого, в момент старта ОС происходит именно так, как я описал: ОС с первого ядра «пинает» все остальные посредством IPI и говорит им «проснись и начни выполнять код функции ожидания» (что-то вроде вечного цикла из HLT). Потом этим ядрам начинают приходить таймерные прерывания, в табличке потоков появляются потоки и так далее.

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

Что реально тупо общая очередь из которой ядра дергают потоки?

И еще вопрос, встречал информацию что та же Windows не может исполнять очень много процессов, если да то почему?

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

Общая очередь — это очень грубое приближение, на самом деле там достаточно изощрённые алгоритмы выбора того, какой поток будет исполняться «следующим». Так вот, согласно расхожему мнению, в винде этот алгоритм говно.

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

Хорошо, в целом многое прояснилось. Еще небольшой вопросик, нередко встречаю информацию, в т.ч. в контексте ВМ эрланга что передача данных между двумя ОС процессами довольно дорогая операция, почему так?

anonymous
()

ЧСХ, треды про rust (во всяком случае на ЛОРе) неизбежно скатываются в лютый срач спустя 15 мин. после опубликования.

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

Если речь о разных процессах (не потоках), то потому, что разные процессы находятся в разных адресных пространствах (имеют свою виртуальную память, т. е. адрес, например, 0x04000000 у двух разных процессов будет на самом деле соответствовать двум совершенно разным местам в физической оперативной памяти). Поэтому любая передача данных между разными адресными пространствами происходит через ОС (процесс говорит ядру ОС, что вот эти данные нужно передать другому процессу, ОС их копирует в память к другому процессу и потом «пинает» его с помощью сигнала или чего-то там ещё) — или, что ещё дороже, через файлы.

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

В многопоточке как раз Go здесь очень шустрый. Посмотри на горизонтальную ось: она проградуирована в секундах, чем меньше — тем лучше.

Правда, рядом в той статье есть ещё один график: там C++ сильно уделывает Go просто за счёт того, что в C++ есть OpenMP.

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

Вспомнил тут как разработчик эрланга в одной из версий отключил принудительное соответствие потокам ВМ и получил сильную просадку по производительности, может у Go та же болезнь? Грубо говоря там используется больше 8 горутин и они постоянно скачут по разными ядрам это и дает просадку, такое может быть?

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

Смотря как передавать.

Обычно используются всякие механизмы передачи данных через ядро ОС, а любое обращение к ОС требует переключения процессора в «режим ОС» и смены настроек MMU. А потом при возврате из кода ОС нужно все вернуть обратно. Это дорого.
Передача данных из юзер-спейса в кернел-спейс требует их копирования из памяти процесса в память ядра, а передача второму процессу требует копирования из памяти ядра обратно в память процесса. Еще расходы.
Иногда процессы общаются вообще через сетевой стек, что еще дороже.

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

ddos3
() автор топика
Ответ на: комментарий от intelfx

Ага, увидел. Конечно проигрывает плюсам, но всего в 2 с небольшим раза, а не как я сначала подумал, в 4 с половиной. Вообще в голову не пришла мысль, что что-то может быть быстрее си/плюсов. В общем-то такой слив в таком молодом языке я считаю очень хорошим, а потом может и дотянут до того что разница будет в 40-70%.

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

А использование общего куска памяти как то влияет на производительность по сравнению с тем если бы каждый поток использовал свой кусок? Или там все ок и нужно заморачиваться только с разруливанием доступа к ресурсам между процессорами?

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

Чтение/запись в общую память работает так же быстро, как и доступ к приватной памяти процесса.

ddos3
() автор топика
24 июля 2014 г.
1 сентября 2014 г.
Ответ на: комментарий от tailgunner

Rust, хотя и не является передним краем CS (которым должен был стать BitC)

Такой большой, а в BitC веришь.

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

в BitC веришь

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

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

Хм, проглядел :)

Во первых потому-что не нужен сам rust. Почему? Да потому что плюсы никто заменять не будет, просто закостылят очередную модную/нужную фичу в них и пойдут дальше.

В плюсы все вклячат конечно, кто бы сомневался. Только должен же быть какой-то предел у сложности. Да и конфликты разных фишек языка никто не отменял. И мне страшно представить, как, например, можно в плюсы вклячить анализатор времени жизни ссылок, наподобие Rust`овского.

Далее компилятор, если на свежей ОС не собирается gcc, то проблему ищут именно в ОС, а не в gcc. Сколько лет компилятор ржавчины пилить до аналогичного состояния? До следующего стандарта плюсов?

Пффф, так можно вообще ничего нового не начинать разрабатывать, оно в любом случае поначалу нестабильнее будет.

Далее. Разработчики rust сами толком не знают что хотят сделать, постоянно запиливая и выпиливая какие-то фичи. О чем это говорит? Да о том что у них нихрена нет плана и чистой удачей для них будет избежать ошибок в дизайне которые выстрелят через пару-тройку лет после релиза и исправляя которые придется поломать половину языка.

http://doc.rust-lang.org/complement-project-faq.html

Основополагающие концепции языка уже давно не меняются - владение и одалживание. Про план смотри Road to Rust 1.0.

Я очень сильно сомневаюсь в том, что детальное и подробное планирование до последнего винтика подобной огромной системы убережет от «ошибок в дизайне которые выстрелят через пару-тройку лет после релиза и исправляя которые придется поломать половину языка».

Еще: совершенно мудацкий синтаксис о который просто ломаются глаза, в старых еще языках простительно, но зачем такое делать в новом?

Я нахожу синтаксис не идеальным, само собой, но вполне приемлемым. Что бы ты хотел убрать и зачем? (Только про ';' не говори, это уже обсуждалось очень-очень-очень много раз)

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

Четкой узкой ниши, как у того же Go, я тоже не вижу. Просто хороший системный язык, как альтренатива плюсам или Си. Очень может пригодиться, как я уже писал, в игровых движках - тут даже не так важен унаследованный С++ код, потому что в разработке игр все равно адово велосипедят.

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

Что бы ты хотел убрать и зачем?

Я бы хотел добавить, ведь:

let mut x: int = 1i;

это слишком читабельно.

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

Тебе не нравится локальный вывод типов? Или синтаксис «let»? Или отдельный «mut»? Или синтаксис числовых литералов?

Можно чуть более развернуто? А то я не уверен, чего ты имел ввиду.

ozkriff
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.