Производительность кода Nemerle
От: Аноним  
Дата: 22.02.10 15:01
Оценка:
#Имя: FAQ.nemerle.Performance001
Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?
Re: Производительность кода Nemerle
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 22.02.10 15:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?


Если сравнивать одну и ту же функциональность, то разницы нет — они все компилируются в IL. Использование списков и туплов на больших обьёмах данных может отрицательно сказываться на производительности.
Ce n'est que pour vous dire ce que je vous dis.
Re[2]: Производительность кода Nemerle
От: Аноним  
Дата: 22.02.10 16:00
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, Аноним, Вы писали:


А>>Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?


DR>Если сравнивать одну и ту же функциональность, то разницы нет — они все компилируются в IL. Использование списков и туплов на больших обьёмах данных может отрицательно сказываться на производительности.


Вопрос в какой именно IL он компилируется. Меня немного смущает реализация if, for, foreach и т.д. на макросах...
Re[3]: Производительность кода Nemerle
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 22.02.10 16:13
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Вопрос в какой именно IL он компилируется. Меня немного смущает реализация if, for, foreach и т.д. на макросах...


В макросах, if действительно реализуется через match, а foreach через хвостовую рекурсию, но компилятор превращает match обратно в if, а хвостовую рекурсию в итерацию. Результат тот же, что и в C#.
Ce n'est que pour vous dire ce que je vous dis.
Re[3]: Производительность кода Nemerle
От: hardcase Пират http://nemerle.org
Дата: 22.02.10 16:14
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Вопрос в какой именно IL он компилируется. Меня немного смущает реализация if, for, foreach и т.д. на макросах...


Напиши примитивную программу и посмотри, сомнения отвалятся автоматически.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Производительность кода Nemerle
От: Аноним  
Дата: 22.02.10 16:24
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, Аноним, Вы писали:


А>>Вопрос в какой именно IL он компилируется. Меня немного смущает реализация if, for, foreach и т.д. на макросах...


DR>В макросах, if действительно реализуется через match, а foreach через хвостовую рекурсию, но компилятор превращает match обратно в if, а хвостовую рекурсию в итерацию. Результат тот же, что и в C#.


А какой смысл в двойных преобразованиях туда-обратно?
Re[5]: Производительность кода Nemerle
От: hardcase Пират http://nemerle.org
Дата: 22.02.10 16:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А какой смысл в двойных преобразованиях туда-обратно?


Конструкции foreach/if/while/etc не являются базовыми для языка.
Базовыми являются match и лямбды, макросистема Немерла позволяет реализовать все "классические" конструкции на этих двух примитивах. Отсюда понимаем необходимость в оптимизациях анонимных функциях: инлайнинг, оптимизация хвостовых вызовов.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Производительность кода Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.02.10 19:30
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Если сравнивать одну и ту же функциональность, то разницы нет — они все компилируются в IL. Использование списков и туплов на больших обьёмах данных может отрицательно сказываться на производительности.


Списков — да, кортежей — нет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Производительность кода Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.02.10 19:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос в какой именно IL он компилируется. Меня немного смущает реализация if, for, foreach и т.д. на макросах...


Макросы весьма гибкая вещь, так что этого бояться не надо. А вообще, некоторые шороховатости сглаживает джит- и пре-компилятор дотнета, так что в на практике проблем с производительностью нет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Производительность кода Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.02.10 19:40
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Базовыми являются match и лямбды,


Уточню немного. Базовыми являются не лямбды, а локальные функции. Лябды выражаются уже через них.
x => x

переписывается макросом в:
fun(x) { x }

а этот синтаксис переписывается компилятором во что-то воде:
{ 
  tempFanc(x){ x }
  tempFanc
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Производительность кода Nemerle
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 22.02.10 20:38
Оценка:
Здравствуйте, VladD2, Вы писали:

DR>>Если сравнивать одну и ту же функциональность, то разницы нет — они все компилируются в IL. Использование списков и туплов на больших обьёмах данных может отрицательно сказываться на производительности.


VD>Списков — да, кортежей — нет.


Я использую Немерле для обработки графики и мой опыт показывает, что кортежы удобные, но очень дорогие, особенно с более чем тремя элементами. Простой тест:

using System.Console;
using System.Diagnostics;

module Main
{
    public Main() : void
    {
        def n = 10_000_000;
        TimeReturn(n);
        TimeSet(n);
    }

    private TimeSet(n : int) : void
    {
        def watch = Stopwatch.StartNew();
        mutable acc;
        repeat (n)
        {
            mutable a, b, c, d;
            Set(out a, out b, out c, out d);
            acc += a; acc += b; acc += c; acc += d;
        }
        watch.Stop();
        WriteLine($"Set: $(watch.ElapsedMilliseconds)");
    }

    private TimeReturn(n : int) : void
    {
        def watch = Stopwatch.StartNew();
        mutable acc;
        repeat (n)
        {
            def (a, b, c, d) = Return4();
            acc += a; acc += b; acc += c; acc += d;
        }
        watch.Stop();
        WriteLine($"Return: $(watch.ElapsedMilliseconds)");
    }

    private Set(a : out int, b : out int, c : out int, d : out int) : void
    {
        a = 1;
        b = 2;
        c = 3;
        d = 4;
    }

    private Return4() : int * int * int * int
    {
        (1, 2, 3, 4);
    }
}

Return: 159
Set: 76

Ce n'est que pour vous dire ce que je vous dis.
Re: Производительность кода Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.02.10 20:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?


Пока что программы написанные на Nemerle обычно бывают быстрее чем на C# или VB, потому что пока что программисты выбирающие Nemerle — это обычно уже весьма квалифицированные специалисты .

Если говорить серьезно, то производительность софта написанного на дотнет-языках больше зависит от знаний авторов кода.

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

Кроме того надо понимать, что функциональные абстракции не бесплатны. Замыкания создают неявно создают объекты, а вызов функции через ссылку приблизительно аналогичен виртуальному вызову. Но эти же затраты есть и в C#/VB когда используются делегаты и замыкания. Более того в Nemerle выполняются некоторые оптимизации (инлайнинг и устранение концевой рекурсии), которые делают функциональный код на Nemerle более быстрым нежели аналогиный код на C#/VB.

Макросы же не несут угрозу производительности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Производительность кода Nemerle
От: hardcase Пират http://nemerle.org
Дата: 22.02.10 20:53
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Я использую Немерле для обработки графики и мой опыт показывает, что кортежы удобные, но очень дорогие, особенно с более чем тремя элементами.


Кортежи 2-х и 3-х элементные — это структуры. Остальные — классы. Отсюда очевиден оверхед их использования.
В .NET 4 тоже есть кортежи, они вообще все — классы, недавно обсуждалось
Автор: Мишень-сан
Дата: 16.02.10
кстати.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: Производительность кода Nemerle
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 22.02.10 20:59
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Кортежи 2-х и 3-х элементные — это структуры. Остальные — классы. Отсюда очевиден оверхед их использования.


Правильно. Это необходимо помнить, чтобы понимать стоимость их использования и изменение семантики с value на reference при переходе на четыре элемента.
Ce n'est que pour vous dire ce que je vous dis.
Re[6]: Производительность кода Nemerle
От: hardcase Пират http://nemerle.org
Дата: 22.02.10 21:06
Оценка: +1
Здравствуйте, Don Reba, Вы писали:

DR>Правильно. Это необходимо помнить, чтобы понимать стоимость их использования и изменение семантики с value на reference при переходе на четыре элемента.


У меня такая философия — если элементов больше чем три, то наверно стоит задуматься об отдельном типе данных (какой-нибудь Record) для этой кухни, иначе через некоторое время будет сложно держать в голове порядок следования элементов.
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Производительность кода Nemerle
От: hi_octane Беларусь  
Дата: 22.02.10 21:16
Оценка:
А>Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?

По итогам реального проекта — производительность такая-же. Что в C#3 лямбды или linq, что в Nemerle лямбды (они же локальные функции) или linq — переписываются в IL сходным образом и ресурсов кушают одинаково. Любая достаточно сложная логика на match переписанная на C# будет кушать больше ресурсов — из-за того что оптимально переписать серьёзный match врукопашную — это убить того кому это потом поддерживать

У нас было требование в одной из частей проекта обеспечить время реакции в 20 ms от получения данных из сети до ответа. Уложились, причём оптимизаций связанных с тем что язык тормозил не было, оптимизировали, в основном, наши алгоритмы.
nemerle скорость оптимизация
Re[4]: Производительность кода Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.02.10 22:37
Оценка: +1
Здравствуйте, Don Reba, Вы писали:

DR>Я использую Немерле для обработки графики и мой опыт показывает, что кортежы удобные, но очень дорогие, особенно с более чем тремя элементами. Простой тест:...


Это не очень корректное сравнение.

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

Во-вторых, практически у всех типов данных есть варианты использования приводящих к большей или меньшей производительности. Вот твой пример в который добавлен еще один вариант — передача данных через поля объекта:
using System.Console;
using System.Diagnostics;

class Data
{
  public mutable a : int;
  public mutable b : int;
  public mutable c : int;
  public mutable d : int;
}

module Main
{
    public Main() : void
    {
        def n = 10_000_000;
        TimeReturn(n);
        TimeSet(n);
        TimeObj(n);
        _ = ReadLine();
    }

    private TimeSet(n : int) : void
    {
        def watch = Stopwatch.StartNew();
        mutable acc;
        repeat (n)
        {
            mutable a, b, c, d;
            Set(out a, out b, out c, out d);
            acc += a; acc += b; acc += c; acc += d;
        }
        watch.Stop();
        WriteLine($"Set: $(watch.ElapsedMilliseconds)");
    }

    private TimeReturn(n : int) : void
    {
        def watch = Stopwatch.StartNew();
        mutable acc;
        repeat (n)
        {
            def (a, b, c, d) = Return4();
            acc += a; acc += b; acc += c; acc += d;
        }
        watch.Stop();
        WriteLine($"Return: $(watch.ElapsedMilliseconds)");
    }

    private TimeObj(n : int) : void
    {
        def watch = Stopwatch.StartNew();
        mutable acc;
        def data = Data();
        repeat (n)
        {
            Obj(data);
            acc += data.a; acc += data.b; acc += data.c; acc += data.d;
        }
        watch.Stop();
        WriteLine($"Obj: $(watch.ElapsedMilliseconds)");
    }
    
    private Set(a : out int, b : out int, c : out int, d : out int) : void
    {
        a = 1;
        b = 2;
        c = 3;
        d = 4;
    }
    
    private Obj(obj : Data) : void
    {
        obj.a = 1;
        obj.b = 2;
        obj.c = 3;
        obj.d = 4;
    }

    private Return4() : int * int * int * int
    {
        (1, 2, 3, 4);
    }
}


Вариант Obj где-то вдвое быстрее нежели передача данных через out-параметры. Значит ли, что out-параметры медленны и их не стоит применять? Конечно нет! Просто для данного варианта использования передача данных через объект несколько эффективнее. Но для других случаев это будет не так.

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

В-третьих, как и большинство тестов — этот показывает относительную разницу двух операций. Если функция не полная пустышка, а выполняет некоторые действия, то на их фоне затраты скорее всего не будет видно даже в микроскоп. Приведенный тест выполняется 10 миллионов раз, а результат — доли секунды.

В-четвертых, многое зависит от того какие данные передаются.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Производительность кода Nemerle
От: Аноним  
Дата: 23.02.10 20:41
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Аноним, Вы писали:


А>>Подскажите, какова разница в производительности кода Nemerle в сравнении с C#, VB и т.д?


VD>Пока что программы написанные на Nemerle обычно бывают быстрее чем на C# или VB, потому что пока что программисты выбирающие Nemerle — это обычно уже весьма квалифицированные специалисты .


VD>Если говорить серьезно, то производительность софта написанного на дотнет-языках больше зависит от знаний авторов кода.


VD>Если сравнивать Nemerle с другими дотнет-языками, то в целом он порождает аналогичный код. Кое-какие проблемы могут быть вызваны связаны с особенностями реализации match. Но это касается только match-ей в которых переход происходит по большому числу литеральных значений (например, целых числе). Обычно такие match-и встречаются в сгенерированном коде вроде парсеров созданных с помощью построителей парсеров использующие конечные автоматы с большими таблицами.


VD>Кроме того надо понимать, что функциональные абстракции не бесплатны. Замыкания создают неявно создают объекты, а вызов функции через ссылку приблизительно аналогичен виртуальному вызову. Но эти же затраты есть и в C#/VB когда используются делегаты и замыкания. Более того в Nemerle выполняются некоторые оптимизации (инлайнинг и устранение концевой рекурсии), которые делают функциональный код на Nemerle более быстрым нежели аналогиный код на C#/VB.


VD>Макросы же не несут угрозу производительности.


Написал тестовое приложение, производящее пузырьковую сортировку на C#, VB и Nemerle. В результате, на массиве из 10000 целых, код Nemerle выполнялся почти на 30% дольше чем аналог на C#.
Хотелось бы понять, я не корректно реализовал сортировку на Nemerle, или он действительно НЕ БЫСТР?
Тестовый проект
Re[3]: Производительность кода Nemerle
От: hardcase Пират http://nemerle.org
Дата: 23.02.10 23:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Написал тестовое приложение, производящее пузырьковую сортировку на C#, VB и Nemerle. В результате, на массиве из 10000 целых, код Nemerle выполнялся почти на 30% дольше чем аналог на C#.

А>Хотелось бы понять, я не корректно реализовал сортировку на Nemerle, или он действительно НЕ БЫСТР?
А>Тестовый проект


Начать надо с того, что привести код в порядок (например для int-ов не использовать CompareTo):
public BubbleSort[T](items : array[T], left : int,  right : int) : void where T : IComparable[T]
{
    for (mutable i = left + 1; i <= right; i++)
        for (mutable j = right; j >= i; j--)
            when (items[j - 1].CompareTo(items[j]) > 0)
                items[j] <-> items[j - 1];
}

public BubbleSortInt(items : array[int], left : int,  right : int) : void
{
    for (mutable i = left + 1; i <= right; i++)
        for (mutable j = right; j >= i; j--)
            when (items[j - 1] > (items[j]))
                items[j] <-> items[j - 1];
}


Ответ дает рефлектор:
public static void BubbleSortInt(int[] items, int left, int right)
{
    int index = 0;
    int num2 = 0;
    for (num2 = left + 1; ((num2 <= right) ? 1 : 0) != 0; num2++)
    {
        index = right;
        while (true)
        {
            if (((index >= num2) ? 1 : 0) == 0)
            {
                break;
            }
            if (((items[index - 1] > items[index]) ? 1 : 0) != 0)
            {
                int num3 = index - 1;
                int num4 = items[index];
                items[index] = items[num3];
                items[num3] = num4;
            }
            index--;
        }
    }
}


Видна ненужная проверка с тернарным оператором. Впрочем, даже с таким тормозом производительность практически эквивалентна VB.NET. По хорошему стоит посмотреть на Mono, а также попробовать скомпилировать примеры вручную, но щас уже поздно совсем.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Производительность кода Nemerle
От: Аноним  
Дата: 24.02.10 06:54
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, Аноним, Вы писали:


А>>Написал тестовое приложение, производящее пузырьковую сортировку на C#, VB и Nemerle. В результате, на массиве из 10000 целых, код Nemerle выполнялся почти на 30% дольше чем аналог на C#.

А>>Хотелось бы понять, я не корректно реализовал сортировку на Nemerle, или он действительно НЕ БЫСТР?
А>>Тестовый проект


H>Начать надо с того, что привести код в порядок (например для int-ов не использовать CompareTo):

H>
H>public BubbleSort[T](items : array[T], left : int,  right : int) : void where T : IComparable[T]
H>{
H>    for (mutable i = left + 1; i <= right; i++)
H>        for (mutable j = right; j >= i; j--)
H>            when (items[j - 1].CompareTo(items[j]) > 0)
H>                items[j] <-> items[j - 1];
H>}

H>public BubbleSortInt(items : array[int], left : int,  right : int) : void
H>{
H>    for (mutable i = left + 1; i <= right; i++)
H>        for (mutable j = right; j >= i; j--)
H>            when (items[j - 1] > (items[j]))
H>                items[j] <-> items[j - 1];
H>}
H>


H>Ответ дает рефлектор:

H>
H>public static void BubbleSortInt(int[] items, int left, int right)
H>{
H>    int index = 0;
H>    int num2 = 0;
H>    for (num2 = left + 1; ((num2 <= right) ? 1 : 0) != 0; num2++)
H>    {
H>        index = right;
H>        while (true)
H>        {
H>            if (((index >= num2) ? 1 : 0) == 0)
H>            {
H>                break;
H>            }
H>            if (((items[index - 1] > items[index]) ? 1 : 0) != 0)
H>            {
H>                int num3 = index - 1;
H>                int num4 = items[index];
H>                items[index] = items[num3];
H>                items[num3] = num4;
H>            }
H>            index--;
H>        }
H>    }
H>}
H>


H>Видна ненужная проверка с тернарным оператором. Впрочем, даже с таким тормозом производительность практически эквивалентна VB.NET. По хорошему стоит посмотреть на Mono, а также попробовать скомпилировать примеры вручную, но щас уже поздно совсем.


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