All streams
Search
Write a publication
Pull to refresh
34
0
Антон Гуща @NCrashed

User

Send message
Примеры для mercury выглядят элегантно, но, конечно, это простые демки. У вайба, как у большого проекта, появился один недостаток — там черт ногу сломит разбираться во многокилометровых модулях. Вот mercury хорошо демонструет ядро асинхронного IO.
Ух ты, наконец-то оформили в отдельную страничку то, что приходилось собирать по новостной группе.

Итого вы работаете с vibe.d? Сопрограммы, правда, я там не видел в чистом виде. Я его использую для синхронизации рукописных кешей для бд, очень уж удобно устроен rest-api. Также все приглядываюсь к SCTP, если реализовать его сокеты для vibe.d, то можно будет не велосипедить на UDP стриминг голоса/видео и игровых данных.
Ожидал увидеть еще рекомендации по написанию bindings, местами бывают нетривиальные или неочевидные проблемы. Как например, глобальные переменные должны экспортированы вот так:
extern(C) extern __gshared int my_global_int;
Пока на написание такого труда я не готов. Из уже имеющихся книг могу порекомендовать:
1. D Cookbook — свежее собрание приемов, специфичных для D.
2. The D Programming Language (перевод), написана в 2010, поэтому многие примеры могут без пинка не заработать.
Проводились бенчи и с другими веб-серверами, правда довольно давно.
Логика такова: если функцию вызывать в контексте, когда она может быть выполнена только в compile-time, то она гарантированно выполнится в compile-time.

Т.е.:
int res = X(some_var);  // run-time
auto res = X(some_var); // run-time
enum res = X(some_var); // compile-time only
immutable res = X(some_var); // compile-time или run-time, если не может выполниться в compile-time
static res = X(some_var);    // compile-time или run-time, если не может выполниться в compile-time


А явно указать какие функции inline, какие нет — нельзя. Оптимизатор сам решает этот момент. Помню у GDC была специальная pragma для forceinline, но в общем случае такой фичи нет.
Напрямую автора не спрашивал, но заметил его желание собирать все на ddili.org. Идеальным был бы вариант github + деплой на gh-pages или вики движок.
Такое утверждение я видел в период перехода с D1 на D2, тогда, да, было обоснованно. Сейчас это хорошо продуманный язык с удобной стандартной библиотекой. Можно на нем писать как на Java или Python и никогда не опускаться на системный уровень. Учитывая очень быструю компиляцию, я уже давно использую D в скриптах.
Можно передавать как аргументы шаблона все что угодно (что можно посчитать в compile-time): POD типы, лямбды, функции, классы, структуры, шаблоны, и даже целиком expressions.

Аргумент — кастомный класс:
import std.stdio;

class A
{
    string field = "Hello";
}

class B(T)
{
    T sub = new T();
}

void main()
{
    auto b = new B!A();
    writeln(b.sub.field);
}
Самый бурный проект — серверный фреймворк vibe.d, который по производительности обгоняет node.js.

Да, хорошая идея, пост о средствах метапрограммирования в D + небольшое сравнение с constexpr и выводом типов (оно различается с C++14).
Автор оригинала пытался охватить еще и новичков. Пока получается слишком verbose, но далее должно пойти интереснее, так как будут рассматриваться неочевидные моменты.

Может быть сделать кусочный перевод и пропустить совсем уж начальный материал?
Проверил на ~master (v2.066-devel-e3bada6) — тоже все нормально.

P.S. Грабли: array.clear; не очищает мапу, а вызывает alias для object.destroy. В 2.066 alias стал deprecated. Чтобы очистить мапу можно либо присвоить ей свежесозданную или пройтись по всем ключам и удалить их.
Так точно, в обоих случаях изменения будут видны вне функции, разницы нет. Я привел пример с add2 только для демонстрации тонкости того, что ассоциативные массивы всегда передаются по ссылке.
Если ассоциативные массивы копировались бы при передаче в функцию, то последний writeln вывел ["o":2], изменялся бы локальный ассоциативный массив внутри функции. Такое поведение имеют статические массивы:
// статический массив
void add(int[5] array)
{
    // заполним весь массив значением 42
    array[] = 42; 
}

// динамический массив
void add(int[] array)
{
    // заполним весь массив значением 42
    array[] = 42; 
}

void main()
{
    int[5] array = [1, 2, 3, 4, 5];
    add(array);
    writeln(array); // [1, 2, 3, 4, 5]
    add(array[]);
    writeln(array); // [42, 42, 42, 42, 42]
}


Если для статических массивов нужно ссылочное поведение, то к типу аргумента добавляют ref. Также важный момент add(array[]), через оператор [ ] (оператор для slicing) мы получаем динамический массив, который внутри ссылается на данные статического массива.
Хм, я такого поведения в 2.065 не обнаружил (а если оно есть в ~master, то определенно нужен regression issue):
import std.stdio;
import std.datetime;

void dos(bool[float] array)
{
    array[double.nan] = true;
}

void main()
{
    bool[float] array;
    auto test1 = benchmark!(() => dos(array))(100_000);   array.clear;
    auto test2 = benchmark!(() => dos(array))(1000_000);  array.clear;
    auto test3 = benchmark!(() => dos(array))(10000_000);
    
    writeln(test1[0].msecs / cast(double) 100_000);   // 0.00038
    writeln(test2[0].msecs / cast(double) 1000_000);  // 0.000307
    writeln(test3[0].msecs / cast(double) 10000_000); // 0.0002816
}
В D ассоциативные массивы ведут себя как объекты:
import std.stdio;

// Возврат из функции
int[string] add(int[string] array)
{
    array["add"] = 1;
    return array;
}

// Измененение будет видно вне функции
void add2(int[string] array)
{
    array["add"] = 1;
}

void main()
{
    writeln(add(["o": 2])); // ["add":1, "o":2]
    writeln(add(["c": 4])); // ["c":4, "add":1]
    
    // еще вариант записи
    writeln(["o": 2].add); // ["add":1, "o":2]
    // или даже так
    ["o": 2].add.writeln; // ["add":1, "o":2]
    
    // Демонстрация поведения by-reference
    int[string] arr = ["o": 2];
    add2(arr);
    writeln(arr); // ["add":1, "o":2]
}

Проблем с GC быть не должно, если ссылок на ассоциативны массив больше нет, то он удаляется.
D REPL:
D> bool[double] map;
=> map
D> map[0.0/0.0] = true;
D> map.keys
=> [-nan]
D> map[-double.nan]
=> true


Для хеширования используется TypeInfo (TypeInfo для классов переопределяет поведение getHash), соответственно:
D> auto val = double.nan;
=> val
D> typeid(double).getHash(&val)
=> 360911136610280172
Для масштаба еще один замер версии на C:
время сек: 9.19
память: 564
В D ассоциативные массивы встроены в рантайм и полагаются на GC. Реализованы они как объекты, т.е. чтобы освободить память ассоциативного массива нужно обнулить все ссылки на него, а также можно вызывать метод clear для очистки внутренностей а.массива.
Rust (Исходник):
$ rustc --version
rustc 0.11.0-pre (6266f64 2014-06-06 23:06:35 -0700)
host: x86_64-unknown-linux-gnu
$ rustc nbody.rs --opt-level 3


Все файлы, относящиеся к бенчмарку D лежат на гитхабе.

DMD:
$ dmd --help
DMD64 D Compiler v2.065
$ dmd -ofnbody source/nbody.d -release -inline -noboundscheck -O


GDC (один из последних коммитов):
$ gdc --version
gdc (GCC) 4.8.2
$ gdc -onbody source/nbody.d -O3 -frelease


LDC2:
$ ldc2 --version
LDC - the LLVM D compiler (0.13.0-beta1):
  based on DMD v2.064 and LLVM 3.4.1
  Default target: x86_64-unknown-linux-gnu
$ ldc2 -ofnbody source/nbody.d -release -O3


Замерял следующим образом (далее таблица по 10 замеров для каждого билда):
/usr/bin/time --verbose ./nbody 50000000


Таблица замеров (время в секундах):


Выводы: Rust и D примерно одинаковы по производительности. Для D лучше использовать GDC, когда важна скорость.

Конфигурация машины:
Intel® Core(TM)2 Quad CPU Q9400 @ 2.66GHz
3.14.4-200.fc20.x86_64

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity