Обновить
154
0.1
Григорий@bfDeveloper

Программист на C++, D, Brainfuck

Отправить сообщение
Придётся подумать над оптимизацией размера. По видео хорошо заметно, что вся машина не входит в область расчёта, и поэтому её дальние части работать не будут.
А вообще большущее спасибо за работу. Сам хотел такое делать, но руки не доходили.
D — противоположность Go для больших проектов. Я бы даже сказал, что он заточен под большие проекты. Множество привычных фич, которых нет в Go, в других языках были придуманы для масштабирования проекта (ООП, шаблоны, compile time, возможность своих DSL), и D поддержал и развил эти идеи. Из-за этого он выглядит нагруженным, но зато поддерживает кучу разных подходов и парадигм (от процедурной до ООП и функциональной).
По первому вопросу всё непросто. D гораздо привычнее для программистов с других языков, но при этом он существенно сложнее Go. Для С++ программистов D покажется простым, и среднего программиста можно сажать писать код почти сразу.Для Java программистов — очень знакомым, но с кучей новых вещей.
С какого бы языка человек не пришёл он найдёт в D знакомые концепции, но это бывает минусом. Всё же проект должен быть однородным и все должны писать одинаково. И вот для обучения D стилю времени уйдёт точно больше чем в случае с Go.
А я вот не согласен с тем, что пользователю нужен результат. Нет, изначально гаджеты и софт для этого создавался, но уже давным давно люди покупают ощущения использования, а не результат. Кто пользуется возможностями iPhone6, которые недоступны в iPhone5? Кто из владельцев спорткаров действительно выжимал максимальную скорость?
К сожалению большинство современных гаджетов предлагают в первую очередь ощущение того, что этот гаджет вам нужен, иначе его не продать. Новомодные стартапы придумывают потребность пользователя, а потом её решают. В этом ключе оказывается важнее управление лампочкой с телефончика, чем нормальное освещение в квартире.
Я не говорю, что всё описанное выше хорошо, скорее это плохо. Но к сожалению, сейчас рынок работает так.
void mySum(int[] r, Task tid) {
    int result = r.sum;
    tid.send(result);
}

void example() {
    auto s = [7, 2, 8, -9, 4, 0];

    auto c = Task.getThis;
    runTask(toDelegate(&mySum), s[0..$/2], c);
    runTask(toDelegate(&mySum), s[$/2..$], c);
    int x = receiveOnly!int();
    int y = receiveOnly!int();

    logInfo("%d %d = %d", x, y, x+y);
}

Проект, который можно запустить, здесь.
Это почти полный эквивалент. По крайней мере делает ровно то же самое, и я постарался сделать код максимально похожим, чтобы прослеживались параллели.
Основное отличие — отсутствие канала. Вместо этого посылается сообщение. Полной аналогии типизированных каналов в vibe.d нет, есть две альтернативы:

  • Сообщения. Буферизированые в очереди, типизированные, но посылаются в сопрограмму, а не в отдельный объект. Минимальная шаблонная обёртка и это будет полная аналогия каналов
  • TaskPipe. Ведёт себя как канал, можно буфферизировать, можно не буфферизировать, но предназначен только для данных. То есть только ubyte[]

Цикл суммирования я тоже убрал, это слишком много бессмысленного кода. Благодаря нормальным шаблонам в D есть нормальные обобщённые алгоритмы. Их не надо писать каждый раз заново, при этом они не теряют в производительности. Это как раз та область, где D нет равных. Go тут тоже нет равных, но в обратном смысле — этой фичи нет вообще и без нормальных шаблонов быть не может.
И вот из того, что я видел

Мне кажется проблема в том, что асинхронность в D вы не видели.

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

Это точно так же можно делать в D. Fiber по легковесности эта та же самая горутина, можете создавать десятками и сотнями тысяч.

в D предлагают опять эти уродливые события и колбеки

Я вас не понимаю, честно. Найдите в vibe.d хоть один колбек. Кроме разве что onConnection и onTimer. Но они и инициируются не кодом, а некой третьей стороной, для них нет линейного кода. Так проиходит и в Go и в C#.
А для чтения, записи, подключения к кому-то нет никаких колбеков или событий. События есть для общения между сопрограммами, но это тот же самый select в Go, только гораздо универсальнее.
Бывают ситуации, где предлагается альтернатива: колбек или возвращаемое значение. Просто так получилось, что чистые колбеки работают чуть-чуть быстрее и это API оставлено. Но код всё равно можно писать синхронно.
Всё сделано так чтобы было удобно писать именно линейный код: предоставляются асинхронные линивые диапазоны для чтения/записи, автоматически закрываются соединения при выходе из скоупа и тд, и тп. Чего-чего, а callback hell, это точно не про vibe.d
Fiber в стандартной библиотеке. Vibe.d поддерживает множество ивентлупов (libevent, libev, win32, собственная библиотека libasync). Большинство библиотек для асинхронных операций основываются на vibe.d, он стал почти стандартом, поэтому проблемы совместимости нет. Кроме того модель сопрограм такова, что если функция не выполняет асинхронных действий сама, то ей не требуется какая-то особая поддержка асинхронности. То есть любые синхронные библиотеки отлично работают в асинхронном коде.
Хорошо у него с производительностью. Сравнивал простые HTTP сервер и клиент с Go, получилось примерно одинакого. Причём масштабируются и Go и D одинакого хорошо. С учётом обработки и всяких парсингов JSON D оказывается быстрее. Есть мнение, что самый быстрый JSON как раз написан на D. Бенчмарк конечно не совсем честный, но точно претендент на лидерство.
В бенчмарке по вашей ссылке vibe.d есть, правда работал в один поток (была взята старая версия фреймвёрка с досадным багом). PR с нормальной многопоточной версией был отправлен вовремя, но почему-то его не приняли. Ждём следующего запуска, чтобы увидеть правильные результаты.
"Сложный" пример предлагал чуть выше, а за совсем простыми можете обратиться сюда. Пример оттуда:

auto conn = connectTCP("time-c.nist.gov", 13);
logInfo("The time is: %s", conn.readAllUTF8());

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

while(true) {
        c.write(buf.data);
        c.write(['\0']);
        buf.clear();
        c.readUntil(buf, ['\0'], SIZE);
    }
}

Это кусок одного очень простого теста, слегка усложнённый вариант эхо сервера. Пишет в сокет то, что получил. Что c.write, что c.readUntil — асинхронные операции, в которых произойдёт переключение волокон исполнения. С моей точки зрения Fibers — абсолютный эквивалент goroutines и, что уже субъективно, гораздо удобнее async из C#.
Про асинхронность не правда. Корутины есть (называются Fiber), кроме того есть целый фреймвёрк для асинхронного io: vibe.d
Совсем правильный пример конкатенации должен быть таким:
auto s = concat(s1,s2,s3);
, где concat — ленивый диапазон отсюда (https://github.com/ericniebler/range-v3), ну или из std, когда будет.
В этом случае вообще не произойдёт выделения памяти. Понятно, что если дальше нужен быстрый произвольный доступ, то всё равно лучше создать именно строку через range::copy(concat(...), s). Но если потом вы будете читать пару символов или только последовательно, то лучше оставить ленивый диапазон.
Согласен, язык не так популярен на хабре, стоило подробнее описать, зачем вообще писать на D. Восполню пробел парой ссылок на статьи на хабре:
https://habrahabr.ru/post/246623/
https://habrahabr.ru/post/224419/
https://habrahabr.ru/post/197480/
https://habrahabr.ru/post/154345/
Есть динамический биндинг OpenCL. http://code.dlang.org/packages/derelict-cl
Это просто описанный интрефейс к обычному OpenCL. Как хэдеры в сях. Аналогичная штука есть для CUDA
http://code.dlang.org/packages/derelict-cuda
Холиварный вброс, но всё же отвечу. Затем, что быстрее. Бытрее писать и внезапно быстрее работает.
Писать быстрее благодаря обилию алгоритмов, шаблонов, нормальной типизации, безопасности (в виде RAII, контрактов, тестов и сборке мусора) и кучи плюшек (http://dlang.org/ctod.html).
Быстрее работает — немного спорное утверждение. Эквивалентный код чуть медленнее, но на D не пишут как на C. Банальный пример: там, где в C будет массив или копия массива, в D будет ленивый диапазон. По моему опыту замена конкатенации строк на ленивый диапазон даёт прирост скорости 6 раз. Опыт портирования проектов с С или С++ говорит об ускорении результата. Например, в фейсбуке портировали небольшую библиотеку https://code.facebook.com/posts/729709347050548/under-the-hood-building-and-open-sourcing-flint/ D версия работает быстрее.
Чтобы повторить то, что даёт стандартная библиотека диапазонов в D, понадобится куча кода на C, который никто просто не будет писать. Писать быстрый код на D быстрее. Писать обычный код ещё быстрее.
Писать супероптимизированный код на D тоже проще, так как ничто не мешает опуститься до уровня C, пользоваться указателями и всеми низкоуровневыми оптимизациями вплоть до встроенного ассемблера. Вот только мощность шаблонов и прочих фич времени выполнения будет помогать даже на низком уровне и всем этим можно пользоваться.
Ситуаций, в которых D уступает C или C++, очень мало и с каждым днём становится всё меньше.
Бенчмарков не ставил, но не вижу причин, почему он должен отличаться от x86. Бэкенд у компиляторов одинаковый, сами языки примерно на одном уровне производительности, так что +- то же самое.
Где-то вы тут запутались. В целом всё верно, М1 — начальная масса, М2 — конечная. Вот только откуда М1+М3+М4=const? Из соображений, что стартовая масса всегда одинаковая? Это не совсем правда, скорее М1+М3+М4<=const.
По самой формуле (М1+М3+М4)/(М2+М3) = C = e^(V/I) = const, так как e^(V/I) от массы не зависит. Так как М1/М2 = С, то (М3+М4)/М3 = С, отсюда увеличение массы топлива для посадки М3+М4 = С*М3. Это линейная зависимость. Для удельного импульса Мерлина в 2.73 км/с и скорости расстыковки в 3.4 км/с получаем С = e^1.24542 = 3,4744. То есть надо взять дополнительно в три с половиной раза больше топлива, чем нужно для посадки.
Причин много.
Парашют тоже что-то весит и выигрыш получается несущественным. На тех скоростях даже без парашюта аэродинамическое торможение существенно, а ради последних 100 м/с тащить парашют не очень выгодно.
Парашютом сложно управлять. Можно, но сложно. Точность посадки будет хромать.
Маску нужно отработать вертикальную посадку для будущих миссий на Марс.
Вообще-то линейная. image
В показателе экспоненты отношение скорости к удельному импульсу. Масса входит строго линейно. Да, коэффициент для современных ракет около 30, но экспоненты там нет. Чтобы вывести в 2 раза больший груз нужна ракета в 2 раза больше.
Почему-то последнее время эта ошибка очень часто появляется в обуждениях космосмической темы. Не в обиду будет сказано, но похоже большинство комментирующих формулу Циолковского в глаза не видели.
Не согласен с искажением термина coroutine. На компилируемом языке вполне возможны корутины. Тот же boost:coroutine или даже go. Абстракция та же самая: системных потоков мало, реальных потоков исполнения с независимыми стеками много. Это же не просто таски, обрабатываемые пулом потоков, это полноценные корутины, которые можно приостановить на середине, а потом продолжить с того же места. А поток может быть и один.
Однако предложение действительно сырое, не надо тащить чужеродные непродуманные концепции в язык. Похоже MS форсит свою реализацию, даже в свой компилятор поддержку добавили.
Очень рекомендую посмотреть диапазоны в D. В C++ слишком много синтаксического шума, за которым идею не так просто разглядеть. Кроме того для D гораздо больше документации, статей и примеров из реальной жизни. Для начала рекомендую http://www.tutorialspoint.com/d_programming/d_programming_ranges.htm
а так же примеры отсюда: http://dlang.org/phobos/std_range.html и отсюда: http://dlang.org/phobos/std_algorithm_iteration.html

Информация

В рейтинге
3 736-й
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность