haskell имеет gc, потребляет много памяти что ,в некоторых случаях, критично.
(орфография сохранена)
Да нормально программы на haskell потребляют память. Бинарники только большие получаются, а с памятью нормально.
Я вот никак не могу добиться того, чтобы эквивалентный код на rust заработал быстрее, чем такой же, но на haskell. Что ни делаю, все равно на haskell мой код быстрее, чем такой же код на rust.
В пузоне счетчик ссылок вместо GC? Ну ваще днище. Какой же гвидон распиаренный даун все-таки. Хотя вроде гугль выкиеул его на мороз вместе с недоязычком для дошколят.
Я вот никак не могу добиться того, чтобы эквивалентный код на rust заработал быстрее, чем такой же, но на haskell. Что ни делаю, все равно на haskell мой код быстрее, чем такой же код на rust.
Код на haskell - конкретно задача MachRep1.hs (с увеличенным конечным временем моделирования до t2=10000000.0 - десять миллионов) из дистрибутива Айвики: http://hackage.haskell.org/package/aivika
С кодом на rust я пока не решил, открывать его или нет. Но он чем-то похож на futures-rs. Если кто напишет на rust быстрее, буду только рад узнать. Условие - код должен реализовывать именно процесс-ориентированную парадигму дискретно-событийного моделирования, чтобы было легко использовать и писать в таком стиле.
Ну, вот, у меня сейчас в фоне висел браузер FireFox на трех простых страницах. Это немного на сколько-то процентов замедлило скорость тестов, которые я сейчас повторил.
Модель на haskell у меня обсчиталась в среднем за 6.6 секунд. Цифры стабильные, несмотря на использование случайных задержек.
Такая же модель на rust со всеми ухищрениями у меня обсчиталась в среднем за 8.2 секунды.
Причем, код на haskell в разы чище, короче и проще, потому что на rust пришлось имитировать монады (впрочем, как в futures-rs).
Сам код на rust получился такой:
#![type_length_limit="2097152"]
extern crate rand;
extern crate aivika;
use rand::distributions::{Exp, IndependentSample};
use aivika::simulation::Specs;
use aivika::simulation::simulation::*;
use aivika::simulation::event::*;
use aivika::simulation::ref_comp::*;
use aivika::simulation::process::*;
const MEAN_UP_TIME: f64 = 1.0 / 1.0;
const MEAN_REPAIR_TIME: f64 = 1.0 / 0.5;
fn machine_process(total_up_time: RefComp<f64>) -> ProcessBox<()> {
loop_process(move || {
let total_up_time = total_up_time.clone();
let exp = Exp::new(MEAN_UP_TIME);
let up_time = exp.ind_sample(&mut rand::thread_rng());
hold_process(up_time).flat_map(move |()| {
total_up_time.modify(move |total_up_time| {
total_up_time + up_time
}).into_process()
}).flat_map(move |()| {
let exp = Exp::new(MEAN_REPAIR_TIME);
let repair_time = exp.ind_sample(&mut rand::thread_rng());
hold_process(repair_time)
})
}).into_boxed()
}
fn main() {
let specs = Specs {
start_time: 0.0,
// stop_time: 1000.0,
stop_time: 10000000.0,
dt: 1.0
};
let total_up_time = RefComp::new(0.0);
let total_up_time2 = total_up_time.clone();
let model =
boxed_process(machine_process(total_up_time.clone())).run().flat_map(move |_| {
boxed_process(machine_process(total_up_time.clone())).run()
}).run_in_start_time().flat_map(move |_| {
let total_up_time = total_up_time2;
time_event().flat_map(move |t| {
total_up_time.read().map(move |total_up_time| {
total_up_time / (2.0 * t)
})
}).run_in_stop_time()
});
let result = model.run(specs);
println!("The result is {} (~ 0.66)", result);
assert!((result - 0.66).abs() < 1.5);
}
Здесь практически все комбинаторы flat_map, map инлайнятся, кроме loop_process. То, где используется слово boxed - явно уходит в кучу. Все остальное по возможности живет на стеке. Главный цикл сидит внутри loop_process.
Как-то даже вырубал случайность из моделей. Там экспоненциальное распределение. Поэтому условно можно брать сразу среднее, а не использовать генератор. Но даже такой код на rust отстает
let model =
boxed_process(machine_process(total_up_time.clone())).run().flat_map(move |_| {
boxed_process(machine_process(total_up_time.clone())).run()
}).run_in_start_time().flat_map(move |_| {
Нда... До недавнего времени я был уверен, что Rust — это все-таки замена чистого C, а не C++. Но теперь у меня на этот счет есть большие сомнения. Мало кто из убежденных C-шников захочет писать подобные макароны, пусть даже они дают большую безопасность. Не говоря уже про тех, кто тупо не сможет писать подобные макароны.
Причем, код на haskell в разы чище, короче и проще, потому что на rust пришлось имитировать монады (впрочем, как в futures-rs).
Я так понимаю, что код всё же не эквивалентен?
Здесь практически все комбинаторы flat_map, map инлайнятся, кроме loop_process
Если так, остается предполагать по-разному реализованные алгоритмы в Haskell-версии aivika и Rust-версии.
Закрыл браузеры. Получилось, что код на haskell отработал в среднем за 5.9 - 6 секунд, а код на rust - за 7.2 - 7.5 секунд, соответственно
Кхм. Как будто ты их по наручным часам меряшь. Что говорит time? aivika на Rust может быть хуже распараллелена (или Haskell смог что-то распараллелить лучше), например - это будет видно.
Мало кто из убежденных C-шников захочет писать подобные макароны, пусть даже они дают большую безопасность. Не говоря уже про тех, кто тупо не сможет писать подобные макароны.
dave - хаскелист/скалист/лиспер, он и пишет так. Системные прогеры так писать не будут, а убежденные сишники (типа Iron_Bug) вообще не будут писать на Rust.
Да мне как раз rust понравился. Но я думаю, что его модель так же не оптимальна по выразительности в отношении железа, как и модель Си++ к примеру (спорить не буду - не охота, да и нет времени)
И скорее всего, оптимального языка нет и быть не может
Я тебе уже написал, что в этом выражении есть смысл. Захочу я среднее поменять, то мне что каждый раз самому вычислять интенсивность, когда есть компьютер, который прекрасно это сделает за меня, причем сделает это оптимально.
Да просто попытался применить. Мне интересны задачи, для которых rust подходит. Я воспринимаю этот язык, как сильно популяризованную версию haskell с прицелом на системное и низкоуровневое программирование
Я тебе уже написал, что в этом выражении есть смысл.
Смысл был бы, если бы у вас было что-то вроде:
const A : f64 = 1.0;
const B : f64 = 1.0;
const MEAN_UP_TIME : f64 = A/B;
Тогда было бы очевидно, что MEAN_UP_TIME вычисляется на основании каких-то значений, которые можно варьировать. При этом если еще вместо A и B будут осмысленные названия, так вообще хорошо.
Ваш же код говорит о том, что у вас каша в голове. И с этой кашей в голове вы делаете заявления вида: «Но я думаю, что его модель так же не оптимальна по выразительности в отношении железа, как и модель Си++ к примеру». Смешно же.
У тебя у самого каша, раз пристал к тому, как мне нравится задавать параметры модели. (кстати, там название осталось от хаскелевской версии - должен быть RATE, но ты все равно не заметил)
У тебя у самого каша, раз пристал к тому, как мне нравится задавать параметры модели.
Мне как-то фиолетово, какой говнокод вы производите. Поинт был в двух совсем других вещах:
- упертые C-шники, использующие C для низкоуровневых вещей, писать на Rust-е в таком духе, как это делаете вы, не будут. И если то, как используете Rust вы — это идиоматический код, то C-шники будут держаться от Rust-а так же далеко, как и от C++;
- выше заявление о том, что «модель Rust-а» для чего-то там не подходит, звучит смешно.
Полагаю, вы так же согласны с озвученным тезисом о том, что «его [Rust-а] модель так же не оптимальна по выразительности в отношении железа, как и модель Си++ к примеру»?
Если согласны, то может развернете этот тезис так, чтобы он был понятен простым смертным?
Во-первых, я бы сначала отметил, что в первом случае вам следовало вместо «так же» использовать «также».
Во-вторых, я никакого тезиса не заметил, только личное мнение Дэйва, адресованное мне, а не ко всем присутствующим в треде. Объяснять, что имел в виду другой человек, никогда не казалось мне привлекательным занятием, и в этот раз я также предпочту этого избежать.
И в-третьих, давайте уже перестанем оффтопить. Вам, конечно, не терпится получить сатисфакцию, но для этого еще будут возможности в будущем.