Re[13]: Минутка WTF-19: Catch me if you can
От: vdimas Россия  
Дата: 20.03.17 21:05
Оценка:
Здравствуйте, Sinix, Вы писали:

S>И при этом чужой опыт хождения по граблям ты отметаешь не глядя


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


S>Ну, т.е. чтоб хоть как-то нормально обсуждать, надо сначала расписать совсем базовые вещи, да ещё и добиться, чтоб ты с ними согласился, а не продолжал гнуть своё. Вот это-то мне как раз делать и влом.


Не надо ничего расписывать словами.
Я тебе показал в листинге, что твой тест не тестирует того, что ты планировал тестировать.
Остальное — лирика.
Re[13]: Минутка WTF-19: Catch me if you can
От: vdimas Россия  
Дата: 20.03.17 21:26
Оценка: 26 (1)
Здравствуйте, Sinix, Вы писали:

S>Смысл в следующем: в RyuJit одно поломали другое починили здорово подкрутили эвристики для loop hoisting, т.е. то самое вытаскивание обращения к полю за тело цикла.

S>И, как результат, для вещей, которые JIT умеет оптимизировать (обсуждаемый случай — как раз из них)

В общем случае такие оптимизации невозможны.
Они как раз, сцуко, только в синтетических тестах и происходят.
Это по опыту ежедневной работы с куда как более мощным офлайн-оптимизатором С++, который еще больше кода выкидывает нафик.

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

Надо писать ручной тест и в коде сделать несколько "отвлекающих манёвров", например, симулировать доступ к тестируемому объекту из разных потоков, но во время выполнения тела теста объект не трогать. Тогда джит не сможет сделать никаких предположений и вынужден будет обращаться к поля объекта "честно", т.е. без кеширования их в начале цикла. Потому что именно такова семантика средней программы.


S>смысла заморачиваться с структурой нет — получаем 5%-10% выигрыша


Выигрыш там в 3-4 раза, это на реальных дотнетных проектах (VoIP, HFT).
В синтетических тестах выигрыш всегда чуть меньше выходит — примерно в 2.5 раза.
Потому что синтетический тест измеряет профит лишь от одного уровня вложенности.
Если таких уровней вложенности более одного, то профит умножается для каждого уровня.
В среднем проекте обычно присутствует некий высокоуровневый-объект-обертка над неким List<>, тот в свою очередь тоже является оберткой над Array. Т.е. уровень косвенности минимум 2, теоретический прирост должен быть в ~6.25 раз, но фактически помимо беготни по графу происходят еще вычисления, поэтому реальный эффект на боевых проектах где-то 3-4 раза.
В нейтиве такие же цифры получаются, что характерно.
Т.е. дотнет тут не на уникальной позиции.


S>в лучшем случае в обмен на лишний боксинг в типовом случае работы с linq.


Лишний боксинг тоже зло, ес-но.
Именно поэтому я предлагал рисовать свои "точки входа" для классов-расширений типа Enumerable.
Что там будет происходить с value-типами-коллекциями в Linq-выражениях в этом его expression-синтаксисе, если честно, не в курсе, еще не экспериментировал. Что-то мне подсказывает, что там, где производительность важна, там этот синтаксис не используют.
Re[14]: Не понимая и половины
От: vdimas Россия  
Дата: 20.03.17 22:54
Оценка:
Здравствуйте, samius, Вы писали:

S>>Без возможности вызывать методы перчислителя напрямую из метода sum, эта чушь не стоит обсуждения.


S>как-то так

S>
S>        static int Sum<TColl, TEnumerator>(TColl coll)
S>            where TColl : IMyEnumerable<TEnumerator>
S>            where TEnumerator : IEnumerator<int>
S>


А рядом для static double Sum<...> where TEnumerator : IEnumerator<double>? ))
Re[14]: Не понимая и половины
От: samius Япония http://sams-tricks.blogspot.com
Дата: 21.03.17 03:56
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Перечислитель будет доступен лишь через методы интерфейса IEnumerator<int>. А значит — все равно отбоксится.


V>Не отбоксится. ))


