Здравствуйте, pilgrim_, Вы писали:
_>>>Тут тоже интересная тема, чем отличается для компилятора A a; a.f.();, от A* a; a->f(); , что сlang ,что gcc генерят в последнем случае косвенный вызов. EP>>В последнем случае вообще UB. _>Я создание объекта для краткости просто опустил
Это ключевой момент (помимо включённых оптимизаций) — чтобы заинлайнить компилятор должен видеть какого типа объект по указателю объект.
В случае A a; a.f(); — тип объекта неизменен, поэтому и элементарно инлайнится, даже если между созданием и использованием будет много "непрозрачного" кода использующего этот объект.
Кстати, в C++11 появился final — он тоже помогает инлайнингу.
Re[38]: Visual C# vs C++. Надо сравнить перспективы.
Здравствуйте, Klikujiskaaan, Вы писали:
EP>>Ещё один сишарпист принёс говнеца в тему — да уж, бытие определяет их сознание K>Ну, во первых: это ты с порваной жо бегаешь из темы в тему,
Я уже понял что у тебя проблемы с жо, и фиксация на теме "троганья всякого", но не надо здесь об этом кричать — это оффтопик, спасибо.
K>демонстрируя свои комплексы С++неполноценности
Какие комплексы? Например? Без всяких комплексов использую другие языки, в том числе C#
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>> Еще раз, нет никаких особых препятствий для инлайнинга сомпараторов при специализации как это делается в C++. S>>Препятствий-то нет, но и инлайнинга тоже нет.
S> А откуда ты з-наешь?
Вижу по примеру.
S>Вот смотри исходники
S>https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs
S> А вот как это разворачивается
S>Optimising LINQ
S>roslyn-linq-rewrite
Я ровно об этом и пишу, что разворачивается все что угодно, но не компаратор.
S> Так Func<TSource, bool> predicate S> это и есть компаратор. Он и разворачивается.
То есть ты называешь компаратором предикат, потому мы и не можем понять друг друга.
S> То есть
То есть в этом примере отсутствует как класс обобщенный параметрически полиморфный компаратор. За него ad hoc полиморфный оператор сравнения для Int32, подставляемый компилятором (уже сколько лет) по выведенному типу T для метода Where исходя из типа первого аргумента. И оптимизация линка ровно ничего с вызовом оператора сравнения Int32 не делает, оставляет его как есть.
Здравствуйте, samius, Вы писали:
S>> Так Func<TSource, bool> predicate S>> это и есть компаратор. Он и разворачивается. S>То есть ты называешь компаратором предикат, потому мы и не можем понять друг друга.
В .Net это называется дженерик метод.
Чеи он отличается от компаратора? S>> То есть
S>То есть в этом примере отсутствует как класс обобщенный параметрически полиморфный компаратор. За него ad hoc полиморфный оператор сравнения для Int32, подставляемый компилятором (уже сколько лет) по выведенному типу T для метода Where исходя из типа первого аргумента. И оптимизация линка ровно ничего с вызовом оператора сравнения Int32 не делает, оставляет его как есть.
Еще раз при специализации шаблона будет подставляться код перегрузки оператора. Тоже самое.
Это та же кодогенерация. Просто в .Net можно делать оптимизацию при компиляции в CIL, а затем из CIL в машинный код.
Аналог С++ это аналог LLVM
Еще раз Func<TSource, bool>
TSource это дженерик параметр и никакой не инт
Внутри дженерик метода он вызывается.
То есть по твоему predicate(item)) это не дженерик метод?
while (enumerator.MoveNext()) {
TSource item = enumerator.Current;
if(predicate(item)) {
current = item;
return true;
}
}
Другое дело, что разворачивается не один оператор, а сразу несколько в одном цикле.
И для Linq они оптимизированы.
И по большому счету Linq применяется больше всех дженериков.
Еще раз повторю нет проблем проинлайнить методы интерфейса, если известно статически его определение.
Это тоже само что и перегрузка операторов. Все исходники для этого есть.
Вот когда ваши шаблоны будут так разворачиваться тогда может ...
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>> Так Func<TSource, bool> predicate S>>> это и есть компаратор. Он и разворачивается. S>>То есть ты называешь компаратором предикат, потому мы и не можем понять друг друга.
S> В .Net это называется дженерик метод.
Не согласен. В дотнете это называется дженерик делегат.
S>Чеи он отличается от компаратора?
Под компаратором я понимаю нечто (метод или делегат), что принимает два аргумента и возвращает признак превосходства значения одного аргумента над значением другого. Т.е. отличия как минимум в сигнатуре, в семантике использования. S>>> То есть
S> Еще раз при специализации шаблона будет подставляться код перегрузки оператора. Тоже самое. S> Это та же кодогенерация. Просто в .Net можно делать оптимизацию при компиляции в CIL, а затем из CIL в машинный код. S>Аналог С++ это аналог LLVM
Я тут вовсе не точу за C++.
S>Еще раз Func<TSource, bool>
S>TSource это дженерик параметр и никакой не инт
но это дженерик параметр метода Where. А метод, сравнивающий x и q — внезапно вовсе не дженериковый.
Вот как мне его показывает ILSpy:
Исходник
where (x >= lo) && (x <= hi)
результат в ILSpy
// ClassLibrary2.Class1.<>c__DisplayClass1_0internal bool <Scale>b__0(int x)
{
return x >= this.lo && x <= this.hi;
}
Т.е. угловые скобки здесь — часть сгенерированного имени, но не признак дженерика.
S>Внутри дженерик метода он вызывается. S> То есть по твоему predicate(item)) это не дженерик метод?
По-моему — нет. И по ILSpy-евскому тоже. Ему можно верить.
S> Другое дело, что разворачивается не один оператор, а сразу несколько в одном цикле. S>И для Linq они оптимизированы. S> И по большому счету Linq применяется больше всех дженериков. S>Еще раз повторю нет проблем проинлайнить методы интерфейса, если известно статически его определение.
Теоретически — нет. Проблема в том, что примера, который бы это демонстрировал, я не вижу.
Я знаю про возможность заинлайнить метод интерфейса, если реализовать его структурой, подать структуру через дженерик аргумент с констрейнтом (и тогда, может быть заинлайнится).
Foo<T, TComparer>(...) where TComparer : IComparer<T>
Но я в LINQ не вижу ни одного метода, который бы принимал компарер (или еще что-нибудь) таким макаром.
S>Это тоже само что и перегрузка операторов. Все исходники для этого есть.
Перегрузка операторов — хорошо. Но это ad-hoc, а не параметрический полиморфизм.
S> Вот когда ваши шаблоны будут так разворачиваться тогда может ...
Не наши. Я болею за дотнет.
Здравствуйте, samius, Вы писали:
S>>Еще раз Func<TSource, bool>
S>>TSource это дженерик параметр и никакой не инт S>но это дженерик параметр метода Where. А метод, сравнивающий x и q — внезапно вовсе не дженериковый. S>Вот как мне его показывает ILSpy: S>Исходник S>
S> where (x >= lo) && (x <= hi)
S>
S>результат в ILSpy S>
S>// ClassLibrary2.Class1.<>c__DisplayClass1_0
S>internal bool <Scale>b__0(int x)
S>{
S> return x >= this.lo && x <= this.hi;
S>}
S>
S>Увы, дженерика не было. S>В IL S>[code]
Правильно потому что ты берешь уже выведенный дженерик класс
Ты должен смотреть System.Collections.Generic.List`1[T]
А ты сотришь уже созданный через MakeGenericType
System.Collections.Generic.List`1[int]
И сообветственно для него и компараторы должны быть с заменой T на int
Разницу чувствуешь?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>Правильно потому что ты берешь уже выведенный дженерик класс S>Ты должен смотреть System.Collections.Generic.List`1[T]
S>А ты сотришь уже созданный через MakeGenericType
S>System.Collections.Generic.List`1[int] S> И сообветственно для него и компараторы должны быть с заменой T на int
S>Разницу чувствуешь?
Гхм. Насколько я помню, я смотрел результат работы компилятора C#, т.е. сборку с помощью ILSpy. А MakeGenericType — функция, которая не вызывается компилятором. Она вызывается рантаймом, следователььно результат ее работы вряд ли бы я мог обнаружить в сборке вместе с IL кодом. Логично?
Кроме того, обобщенная запись компаратора в C# — это Comparer<T>.Default.Compare(x, q), но никак не x < q.
То есть сейчас штатный компилятор C# без всяких переписываний сначала определяет тип Where<T> по первому аргументу и выводит Int32, потом подставляет в лямбде оператор сравнения двух интов. Для него лямбда, подсунутая в Where — это уже не дженерик метод.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Здравствуйте, samius, Вы писали:
S>>Правильно потому что ты берешь уже выведенный дженерик класс S>>Ты должен смотреть System.Collections.Generic.List`1[T]
S>>А ты сотришь уже созданный через MakeGenericType
S>>System.Collections.Generic.List`1[int] S>> И сообветственно для него и компараторы должны быть с заменой T на int
S>>Разницу чувствуешь?
S>Гхм. Насколько я помню, я смотрел результат работы компилятора C#, т.е. сборку с помощью ILSpy. А MakeGenericType — функция, которая не вызывается компилятором. Она вызывается рантаймом, следователььно результат ее работы вряд ли бы я мог обнаружить в сборке вместе с IL кодом. Логично?
Она вызывается динамически. Но сам то по себе дженерик класс от этого никуда не делся. и его специализация для валуе типов будет для каждого своя, а вот для объектов будет одна.
S>Кроме того, обобщенная запись компаратора в C# — это Comparer<T>.Default.Compare(x, q), но никак не x < q. S>То есть сейчас штатный компилятор C# без всяких переписываний сначала определяет тип Where<T> по первому аргументу и выводит Int32, потом подставляет в лямбде оператор сравнения двух интов. Для него лямбда, подсунутая в Where — это уже не дженерик метод.
Comparer это просто класс реализующий
public interface IComparable<in T>
и нетипизированный IComparer
Никто тебе не мешает создать свою реализацию на структуре.
В большинстве случаев это пережитки эпохи без дженериков
Сейчас ситуация така, что штатный компилятор делает то же само что и MakeGenericType в рантайме.
А вот Roslyn как раз и делает оптимизацию на уровне исходного кода, то же саме, что и в C++.
Там та же самая кодогенерация при специализации шаблона.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>Гхм. Насколько я помню, я смотрел результат работы компилятора C#, т.е. сборку с помощью ILSpy. А MakeGenericType — функция, которая не вызывается компилятором. Она вызывается рантаймом, следователььно результат ее работы вряд ли бы я мог обнаружить в сборке вместе с IL кодом. Логично?
S> Она вызывается динамически. Но сам то по себе дженерик класс от этого никуда не делся. и его специализация для валуе типов будет для каждого своя, а вот для объектов будет одна.
Так все-таки, каким образом я мог увидеть результат работы MakeGenericType в сборке?
S>>Кроме того, обобщенная запись компаратора в C# — это Comparer<T>.Default.Compare(x, q), но никак не x < q. S>>То есть сейчас штатный компилятор C# без всяких переписываний сначала определяет тип Where<T> по первому аргументу и выводит Int32, потом подставляет в лямбде оператор сравнения двух интов. Для него лямбда, подсунутая в Where — это уже не дженерик метод.
S> Comparer это просто класс реализующий S>
S>public interface IComparable<in T>
S>
То есть Int32 — это Comparer? S> и нетипизированный IComparer
Оба сразу? А есть такие классы, которые реализуют сразу и то и другое?
S> Никто тебе не мешает создать свою реализацию на структуре. S>В большинстве случаев это пережитки эпохи без дженериков
Конечно не мешает. Но что-то мешает мне свою реализацию на структуре подать по значению в LINQ методы типа Where.
S> Сейчас ситуация така, что штатный компилятор делает то же само что и MakeGenericType в рантайме.
Можно какую-либо демонстрацию вашего тезиса? S> А вот Roslyn как раз и делает оптимизацию на уровне исходного кода, то же саме, что и в C++. S>Там та же самая кодогенерация при специализации шаблона.
Кодогенерация при специализации шаблона? Можно подробнее? Или что вы здесь называете кодогенерацией? Подстановку типа что ли?
Смысл в том, что класс доступный через рефлексию с MakeGenericType и со статической компиляцией должны быть одинаковыми.
Эти ограничения сведены к минимуму в .Net Native S>> А вот Roslyn как раз и делает оптимизацию на уровне исходного кода, то же саме, что и в C++. S>>Там та же самая кодогенерация при специализации шаблона. S>Кодогенерация при специализации шаблона? Можно подробнее? Или что вы здесь называете кодогенерацией? Подстановку типа что ли?
где вкуснее покормят, где девок покруче в баню подгонят — то и бери
именно так помню давным давно главбух выбрал и привез хрень на базе дб прогресс в одну дочку автоваза где я проторчал почти полгода )))
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>> Сейчас ситуация така, что штатный компилятор делает то же само что и MakeGenericType в рантайме. S>>Можно какую-либо демонстрацию вашего тезиса?
S> Смотри http://infostart.ru/public/448668/
Я не собираюсь в ближайшей перспективе осваивать 1C
S> Смысл в том, что класс доступный через рефлексию с MakeGenericType и со статической компиляцией должны быть одинаковыми.
Отсюда не вытекает то, что компилятор делает аналог MakeGenericType.
S>Эти ограничения сведены к минимуму в .Net Native
Какие ограничения?
S>>> А вот Roslyn как раз и делает оптимизацию на уровне исходного кода, то же саме, что и в C++. S>>>Там та же самая кодогенерация при специализации шаблона. S>>Кодогенерация при специализации шаблона? Можно подробнее? Или что вы здесь называете кодогенерацией? Подстановку типа что ли?
S> Я уже устал ссылку давать. S>Optimising LINQ S>roslyn-linq-rewrite
Когда я увидел слова "специализация" и "шаблон", то подумал что речь о C++, который в контексте упомнянут. А тут опять эта ссылка.
Я уже устал эту ссылку смотреть. От того что она тут очередной раз появляется, в ней не появляется инлайнинга параметрически полиморфных компараторов.
S>Там не просто подстановка типа но и оптимизация всех ветвей Linq запроса.
Я сдаюсь. Того, что я ожидал, я там не увижу, а время жаль.
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>На самом деле Linq это в том числе и деревья выражений Динамические Linq-запросы или приручаем деревья выражений
S>Динамическое построение Linq запроса
S> Которые могут компилироваться в рантайме. А могут и на этапе компиляции. S> Для SQL это кодогенерация, а для Enumerable это компиляция обхода коллекции
S>Если использовать вместо S>Вместо Func<t,bool>>
S>Expression<Func<t,bool>>
S> то все прекрасно будет инлайнится при специализации.
S>Класс Expression<TDelegate>
Не надо возить меня по этим азам. Писал я и свой LINQ провайдер для сериализации запросов когда-то. Все это совершенно не касается инлайнигна "параметрически полиморфных компараторов", если разобраться что такое "компаратор" и "параметрический полиморфизм".
Здравствуйте, samius, Вы писали:
SS>Не надо возить меня по этим азам. Писал я и свой LINQ провайдер для сериализации запросов когда-то. Все это совершенно не касается инлайнигна "параметрически полиморфных компараторов", если разобраться что такое "компаратор" и "параметрический полиморфизм".
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>Тем, что оно не может принять два значения и сравнить их между собой, как это делают компараторы. S>Ок
S>
S> Expression<Func<T,T,int>> func
S>
Отлично, благодарю.
Но это еще не компаратор, это только его сигнатура. Осталось написать параметрически полиморфное тело компаратора и продемонстрировать как оно инлайнится.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Здравствуйте, samius, Вы писали:
S>>>Тем, что оно не может принять два значения и сравнить их между собой, как это делают компараторы. S>>Ок
S>>
S>> Expression<Func<T,T,int>> func
S>>
S>Отлично, благодарю. S>Но это еще не компаратор, это только его сигнатура. Осталось написать параметрически полиморфное тело компаратора и продемонстрировать как оно инлайнится.
То есть
System.Linq.Expressions.Expression<Func<int,int, int>> expr = (i,x) => i -x;
А как использовать деревья выражений я тебе уже кучу сслок давал.
На самом деле, что можно в рантайме, то можно и на этапе компиляции. Так или иначе компилятор строит AST дерево, и можно подставлять не адрес на функцию, а разворачитвать тело функции по адресу на этапе компиляции в CIL код.