Ты прав, не отбоксится. Метод, возвращающий struct Enumerator из твоего Sum даже не будет вызван. Так чего ради нужна такая "оптимизация"?
Re[15]: Не понимая и половины
От: samius Япония http://sams-tricks.blogspot.com
Дата: 21.03.17 04:00
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


V>А рядом для static double Sum<...> where TEnumerator : IEnumerator<double>? ))

Если мне понадобится такая фигня ради того что бы ехать, то я не побрезгую назвать методы SumInt и SumDouble.
Re[9]: "Небезопасный" код
От: Privalov  
Дата: 21.03.17 06:55
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Не, ну сколько можно на эти грабли наступать-то??? Басика с весёлой троицей null, empty и nothing мало?


В Васике существовало мощнейшее средство: расставить в программе on error resume next и уволиться. Правда, Васик от помоечки оно не спасло.
Re[16]: Не понимая и половины
От: vdimas Россия  
Дата: 21.03.17 13:02
Оценка:
Здравствуйте, samius, Вы писали:

V>>А рядом для static double Sum<...> where TEnumerator : IEnumerator<double>? ))

S>Если мне понадобится такая фигня ради того что бы ехать, то я не побрезгую назвать методы SumInt и SumDouble.

+100500
Re[15]: Не понимая и половины
От: vdimas Россия  
Дата: 21.03.17 13:05
Оценка:
Здравствуйте, samius, Вы писали:

S>>>Перечислитель будет доступен лишь через методы интерфейса IEnumerator<int>. А значит — все равно отбоксится.

V>>Не отбоксится. ))
S>Ты прав, не отбоксится. Метод, возвращающий struct Enumerator из твоего Sum даже не будет вызван. Так чего ради нужна такая "оптимизация"?

Ради уменьшения уровня косвенности:
            Method |          Mean |    StdDev | Scaled | Scaled-StdDev |
------------------ |-------------- |---------- |------- |-------------- |
    TestRefWrapper | 2,345.5918 us | 7.4546 us |   1.00 |          0.00 |
 TestStructWrapper |   961.5590 us | 6.0217 us |   0.41 |          0.00 |

Разница ~2.5 раза.
Re[16]: Не понимая и половины
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.03.17 13:52
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>>>Перечислитель будет доступен лишь через методы интерфейса IEnumerator<int>. А значит — все равно отбоксится.

V>>>Не отбоксится. ))
S>>Ты прав, не отбоксится. Метод, возвращающий struct Enumerator из твоего Sum даже не будет вызван. Так чего ради нужна такая "оптимизация"?

V>Ради уменьшения уровня косвенности:

V>
V>            Method |          Mean |    StdDev | Scaled | Scaled-StdDev |
V>------------------ |-------------- |---------- |------- |-------------- |
V>    TestRefWrapper | 2,345.5918 us | 7.4546 us |   1.00 |          0.00 |
V> TestStructWrapper |   961.5590 us | 6.0217 us |   0.41 |          0.00 |
V>

V>Разница ~2.5 раза.

При этом у тебя для 64

Результаты для x64 :
Method | Mean | StdDev | Scaled | Scaled-StdDev |
------------------ |-------------- |---------- |------- |-------------- |
TestRefWrapper | 816.8624 us | 3.9044 us | 1.00 | 0.00 |
TestStructWrapper | 774.8507 us | 1.6223 us | 0.95 | 0.00 |


Никаких ~2.5 раза.

Попробуй .Net Core
и солнце б утром не вставало, когда бы не было меня
Re[17]: Не понимая и половины
От: vdimas Россия  
Дата: 21.03.17 14:15
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>При этом у тебя для 64

S>Результаты для x64 :
S> Method | Mean | StdDev | Scaled | Scaled-StdDev |
S>------------------ |-------------- |---------- |------- |-------------- |
S> TestRefWrapper | 816.8624 us | 3.9044 us | 1.00 | 0.00 |
S> TestStructWrapper | 774.8507 us | 1.6223 us | 0.95 | 0.00 |

Садись, два.
Для x64 исходный тест не работоспособен.


S>Никаких ~2.5 раза.


Такие же точно.


S>Попробуй .Net Core


Попробуй сам.
Re[18]: Не понимая и половины
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.03.17 14:26
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Serginio1, Вы писали:


S>>При этом у тебя для 64

S>>Результаты для x64 :
S>> Method | Mean | StdDev | Scaled | Scaled-StdDev |
S>>------------------ |-------------- |---------- |------- |-------------- |
S>> TestRefWrapper | 816.8624 us | 3.9044 us | 1.00 | 0.00 |
S>> TestStructWrapper | 774.8507 us | 1.6223 us | 0.95 | 0.00 |

V>Садись, два.

V>Для x64 исходный тест не работоспособен.

Так это твои результаты http://rsdn.org/forum/dotnet/6731352.1
Автор: vdimas
Дата: 20.03.17

Ты самокритичен оказывается

S>>Никаких ~2.5 раза.


V>Такие же точно.


По таблице чего то не видно.
S>>Попробуй .Net Core

V>Попробуй сам.

То есть тебе в лом самому разобраться? ОК
и солнце б утром не вставало, когда бы не было меня
Re[19]: Не понимая и половины
От: vdimas Россия  
Дата: 21.03.17 15:50
Оценка:
Здравствуйте, Serginio1, Вы писали:

V>>Садись, два.

V>>Для x64 исходный тест не работоспособен.
S>Так это твои результаты http://rsdn.org/forum/dotnet/6731352.1
Автор: vdimas
Дата: 20.03.17


Но ты дальше таблицы с результатами не читал, надо понимать?


S>Ты самокритичен оказывается


Сначала дочитай пост по ссылке до конца, потом возвращайся.


S>По таблице чего то не видно.


По таблице невалидные результаты.
Потому что сам тест невалиден.


V>>Попробуй сам.

S>То есть тебе в лом самому разобраться? ОК

Я как раз дал ассембленый листинг с подробнейшим разбором происходящего.
А ты опять хамишь игнором аргументов оппонента.
Re[16]: Не понимая и половины
От: samius Япония http://sams-tricks.blogspot.com
Дата: 21.03.17 16:26
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Ты прав, не отбоксится. Метод, возвращающий struct Enumerator из твоего Sum даже не будет вызван. Так чего ради нужна такая "оптимизация"?


V>Ради уменьшения уровня косвенности:

V>
V>            Method |          Mean |    StdDev | Scaled | Scaled-StdDev |
V>------------------ |-------------- |---------- |------- |-------------- |
V>    TestRefWrapper | 2,345.5918 us | 7.4546 us |   1.00 |          0.00 |
V> TestStructWrapper |   961.5590 us | 6.0217 us |   0.41 |          0.00 |
V>

V>Разница ~2.5 раза.

За счет чего разница будет в 2.5 раза, если ты уменьшил уровень косвенности лишь у одного вызова на забег по коллекции, в то время как 2*n вызовов осталось ровно с той же косвенностью, как и при передаче интерфейса?
Re[20]: Не понимая и половины
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.03.17 16:30
Оценка: :)
Здравствуйте, vdimas, Вы писали:


V>Я как раз дал ассембленый листинг с подробнейшим разбором происходящего.

V>А ты опять хамишь игнором аргументов оппонента.

Это я хамлю???
Все таки иногда нужно смотреть в зеркало.
Зачем приводишь невалидные данные?
и солнце б утром не вставало, когда бы не было меня
Re[14]: Минутка WTF-19: Catch me if you can
От: Sinix  
Дата: 21.03.17 16:35
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>В общем случае такие оптимизации невозможны.

V>В среднем проекте обычно присутствует некий высокоуровневый-объект-обертка над неким List<>, тот в свою очередь тоже является оберткой над Array. Т.е. уровень косвенности минимум 2, теоретический прирост должен быть в ~6.25 раз, но фактически помимо беготни по графу происходят еще вычисления, поэтому реальный эффект на боевых проектах где-то 3-4 раза.

Угу, кажись, я наконец понял про что ты говоришь.
Речь про попытку совместить обработку кучи однородных данных в hotpath и сложные структуры данных над plain-массивом, так?
Как-то совсем частный сценарий получается. Если честно, я бы такое вытаскивал на плюсы сразу. По крайней мере пока нормальный оптимизатор не завезут.
В дотнете как правило в hotpath используется массив напрямую. Именно чтоб не напарываться на "а сегодня JIT не смог".

Но это справедливо именно для тшательно вылызанного perf-critical кода. Для всего остального никто с тонной вложенных структур заморачиваться не будет, возвращаемся к результатам выше
Re[17]: Не понимая и половины
От: vdimas Россия  
Дата: 21.03.17 21:33
Оценка:
Здравствуйте, samius, Вы писали:

V>>Ради уменьшения уровня косвенности:

V>>
V>>            Method |          Mean |    StdDev | Scaled | Scaled-StdDev |
V>>------------------ |-------------- |---------- |------- |-------------- |
V>>    TestRefWrapper | 2,345.5918 us | 7.4546 us |   1.00 |          0.00 |
V>> TestStructWrapper |   961.5590 us | 6.0217 us |   0.41 |          0.00 |
V>>

V>>Разница ~2.5 раза.

S>За счет чего разница будет в 2.5 раза, если ты уменьшил уровень косвенности лишь у одного вызова на забег по коллекции, в то время как 2*n вызовов осталось ровно с той же косвенностью, как и при передаче интерфейса?


В этой таблице результаты джита x86. Очевидно, что этот джит не провел для тестового цикла оптимизацию, т.е. не выкинул из его тела обращение к полям объекта "честным образом", т.е. через переменную, указанную в исходнике теста.
Re[15]: Минутка WTF-19: Catch me if you can
От: vdimas Россия  
Дата: 21.03.17 21:47
Оценка: 52 (1)
Здравствуйте, Sinix, Вы писали:

S>Угу, кажись, я наконец понял про что ты говоришь.

S>Речь про попытку совместить обработку кучи однородных данных в hotpath и сложные структуры данных над plain-массивом, так?

Почти так. Дело не только в массиве.
Если объекты агрегируют друг друга, то в плюсах это обычно происходит естественным образом — по значению.
Отсюда "бесплатность" абстракций.

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


S>Как-то совсем частный сценарий получается.


Это общий сценарий. Я как-то специально подсчитывал, у меня на сотни прикладных классов было только 5 объектов верхнего уровня, создаваемых явно по new и всего два объекта для передачи их м/у потоками.

Т.е., когда такая возможность располагать объекты в памяти друг друга идёт изкаробки, то ей активно пользуются при разработке архитектуры, ес-но.


S>В дотнете как правило в hotpath используется массив напрямую. Именно чтоб не напарываться на "а сегодня JIT не смог".


Угу, в Джава тоже.
Причем, в дотнете хоть сопряжение с нейтивом, считай, бесплатное, поэтому такой код, действительно, часто пишут как внешний или линкуемый модуль на плюсах. А в Джаве осилить JNI — тот еще трах и не всегда даёт профит, особенно при частых вызовах. Поэтому берут массив байт и ручным образом в нем рисуют сложные структуры (для HFT, например), т.е. ручками выполняют работу некоего нейтивного компилятора. ))


S>Но это справедливо именно для тшательно вылызанного perf-critical кода. Для всего остального никто с тонной вложенных структур заморачиваться не будет, возвращаемся к результатам выше


Ну да. Считанные единицы объектов верхнего уровня могут быть не заморочены. ))
Re[12]: Junk in — junk out
От: Qbit86 Кипр
Дата: 21.03.17 22:50
Оценка:
Здравствуйте, vdimas, Вы писали:

V>1. Методы-расширения, как и обычные методы, не включают в свою сигнатуру ограничения.


Ок, но это не относится к тезису «вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.»

Давай рассмотрим конкретную (в меру извращённую) реализацию упомянутого суммирования, с дженериком и констрейнтами:
internal static class Foo<TElement>
{
    internal static TElement Sum<TEnumerable, TMonoid>(TEnumerable items, TMonoid monoid)
        where TEnumerable : IEnumerable<TElement>
        where TMonoid : IMonoid<TElement>
    {
        // При сравнении объекта value-типа с литералом `null`
        // не будет боксинга в рантайме согласно C# Specification, section 7.10.6.

        if (items == null)
            throw new ArgumentNullException(nameof(items));

        if (monoid == null)
            throw new ArgumentNullException(nameof(monoid));

        TElement result = monoid.Identity;
        foreach (var item in items)
            result = monoid.Combine(result, item);

        return result;
    }
}


Почему этот алгоритм будет работать для reference-типов и не будет для value-типов, или наоборот?

V>3. Из-за п.2. в теле обычных и генерик-методов может случиться неявный боксинг структуры, а программист и не обратит внимания. Но результат боксинга структуры никогда не равен null, даже если структура не инициализирована.


Если алгоритму передают некорректный экземпляр value-типа, то алгоритм поведёт себя так же, как если бы ему подали по не-null ссылке некорректный экземпляр reference-типа.

Алгоритму могут передать объект значимого типа, который бросит `System.InvalidOperationException` в методе `GetEnumerator()`. Например, по причине неинициализированности экземпляра `ImmutableArray<decimal>`, или по какой-то другой причине для экземпляра какой-то другой структуры. Но точно так же алгоритму могут передать не-null ссылку на объект ссылочного типа, который тоже бросит `System.InvalidOperationException` в методе `GetEnumerator()`. Junk in — junk out.

V>Все эти вещи насчет инициализаций структур дефолтными конструкторами надо решать в комплексе


Напомню, что изначально вопрос обобщённых алгоритмов поднимался вне контекста дефолтной инициализации. Просто как утверждение «собаку съел, в поисках классов таких алгоритмов, которые, таки, работают в обоих случаях и в попытках сформулировать ограничения на такие алгоритмы».

Я же утверждаю, что вполне можно придумывать такие обобщённые алгоритмы с констрейнтами, которым безразлично, передают ли им объекты структур или классов. Вот как суммирование в примере выше.
Глаза у меня добрые, но рубашка — смирительная!
Re[13]: Junk in — junk out
От: vdimas Россия  
Дата: 22.03.17 00:00
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Почему этот алгоритм будет работать для reference-типов и не будет для value-типов, или наоборот?


Ты опять мне пытаешься доказать, что такие алгоритмы, корректно работающие для вэлью и реф типов, всё-таки, есть?
Т.е., пытаешься мне навязать некую удобную для оспаривания позицию?
Не взлетит... ))


Q>Если алгоритму передают некорректный экземпляр value-типа, то алгоритм поведёт себя так же, как если бы ему подали по не-null ссылке некорректный экземпляр reference-типа.


Не туда ты опять смотришь.
Я могу в прикладном виде описать гарантии, которые не дадут мне привести ref-объект в невалидное состояние.
Для value-типов ср-в обеспечения таких гарантий нет.
Однакое, есть сценарии, когда такие гарантии "почти есть".
Например — value-тип являться приватным полем ref-типа и инициализируется в конструкторе.
Помимо этого у обрабатывающих ф-ий стоит модификатор ref в аргументах, что тоже уменьшает вероятность "просто случайно подать".
Помимо этого такие структуры у меня НЕ реализуют известные библиотекам фреймворка интерфейсы, чтобы, опять же, защититься на уровне системы типов от "случайно не туда подали через неявный боксинг".
И т.д. и т.п.
Т.е. я насобирал много правил, помогающих уменьшать вероятность ошибок при проектировании в value-типах, но не смог найти 100% работающей защиты от неправильного использования, т.е. не смог поручить контроль за правильностью использования компилятору. Т.е. только ручками подобную корректность обеспечиваем в любом случае.


Q>Алгоритму могут передать объект значимого типа, который бросит `System.InvalidOperationException` в методе `GetEnumerator()`.


Исключения "not implemented" или "invalid operation" — это первые признаки плохой архитектуры.

Простой пример. Вот есть класс TcpClient.

У него 80% методов выбрасывают "invalid operation".
Почему? Потому что для этого типа оставили пустой конструктор и еще несколько "глупых" конструкторов.
В итоге, объект может находиться в невалидном (неинициализированном) состоянии.
Если убрать пустой конструктор, то у нас пропадает надобность в св-ве Active, а так же уходят все места в его внутреннем коде, которые проверяют это св-во.

В классе TcpClient необходимо было оставить только конструктор от аргументов host+port, а так же добавить конструктор от Socket.
В случае конструирования от Socket можно проверить инвариант сразу, проверив RemoteEndPoint или Connected, т.е. запретить конструировать объект TcpClient в невалидном состоянии.

На самом деле класс TcpClient вообще является убожеством мысли как таковым. Он не даёт над классом Socket никакой другой дополнительной функциональности кроме как одного метода GetStream(). Что мешало добавить GetStream() в сокет — загадка великая есть.


Q>Но точно так же алгоритму могут передать не-null ссылку на объект ссылочного типа, который тоже бросит `System.InvalidOperationException` в методе `GetEnumerator()`.


Могут. Но это будут проблемы того ССЗБ, которому нравится InvalidOperationException.
Мне же нужна возможность конструировать всегда валидные объекты.


V>>Все эти вещи насчет инициализаций структур дефолтными конструкторами надо решать в комплексе

Q>Напомню, что изначально вопрос обобщённых алгоритмов поднимался вне контекста дефолтной инициализации.

Не отмажешься, не пытайся. ))
Структуры принципиально отличаются от ref-типов буквально двумя побочными эффектами:
— дефолтной инициализацией;
— передачей копий значений, в т.ч. через неявный боксинг.
В последнем случае происходят свои приколы — например, в некоем алгоритме будет изменяться содержимое копии, а не целевого экземпляра структуры.

Т.е. контекст был один — дотнет.

Тут ведь как? — ну не понял и не понял, хосподя.
Было бы тебе интересно — переспросил бы.


Q>Просто как утверждение «собаку съел, в поисках классов таких алгоритмов, которые, таки, работают в обоих случаях и в попытках сформулировать ограничения на такие алгоритмы».


Ну? Что не так-то?
Ты ведь не единственный тут такой, которые вместо того, чтобы уточнить подробности (если вообще охота дальше продолжать обсуждение) всегда первым делом переходят в несознанку/отрицалово и требуется десятки постов, чтобы разгрести все эти нагромождения "нет, нет и еще раз нет!".

А чего "нет", куда "нет" и почему вообще "нет"-то?... а ХЗ. Так надо! ))
Законы жанра?


Q>Я же утверждаю, что вполне можно придумывать такие обобщённые алгоритмы с констрейнтами, которым безразлично, передают ли им объекты структур или классов. Вот как суммирование в примере выше.


Ну так и я тебе ровно этот случай указал — это когда целевая структура не передаётся сама, рядом с ней надо передавать "словарь операций".

Причем, тут мало того, что таким образом можно хоть как-то задействовать арифметику.
Тут еще чисто вероятностный момент работает — когда надо передать два связанных строгим типовым отношением объекта куда-то, то на порядки сложнее допустить ошибку случайно, в этом месте просыпается внимательность программиста, ЧТД. Потому что есть такая фишка — основная доля ошибок делается в простых местах, в сложных местах ошибок обычно меньше.

Но все-равно, в отуствии ср-в обеспечения гарантий валидности объектов вероятность споткнуться об это остаётся ненулевой, даже для случая оперрования парой типов.

Собсно, моё разочарование в дотнете больше было не от его тормознуточти, а от непоследовательной системы типов, которая больно бъёт по рукам аккурат тогда, когда я пытаюсь с этой тормознутостью бороться, ы-ы-ы! )))
Нифига себе!
"Ах вот вы как? Ну ОК, не больно-то и хотелось..."
Отредактировано 22.03.2017 0:00 vdimas . Предыдущая версия .
Re[18]: Не понимая и половины
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.03.17 03:45
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>За счет чего разница будет в 2.5 раза, если ты уменьшил уровень косвенности лишь у одного вызова на забег по коллекции, в то время как 2*n вызовов осталось ровно с той же косвенностью, как и при передаче интерфейса?


V>В этой таблице результаты джита x86. Очевидно, что этот джит не провел для тестового цикла оптимизацию, т.е. не выкинул из его тела обращение к полям объекта "честным образом", т.е. через переменную, указанную в исходнике теста.


Причем тут вообще эта таблица и джит? Я пытаюсь выяснить у тебя, за счет чего ты ожидаешь уменьшение косвенности в методах типа
int Sum<T>(T coll) where T : IEnumerable<int>

Никакая джит оптимизация цикла в этом конкретном Sum не может отменить тот факт, что цикл будет дергать MoveNext/Current через интерфейс. Так чем же он лучше, чем обычный
int Sum(IEnumerable<int>)


?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.