Здравствуйте, 4058, Вы писали:
4>Доброго времени суток.
4>Краткое предисловие:
4>В процессе переноса кода с FW 3.5 SP1 на FW 4+, заметил на некоторых фрагментах существенную просадку производительности. 4>Проблема выявилась в неожиданном месте, а именно на строковых операциях наподобие String.IndexOf, которые данный код активно использует.
Все дело в используемой версии таблицы Unicode. В версии .NET3.5 использовался Unicode 5.0, c 4 — Unicode 5.1, с NET4.5 — Unicode 6.0 и далее, в .NET Core зависит от ОС.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[16]: Регресс производительности при переходе с FW 3.5 SP1
Core31 и FW 4.0 почти равны, 3.5 далеко в хвосте ...
Теперь по int-ам:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
IntBench(1000000);
}
static void IntBench(int arrSize)
{
const int cnt = 1000;
List<int> arr = new List<int>(arrSize);
for (int j = 0; j < arrSize; j++)
arr.Add(j);
int key = arrSize - 1;
int c = 0;
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < cnt; i++)
c += arr.IndexOf(key);
double ts = sw.Elapsed.TotalSeconds;
ulong total = (ulong)arrSize * (ulong)cnt;
Console.WriteLine("String ({3}) {0} op / {1:0.000} sec = {2:0}", total, ts, total / ts, arrSize);
}
}
В процессе переноса кода с FW 3.5 SP1 на FW 4+, заметил на некоторых фрагментах существенную просадку производительности.
Проблема выявилась в неожиданном месте, а именно на строковых операциях наподобие String.IndexOf, которые данный код активно использует.
Псевдо-код для демонстрации проблемы:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
StrBench(100000);
}
static void StrBench(int arrSize)
{
const int cnt = 10;
List<string> arr = new List<string>(arrSize);
for (int j = 0; j < arrSize; j++)
arr.Add(string.Format("{0}{1}{2}", new string('x', 100), BuildKey(j), new string('x', 100)));
string key = BuildKey(arrSize - 1);
int c = 0;
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < cnt; i++)
c += arr.Count(s => s.IndexOf(key) > -1);
double ts = sw.Elapsed.TotalSeconds;
ulong total = (ulong)arrSize * (ulong)cnt;
Console.WriteLine("String ({3}) {0} op / {1:0.000} sec = {2:0}", total, ts, total / ts, arrSize);
}
static string BuildKey(int i)
{
return i.ToString().PadLeft(10, '0');
}
}
Билдим: Release (обязательно!)|Any CPU отдельно под FW 3.5 и FW 4 (я делал под 4.0 и 4.7.2)
т.е. производительность в 3.5 раза больше на 4-х ядрах (под FW 4+), и при этом всего в 1.3 раза, чем на одном ядре под FW 3.5 SP1.
Умозаключения и прочая философия
Вычислительная производительность одного ядра уже давно не сильно растет, если сравнить мою железку 5-ти летней давности (i5-6500) с железкой 10-ти летней давности (Core i3-540 на 3.06 Ггц) то получается, приблизительно в 1.5 раза в окрестностях почти равных частот.
На одном ядре профит (без учета увеличения частоты) обычно можно получить за счет более быстрого и емкого кэша и оптимизации конвейера.
В виду вышесказанного, всё это выглядит непредумышленной диверсией со стороны разработчиков FW, т.к. регресс производительности, некоторых часто-используемых операций при переходе на FW 4+ существенно превышает многолетний прогресс по IPC на одно ядро.
С уменьшением техпроцесса по-прежнему, увеличивается энергоэффективность и кол-во ядер, за счет чего можно повысить производительность, но не все ведь можно распараллелить, и не всегда это легко.
В данном случае код местами переписан, проблемы нет (плюс профит от распараллеливания средствами LINQ), но беспокоит сам факт, что пришлось это делать.
P.S. Под .NET пишу с 1-й беты (2001 год), до этого C/C++ под x86, а еще ранее ASM под 3 МГЦ-овые 8-ми битки — i8080 (Z80) ...
Re: Регресс производительности при переходе с FW 3.5 SP1 на FW 4+ (String.IndexO
Здравствуйте, Serginio1, Вы писали:
S>Ща .Net Core 3.1 и там говорят скорость выше. Кроме того можно еще попробовать .Net Native из UWP
Обновил VS 2019 до версии 16.5.5, сбилдил и запустил этот "тест" под Core 3.1 — результат аналогичен Core 2.1.
offtop:
Как это можно понимать, более 10-ка лет .NET FW "нашпиговывают" множеством сомнительных плюшек в плане повседневной практичности, при этом местами "отламывают" такую важную для повседневности вещь как производительность, причем в самых неожиданных местах.
Можно понять, когда в 2.0 мы получили параметризованные типы и анонимные делегаты, в 3.0 лямбда-выражения, это все было реально нужно, библиотеки и языки органично развивались по большей части в правильном направлении.
Конечно для обработки "офисных" документов (PDF/Excel/Word), различных конвертеров, компрессии, драйверов к различным БД, криптографии/ЭЦП, да и много другого приходится "тащить" сторонние библиотеки (т.к. либо чего-то просто нет, либо есть — но очень плохо), но я не замечал при постепенном переходе от 1.0 до 3.5 SP1 потери производительности ранее написанного кода.
В расчет не берем средства разработки, которые все меньше задумывались о трате ресурсов.
Ну а говорить про то, как безобразно выжирают вычислительный ресурс JavaScript (который уже лет 10 пытаются воткнуть везде где ему совсем не место) и прочие Python-ы даже не стоит.
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>>Ща .Net Core 3.1 и там говорят скорость выше. Кроме того можно еще попробовать .Net Native из UWP
4>Обновил VS 2019 до версии 16.5.5, сбилдил и запустил этот "тест" под Core 3.1 — результат аналогичен Core 2.1.
4>offtop: 4>Как это можно понимать, более 10-ка лет .NET FW "нашпиговывают" множеством сомнительных плюшек в плане повседневной практичности, при этом местами "отламывают" такую важную для повседневности вещь как производительность, причем в самых неожиданных местах.
Здравствуйте, rameel, Вы писали:
R>Здравствуйте, 4058, Вы писали:
4>>Доброго времени суток.
4>>Краткое предисловие:
4>>В процессе переноса кода с FW 3.5 SP1 на FW 4+, заметил на некоторых фрагментах существенную просадку производительности. 4>>Проблема выявилась в неожиданном месте, а именно на строковых операциях наподобие String.IndexOf, которые данный код активно использует.
R>Все дело в используемой версии таблицы Unicode. В версии .NET3.5 использовался Unicode 5.0, c 4 — Unicode 5.1, с NET4.5 — Unicode 6.0 и далее, в .NET Core зависит от ОС.
Интересно почему тогда string.Contains дает аналогичные результаты на 3.5 и 4+, может локале-ориентированный компаратор сильно "фонит":
c += arr.Count(s => s.Contains(key));
3.5: String (100000) 1000000 op / 0,248 sec = 4030540
4.0: String (100000) 1000000 op / 0,237 sec = 4205221
Также аналогичные результаты можно получить, если явно в качестве компаратора указать StringComparison.Ordinal:
c += arr.Count(s => s.IndexOf(key, StringComparison.Ordinal) > -1);
3.5: String (100000) 1000000 op / 0,246 sec = 4053168
4.0: String (100000) 1000000 op / 0,239 sec = 4181658
Понять их конечно можно, поскольку Core пытаются пристроить на мобилки и НЕ window-ые сервера, то для лучшего впечатления производительность лучше подтянуть.
Здравствуйте, 4058, Вы писали:
4>Интересно почему тогда string.Contains дает аналогичные результаты на 3.5 и 4+, может локале-ориентированный компаратор сильно "фонит":
Здравствуйте, rameel, Вы писали:
R>Все дело в используемой версии таблицы Unicode. В версии .NET3.5 использовался Unicode 5.0, c 4 — Unicode 5.1, с NET4.5 — Unicode 6.0 и далее, в .NET Core зависит от ОС.
4>... Contains/Ordinal
R>Потому что не используется локаль
Из этого следует, что переход с Unicode 5.0 (FW 3.5) на 5.1 (FW 4.0) выдаёт регресс производительности для локалезависимых операций в 2.7 раза?
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> При этом есть куча примеров, где .Net Core и .Net Native обгоняют в 5 и более раз. S>>https://devblogs.microsoft.com/dotnet/regex-performance-improvements-in-net-5/
4>Понять их конечно можно, поскольку Core пытаются пристроить на мобилки и НЕ window-ые сервера, то для лучшего впечатления производительность лучше подтянуть.
Здравствуйте, 4058, Вы писали:
4>P.S. Под .NET пишу с 1-й беты (2001 год), до этого C/C++ под x86, а еще ранее ASM под 3 МГЦ-овые 8-ми битки — i8080 (Z80) ...
Тем более странно, что ты разницу в работе одной функции проецируешь на весь .Net 4.0.
Просто напиши свою версию этой функции. Если так важна производительность, сделай это в ансэйфе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, Serginio1, Вы писали:
S> Кстати вот другие бенчмарки https://habr.com/ru/post/481558/ S>На интах IndexOf
S>Method Type .NET 4.8 Core 2.1 Core 3.1 S>IndexOf Int 1.00 0.99 0.43 S>IndexOf String 1.00 0.95 0.95
S>Возьми их тесты
Мы не обсуждаем IndexOf для коллекций/массивов, речь в исходном сообщении про обработку строк (indexOf внутри строки, а не коллекции).
Приведенные тобой результаты, из примера где они гоняют IndexOf на коллекции.
Re[3]: [R#] Merge sequential checks and compilation error
Здравствуйте, 4058, Вы писали:
4>Из этого следует, что переход с Unicode 5.0 (FW 3.5) на 5.1 (FW 4.0) выдаёт регресс производительности для локалезависимых операций в 2.7 раза?
Вполне возможно, я не в курсе, что поменялось в 5.1. Вопрос лучше задать непосредственно разработчикам https://github.com/dotnet/runtime
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: Регресс производительности при переходе с FW 3.5 SP1 на FW 4+ (String.Ind
Здравствуйте, rameel, Вы писали:
R>Все дело в используемой версии таблицы Unicode. В версии .NET3.5 использовался Unicode 5.0, c 4 — Unicode 5.1, с NET4.5 — Unicode 6.0 и далее, в .NET Core зависит от ОС.
Начиная с .NET Framework 2.0 с пакетом обновления 1 (SP1) и до .NET Framework 4, каждая версия .NET Framework включает таблицы, которые содержат веса сортировки и данные по нормализации строк и основаны на конкретной версии Unicode. В .NET Framework 4.5 наличие этих таблиц зависит от операционной системы:
В Windows 7 и предыдущих версиях операционной системы Windows таблицы продолжают использоваться для сравнения и упорядочивания строк.
В Windows 8 .NET Framework делегирует операции сравнения строк и упорядочения операционной системе.
Следовательно, результат сравнения строк может зависеть не только от версии .NET Framework, но и от версии операционной системы, как показано в следующей таблице. Обратите внимание, что этот список поддерживаемых версий Unicode применяется только для сравнения и сортировки символов; это не относится к классификации символов Юникода по категориям.
и солнце б утром не вставало, когда бы не было меня
Re[2]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, VladD2, Вы писали:
VD>Тем более странно, что ты разницу в работе одной функции проецируешь на весь .Net 4.0.
Невнимательно читаешь, во первых речь идет конкретно о String.IndexOf (в названии темы даже присутствует), и тот кусок кода просто изобилировал его использованием, и "тупой" перенос с 3.5 на 4.0 на том участке дал заметный регресс производительности, что в результате привело к негативным последствиям.
VD>Просто напиши свою версию этой функции. Если так важна производительность, сделай это в ансэйфе.
Я ранее писал:
В данном случае код местами переписан, проблемы нет (плюс профит от распараллеливания средствами LINQ), но беспокоит сам факт, что пришлось это делать.
Проблема, именно в том, что пришлось внести изменения в код при подъеме версии FW, чего я например ни разу не делал с 1.0 по 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> Кстати вот другие бенчмарки https://habr.com/ru/post/481558/ S>>На интах IndexOf
S>>Method Type .NET 4.8 Core 2.1 Core 3.1 S>>IndexOf Int 1.00 0.99 0.43 S>>IndexOf String 1.00 0.95 0.95
S>>Возьми их тесты
4>Мы не обсуждаем IndexOf для коллекций/массивов, речь в исходном сообщении про обработку строк (indexOf внутри строки, а не коллекции). 4>Приведенные тобой результаты, из примера где они гоняют IndexOf на коллекции.
Ты же утвеждаешь, что 3.5 быстрее! Проверь с интами.
Начиная с .NET Framework 2.0 с пакетом обновления 1 (SP1) и до .NET Framework 4, каждая версия .NET Framework включает таблицы, которые содержат веса сортировки и данные по нормализации строк и основаны на конкретной версии Unicode. В .NET Framework 4.5 наличие этих таблиц зависит от операционной системы:
В Windows 7 и предыдущих версиях операционной системы Windows таблицы продолжают использоваться для сравнения и упорядочивания строк.
В Windows 8 .NET Framework делегирует операции сравнения строк и упорядочения операционной системе.
Следовательно, результат сравнения строк может зависеть не только от версии .NET Framework, но и от версии операционной системы, как показано в следующей таблице. Обратите внимание, что этот список поддерживаемых версий Unicode применяется только для сравнения и сортировки символов; это не относится к классификации символов Юникода по категориям.
Вот веса и версии юникоде могут быть разными и может разниться от содержимого.
Попробуй сортировку где преобладает кириллица.
и солнце б утром не вставало, когда бы не было меня
Re[8]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, Serginio1, Вы писали:
S> Ты же утвеждаешь, что 3.5 быстрее! Проверь с интами.
Я не просто утверждаю, а демонстрирую результаты на конкретном примере, который можно при желании у себя воспроизвести.
Также я не очень понимаю, интереса померится поиском int-а в коллекции, т.к. поиск подстроки и поиск элемента в массиве это несколько разные вещи.
S> Вот веса и версии юникоде могут быть разными и может разниться от содержимого.
Не уверен, что это причина почему производительность снижается в 2.7 раза.
S>Попробуй сортировку где преобладает кириллица.
Мой пример просто генерит 100000 строк длиной чуть более 200 символов, вида:
"XXXXXXX0000000001XXXXXXX"
далее считаем строки (Count на коллекции), в которые входит строка: "0000099999", поиск подстроки через IndexOf, чтобы показать проблему.
Поэтому смысл чего-то мерить с использованием кириллицы я не вижу.
Re[9]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> Ты же утвеждаешь, что 3.5 быстрее! Проверь с интами.
4>Я не просто утверждаю, а демонстрирую результаты на конкретном примере, который можно при желании у себя воспроизвести. 4>Также я не очень понимаю, интереса померится поиском int-а в коллекции, т.к. поиск подстроки и поиск элемента в массиве это несколько разные вещи.
Ну вот ты сравни и покажи результаты. Казалось бы разницы то быть не должно
Ты демонстрируешь на отдельной задаче. Ранее тебе говорили о разнице версий юникода от версий фреймворка.
S>> Вот веса и версии юникоде могут быть разными и может разниться от содержимого.
4>Не уверен, что это причина почему производительность снижается в 2.7 раза.
S>>Попробуй сортировку где преобладает кириллица.
4>Мой пример просто генерит 100000 строк длиной чуть более 200 символов, вида:
4>"XXXXXXX0000000001XXXXXXX"
Заметь, что это строки ASCII
Добавь юникодные символы раз используешь IndexOf
public int IndexOf(string value)
{
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value);
}
4>далее считаем строки (Count на коллекции), в которые входит строка: "0000099999", поиск подстроки через IndexOf, чтобы показать проблему. 4>Поэтому смысл чего-то мерить с использованием кириллицы я не вижу.
А ты попробуй, в чем проблема?
и солнце б утром не вставало, когда бы не было меня
Re: Регресс производительности при переходе с FW 3.5 SP1 на FW 4+ (String.IndexO
Здравствуйте, 4058, Вы писали:
4>Доброго времени суток.
4>Краткое предисловие:
4>В процессе переноса кода с FW 3.5 SP1 на FW 4+, заметил на некоторых фрагментах существенную просадку производительности. 4>Проблема выявилась в неожиданном месте, а именно на строковых операциях наподобие String.IndexOf, которые данный код активно использует.
4> for (int i = 0; i < cnt; i++) 4> c += arr.Count(s => s.IndexOf(key) > -1);
Здравствуйте, Serginio1, Вы писали:
S> Ну вот ты сравни и покажи результаты. Казалось бы разницы то быть не должно
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
IntBench(1000000);
}
static void IntBench(int arrSize)
{
const int cnt = 100;
List<int> arr = new List<int>(arrSize);
for (int j = 0; j < arrSize; j++)
arr.Add(j);
int key = arrSize - 1;
int c = 0;
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < cnt; i++)
c += arr.Count(s => s == key);
double ts = sw.Elapsed.TotalSeconds;
ulong total = (ulong)arrSize * (ulong)cnt;
Console.WriteLine("Int ({3}) {0} op / {1:0.000} sec = {2:0}", total, ts, total / ts, arrSize);
}
}
FW 3.5: Int (1000000) 100000000 op / 0,872 sec = 114699379
FW 4.0: Int (1000000) 100000000 op / 0,990 sec = 101008734
Core31: Int (1000000) 100000000 op / 0,893 sec = 111996104
4>>Поэтому смысл чего-то мерить с использованием кириллицы я не вижу.
S> А ты попробуй, в чем проблема?
Заменил "X" на "Ё", результаты те-же, не понимаю, что должно было изменится, строки в .NET исторически UTF-16 и один символ ASCII в UTF-16 занимает 2 байта, собственно как и буква "Ё".
Re[2]: Регресс производительности при переходе с FW 3.5 SP1 на FW 4+ (String.Ind
Ну как сказать не хочу, в оригинальном коде он не задавался, а когда поднимался с 3.5 на 4.0, заметил существенную разницу, о чем собственно и написал.
Естественно где надо я заиспользовал локаленезависимый компаратор, все это собственно уже выше описано.
Re[11]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
4>
4>FW 3.5: Int (1000000) 100000000 op / 0,872 sec = 114699379
4>FW 4.0: Int (1000000) 100000000 op / 0,990 sec = 101008734
4>Core31: Int (1000000) 100000000 op / 0,893 sec = 111996104
4>
4>>>Поэтому смысл чего-то мерить с использованием кириллицы я не вижу.
S>> А ты попробуй, в чем проблема?
4>Заменил "X" на "Ё", результаты те-же, не понимаю, что должно было изменится, строки в .NET исторически UTF-16 и один символ ASCII в UTF-16 занимает 2 байта, собственно как и буква "Ё".
Здравствуйте, Serginio1, Вы писали:
4>>Заменил "X" на "Ё", результаты те-же, не понимаю, что должно было изменится, строки в .NET исторически UTF-16 и один символ ASCII в UTF-16 занимает 2 байта, собственно как и буква "Ё".
S>https://docs.microsoft.com/en-us/dotnet/api/system.string?redirectedfrom=MSDN&view=netcore-3.1
S>Только вот алгоритм сравнения может быть разный в зависимости от версии фреймворка и версии юникода
Мне трудно представить, что разница может быть настолько существенна, в зависимости от минорной версии юникода (в данном случае мы получается говорим про 5.0 и 5.1).
S>Разница между .Net Core 3.1 и FW 3.5 по твои данным особо то и нет. В пределе погрешности.
Так на обычных "пробегах" по коллекции и object.Equals разницы и не должно быть.
Re[13]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
4>>>Заменил "X" на "Ё", результаты те-же, не понимаю, что должно было изменится, строки в .NET исторически UTF-16 и один символ ASCII в UTF-16 занимает 2 байта, собственно как и буква "Ё".
S>>https://docs.microsoft.com/en-us/dotnet/api/system.string?redirectedfrom=MSDN&view=netcore-3.1
S>>Только вот алгоритм сравнения может быть разный в зависимости от версии фреймворка и версии юникода
4>Мне трудно представить, что разница может быть настолько существенна, в зависимости от минорной версии юникода (в данном случае мы получается говорим про 5.0 и 5.1).
А Юникод это же не 2 байта. Те же китайские иероглифы в 2 байта не умещаются. S>>Разница между .Net Core 3.1 и FW 3.5 по твои данным особо то и нет. В пределе погрешности.
4>Так на обычных "пробегах" по коллекции и object.Equals разницы и не должно быть.
Ну ты заменил IndexOf на Equals я и не заметил, прошу прощения. Но разница то есть.
На Core 3 поиск Int в List стал примерно в 6 раз быстрее, а поиск строк — в 1.4 раза. В Core JIT научился в некоторых ситуациях девирутализировать виртуальные методы, т.е. они вызываются напрямую. Более того, такие методы могут быть заинлайнены. В данном случае девиртуализируется метод EqualityComparer.Default.Equals, который используется для сравнения элементов. В случае с Int всё сводится к вызову Int32.Equals, который к тому же инлайнится. В итоге получившийся код по эффективности близок к прямому сравнению двух Int.
Кстати, раньше я всегда думал, что метод Contains внутри вызывает IndexOf, но оказалось, что это верно только для Core. В полном фреймворке это разные методы, и работают они с разной скоростью.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S> А Юникод это же не 2 байта. Те же китайские иероглифы в 2 байта не умещаются.
Для UTF-16 либо 2 байта (например для ASCII, кириллицы, французского и т.п.), либо 4 байта (для некоторых иероглифов и прочей лабуды).
Строки в .NET исторически в UTF-16, можете взять дамп и посмотреть.
Поэтому было не понятно зачем нужно использовать кириллицу для теста и что должно было изменится.
4>>Так на обычных "пробегах" по коллекции и object.Equals разницы и не должно быть.
S> Ну ты заменил IndexOf на Equals я и не заметил, прошу прощения. Но разница то есть.
Я не заменял IndexOf на Equals, я просто пояснил что делает обычный поиск по коллекции.
S>Опять же https://habr.com/ru/post/481558/
S>
S>На Core 3 поиск Int в List стал примерно в 6 раз быстрее, а поиск строк — в 1.4 раза.
Я этого что-то не прочувствовал.
Просьба на маркетологические "исследования" не ссылаться, можете взять мой пример, и их какой-нибудь пример и сравнить результаты.
Re[15]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> А Юникод это же не 2 байта. Те же китайские иероглифы в 2 байта не умещаются.
4>Для UTF-16 либо 2 байта (например для ASCII, кириллицы, французского и т.п.), либо 4 байта (для некоторых иероглифов и прочей лабуды). 4>Строки в .NET исторически в UTF-16, можете взять дамп и посмотреть. 4>Поэтому было не понятно зачем нужно использовать кириллицу для теста и что должно было изменится.
4>>>Так на обычных "пробегах" по коллекции и object.Equals разницы и не должно быть.
S>> Ну ты заменил IndexOf на Equals я и не заметил, прошу прощения. Но разница то есть.
4>Я не заменял IndexOf на Equals, я просто пояснил что делает обычный поиск по коллекции.
S>>Опять же https://habr.com/ru/post/481558/
S>>
S>>На Core 3 поиск Int в List стал примерно в 6 раз быстрее, а поиск строк — в 1.4 раза.
4>Я этого что-то не прочувствовал. 4>Просьба на маркетологические "исследования" не ссылаться, можете взять мой пример, и их какой-нибудь пример и сравнить результаты.
Ну ты так и не привел тест с IndexOf.
И можешь сравнить тесты "маркентологов". Опровергни...
и солнце б утром не вставало, когда бы не было меня
Re[15]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> А Юникод это же не 2 байта. Те же китайские иероглифы в 2 байта не умещаются.
4>Для UTF-16 либо 2 байта (например для ASCII, кириллицы, французского и т.п.), либо 4 байта (для некоторых иероглифов и прочей лабуды). 4>Строки в .NET исторически в UTF-16, можете взять дамп и посмотреть. 4>Поэтому было не понятно зачем нужно использовать кириллицу для теста и что должно было изменится.
Теперь надо выяснить чем отличаются версии Unicode. По твоим утверждениям нет. Но если сравнивать без учета локали, то разницы то и нет.
Интересно почему тогда string.Contains дает аналогичные результаты на 3.5 и 4+, может локале-ориентированный компаратор сильно "фонит":
c += arr.Count(s => s.Contains(key));
3.5: String (100000) 1000000 op / 0,248 sec = 4030540
4.0: String (100000) 1000000 op / 0,237 sec = 4205221
Также аналогичные результаты можно получить, если явно в качестве компаратора указать StringComparison.Ordinal:
c += arr.Count(s => s.IndexOf(key, StringComparison.Ordinal) > -1);
3.5: String (100000) 1000000 op / 0,246 sec = 4053168
4.0: String (100000) 1000000 op / 0,239 sec = 4181658
4>>>Так на обычных "пробегах" по коллекции и object.Equals разницы и не должно быть.
S>> Ну ты заменил IndexOf на Equals я и не заметил, прошу прощения. Но разница то есть.
4>Я не заменял IndexOf на Equals, я просто пояснил что делает обычный поиск по коллекции.
S>>Опять же https://habr.com/ru/post/481558/
S>>
S>>На Core 3 поиск Int в List стал примерно в 6 раз быстрее, а поиск строк — в 1.4 раза.
4>Я этого что-то не прочувствовал. 4>Просьба на маркетологические "исследования" не ссылаться, можете взять мой пример, и их какой-нибудь пример и сравнить результаты.
На самом деле в производительность .Net Core затратили много труда.
Развивают и CoreRT (.NET Native).
Вот возьми и опровергни их результаты.
Твои исходные данные ну никак не соответсвуют реальным. Нужно брать данные из реальной базы данных.
Да и макркентологи немного другой тест привели
public int List_Contains()
{
int count = 0;
List<T> collection = _list;
T[] array = _lookupValues;
for (int i = 0; i < array.Length; i++)
{
if (collection.Contains(array[i]))
count++;
}
return count;
}
На Core 3 поиск Int в List стал примерно в 6 раз быстрее, а поиск строк — в 1.4 раза. В Core JIT научился в некоторых ситуациях девирутализировать виртуальные методы, т.е. они вызываются напрямую. Более того, такие методы могут быть заинлайнены. В данном случае девиртуализируется метод EqualityComparer.Default.Equals, который используется для сравнения элементов. В случае с Int всё сводится к вызову Int32.Equals, который к тому же инлайнится. В итоге получившийся код по эффективности близок к прямому сравнению двух Int.
Кстати, раньше я всегда думал, что метод Contains внутри вызывает IndexOf, но оказалось, что это верно только для Core. В полном фреймворке это разные методы, и работают они с разной скоростью.
Опровергни их результаты. Заодно можно взять их метод
ValuesGenerator.ArrayOfUniqueValues<T>
и солнце б утром не вставало, когда бы не было меня
Re[16]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, Serginio1, Вы писали:
S>> А Юникод это же не 2 байта. Те же китайские иероглифы в 2 байта не умещаются.
4>Для UTF-16 либо 2 байта (например для ASCII, кириллицы, французского и т.п.), либо 4 байта (для некоторых иероглифов и прочей лабуды). 4>Строки в .NET исторически в UTF-16, можете взять дамп и посмотреть. 4>Поэтому было не понятно зачем нужно использовать кириллицу для теста и что должно было изменится.
Если есть зависимость от версии Юникода, то можно посмотреть на скорость сортировки.
Взять набор символов и перемешивать на каждой итерации. https://ru.stackoverflow.com/questions/547996/Как-перемешать-случайно-переставить-элементы-в-массиве/
Если с сортировкой все нормально, то надо писать, что бы подправили IndexOf
и солнце б утром не вставало, когда бы не было меня
Re[17]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>FW 3.5: String (1000000) 1000000000 op / 1,619 sec = 617788936 4>FW 4.0: String (1000000) 1000000000 op / 0,630 sec = 1586526708 4>Core31: String (1000000) 1000000000 op / 0,278 sec = 3593765105
4>Core31 по отношению к FW 4.0 выдал профит в 2.3 (!), и почти в 6-ть раз по отношению к FW 3.5.
4>P.S. Интересно с чем эти "маркетологи" сравнивали Core.
C C++ Я уже писал про CoreRT. Это наследник .Net Core. Там используется компилятор С++
Здравствуйте, 4058, Вы писали:
4>Невнимательно читаешь, во первых речь идет конкретно о String.IndexOf (в названии темы даже присутствует), и тот кусок кода просто изобилировал его использованием, и "тупой" перенос с 3.5 на 4.0 на том участке дал заметный регресс производительности, что в результате привело к негативным последствиям.
Я как раз внимательно все прочел. И в названии темы String.IndexOf не присутствует. Название вон сверху.
4>В данном случае код местами переписан, проблемы нет (плюс профит от распараллеливания средствами LINQ), но беспокоит сам факт, что пришлось это делать.
Это из серии обжегся на молоке, дую на воду. Ну. одна функция стала по медленнее. Никакого отношения к производительности самого дотнета это не имеет. Производительность зависит от кучи фаторов. И главное это работа компилятора (джит, нген) и сборщика мусора. Вот в 64-битной версии действительно есть некоторая деградация производительности. Ее отдали авторам плюсового компилятора делать (в те времена) и у них получилось не очень хорош. Но сейчас вроде как сделали новую версию и она вполне на уровне.
4>Проблема, именно в том, что пришлось внести изменения в код при подъеме версии FW, чего я например ни разу не делал с 1.0 по 3.5 SP1
Ну, а что ты хочешь? По сути между 3.51 и 4.0 произошла смена эпох. Фактически был только 3 рантайма: 1.0, 2.0, и 4.0 (ну сейчас еще Кор есть). Остальное промежуточные версии сам рантайм затрагивающие мало. При переходе с 1.х на 2.х проблема хватало. И при переходе с 2.х на 4.х тоже. Вы еще очень легко отделались, если это единственная проблема при переносе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Регресс производительности при переходе с FW 3.5 SP1
VD> ... Ну. одна функция стала по медленнее. Никакого отношения к производительности самого дотнета это не имеет. Производительность зависит от кучи фаторов. И главное это работа компилятора (джит, нген) и сборщика мусора.
В данном случае эта функция использовалась часто, никто не говорит про .NET в целом, речь конкретно про String.IndexOf и заметно различающийся performance в зависимости от версии .NET Runtime.
VD>Ну, а что ты хочешь?
Очевидно, чтобы такого не было.
VD>При переходе с 1.х на 2.х проблема хватало.
Достаточно много кода мигрировал с 1 на 2, потом на 3/3.5, подобного особо не замечал.
VD>И при переходе с 2.х на 4.х тоже. Вы еще очень легко отделались, если это единственная проблема при переносе.
Пока перевел небольшой проект только ради возможности удобно распараллелить (Parallel LINQ) обработку достаточно больших массивов текстовых данных, чисто для экономии своего времени, пока других сюрпризов между runtime-м 2.0 и 4.0 не заметил, проект простой и судить особо не о чем.
Здравствуйте, Serginio1, Вы писали:
S> C C++ Я уже писал про CoreRT. Это наследник .Net Core. Там используется компилятор С++
Действительно приятно, что они обращают внимание на производительность, но в моем случае Core скорее противопоказан, т.к. много унаследованного (да и не только) кода цепляется за window-овое окружение. Я и так использую сторонние лайбы (иногда платные), а в случае Core мне понадобиться тащить еще больше стороннего, т.к. по очевидным причинам в погоне за мультиплатформенностью там много чего полезного нет.
Использовать Core меня пожалуй обяжет вектор на импортозамещение в моей конторе, но у меня столько унаследованного кода, что проще поменять контору.
Могу кратко рассказать, как у нас 4 года назад позанимались импортозамещением ...
Есть ряд сильно устаревших систем на FoxPro/dBase (разработка их велась еще с 96-го года), есть ряд устаревших систем использующих не реляционные (очень модные в далекие времена) БД типа Pick https://en.wikipedia.org/wiki/MultiValue (у нас где-то с 94-го), причем эти системы почти не развиваются, но все еще активно используются.
Основной же "интерпрайз" (развивающийся и активно использующийся) я заморозил на .NET 3.5 SP1 (и студия кстати 2008 SP1), а в качестве БД сейчас используется Oracle 10/11 и MSSQL 2008R2/2012. [Причем Oracle мне тоже навязали 10 лет назад, но это уже другая история.]
Так вот, этот интерпрайз также активно использует данные из БД FoxPro/dBase и Universe, к которым вероятно будет проблематично подобрать вменяемые драйвера при переходе на Core, также есть приличный объем унаследованного кода, который цепляется за WINAPI и прочее виндовое окружение.
Так вот, в конце 2016-го нужно было где-то использовать PostgreeSQL, т.к. он в рамках "импортозамещения" оказался обязателен к использованию в моем учреждении. Хочу обратить внимание, под замещением получается подразумевается — использовать, а не заместить .
Поскольку на горизонте давно маячила задача по сбору аналитики (отчеты/статистика и т.п.) из данных разбросанных по различным хранилищам (в данном случае это получается FoxPro/dBase, Universe/Pick, Oracle, MSSQL), то была создана БД PgSQL, в которую с определенным временным интервалом мигрируются необходимые данные из вышеперечисленных хранилищ. К счастью после миграции эта БД по сути ReadOnly, не считая различных логов. Отдельно стоит упомянуть страдания по выжиманию производительности из PgSQL, т.к. сколько памяти и ядер я ему не выделял, и как не помогал планировщику запросов hint-ами, но на той же машине он прилично отставал от MSSQL или Oracle. Речь идет в окрестностях 30 млн записей на таблицу, не сказать, что прям много для современного железа. Может конечно беда в том, что наши доморощенные "импортозамещенцы" развернули PgSQL на винде, а в родном НЕ виндовом окружении было-бы лучше. Не могу сказать.
В рамках вышеобозначенного вектора на импортозамещение, теперь собираются с винды переползать на "отечественный" Astra Linux.
Клиенты у меня исторически под Web (ASP.NET). Почти и так все нормально работает под Chromium-браузерами, единственный нюанс, это в ряде мест используются ActiveX-ы для работы с ЭЦП и сканером (в т.ч. сканером штрих-кодов). Для ЭЦП и так есть официальный плагин под различные браузеры, но вот для доступа к сканеру вероятно плагин прийдется писать самому. Вообщем клиентов перевести с винды, пускай и не просто, но все-таки можно.
А серверная часть это беда, т.к. под Linux, очевидным выбором будет Core, но в нём как было выше озвучено много чего нет (ибо мультиплатформенность).
Re[19]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>А серверная часть это беда, т.к. под Linux, очевидным выбором будет Core, но в нём как было выше озвучено много чего нет (ибо мультиплатформенность).
В ожидании следующего основного выпуска .NET 5 мы продолжим объединять .NET в единую платформу, включив нашу модель приложения для мобильных устройств .NET (Xamarin) в .NET 5. .NET 5 будет включать ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin и ML.NET. Впервые вся платформа будет использовать унифицированный BCL (библиотеки базовых классов) для всех моделей приложений. Наличие версии 5, которая выше, чем у .NET Core и .NET Framework, также дает понять, что .NET 5 — это будущее .NET, единой унифицированной платформы для создания приложений любого типа.
Пакет обеспечения совместимости Windows основан на .NET Standard и обеспечивает доступ к таким технологиям, которые доступны только в Windows. Это особенно полезно для клиентов, которые хотят перейти на .NET Core, но по меньшей мере на первом этапе планируют оставаться в Windows. В этом сценарии возможность использования технологий, предназначенных только для Windows, устраняет препятствия для миграции.
Т.е. это будет как с WPF, вот вам Core 3, в нем теперь есть WPF, но работать это будет только под Windows.
Меня Core интересует только в случае отказа от windows, и под тем-же Linux-ом ничего из вышеперечисленного не будет.
Re[21]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Т.е. это будет как с WPF, вот вам Core 3, в нем теперь есть WPF, но работать это будет только под Windows.
4>Меня Core интересует только в случае отказа от windows, и под тем-же Linux-ом ничего из вышеперечисленного не будет.
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, 4058, Вы писали:
4>>Т.е. это будет как с WPF, вот вам Core 3, в нем теперь есть WPF, но работать это будет только под Windows.
4>>Меня Core интересует только в случае отказа от windows, и под тем-же Linux-ом ничего из вышеперечисленного не будет.
S>Тогда есть Xamarin.Forms https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/
Так сложились обстоятельства, что .NET у нас используется преимущественно для написания различных сервисов и консолей, а клиенты у меня тонкие, чисто под браузер (не считая пару ActiveX), поэтому настольный GUI (WinForms, WPF, Xamarin.Forms) меня не интересует.
От коллег из других контор наслышан про куцость Xamarin.Forms, у них как раз клиенты толстые (или как минимум утолщенные), поэтому они попробовали.
4>Т.е. это будет как с WPF, вот вам Core 3, в нем теперь есть WPF, но работать это будет только под Windows.
S>Да только при этом будуи использоваться библиотеки только .Net Standard и соответственно компилятор коровский
Повторюсь, Core имеет смысл использовать там, где нет возможности использовать Windows.
Использовать Core под Windows для меня выглядит нелогичным, типа давайте перейдем на Core просто так.
Re[23]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>От коллег из других контор наслышан про куцость Xamarin.Forms, у них как раз клиенты толстые (или как минимум утолщенные), поэтому они попробовали.
Ну они развиваются. https://github.com/xamarin/Xamarin.Forms/wiki/Feature-Roadmap
Конечно до уровня WPF им будет далеко.
4>Повторюсь, Core имеет смысл использовать там, где нет возможности использовать Windows. 4>Использовать Core под Windows для меня выглядит нелогичным, типа давайте перейдем на Core просто так.
Просто .Net Framework развиваться не будет. Ну по твоим 3.5, я так понимаю тебе не особо то и нужно.
Лет на 10 хватит
и солнце б утром не вставало, когда бы не было меня
Re[24]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, Serginio1, Вы писали:
S>Конечно до уровня WPF им будет далеко.
Xamarin изначально ориентировался как кроссплатформенный GUI под мобильные устройства, а там по очевидным причинам потребности существенно ниже чем к настольному.
S> Просто .Net Framework развиваться не будет. Ну по твоим 3.5, я так понимаю тебе не особо то и нужно. S>Лет на 10 хватит
Другое дело, что заставят подниматься намного раньше, например если какой-нибудь новый Windows Server не будет его поддерживать, или просто планы поменяются, да еще со всех сторон слушать, о том какой я не модный, если не могу например использовать "фишки" C# 4-8.
Тут еще важно понимать, что вкладывать в термин — развитие.
По факту мне как бывшему C++-нику в 1.0/1.1 сильно не хватало хоть какой-нибудь параметризации типов, в 2.0 я получил generic-и + анонимные делегаты, nullable, в 3.0 получил лямбды, var, и вполне интересный LINQ (но тут скорее про библиотеку, а не синтаксический сахар накрученный поверх библиотеки). Это было весьма органичное развитие полезностями как библиотек, так и самого языка.
На 4.0 особо ничего не приглядел, кроме пожалуй более удобных способов для работы с многопоточностью.
Поэтому стоит выделить, раньше развитие шло для решения вполне насущных задач, а потом оно по большей части пошло ради самого процесса.
Re[25]: Регресс производительности при переходе с FW 3.5 SP1
Здравствуйте, 4058, Вы писали:
4>Тут еще важно понимать, что вкладывать в термин — развитие. 4>По факту мне как бывшему C++-нику в 1.0/1.1 сильно не хватало хоть какой-нибудь параметризации типов, в 2.0 я получил generic-и + анонимные делегаты, nullable, в 3.0 получил лямбды, var, и вполне интересный LINQ (но тут скорее про библиотеку, а не синтаксический сахар накрученный поверх библиотеки). Это было весьма органичное развитие полезностями как библиотек, так и самого языка. 4>На 4.0 особо ничего не приглядел, кроме пожалуй более удобных способов для работы с многопоточностью.
4>Поэтому стоит выделить, раньше развитие шло для решения вполне насущных задач, а потом оно по большей части пошло ради самого процесса.
Здравствуйте, 4058, Вы писали:
4>Из этого следует, что переход с Unicode 5.0 (FW 3.5) на 5.1 (FW 4.0) выдаёт регресс производительности для локалезависимых операций в 2.7 раза?
...или же делает это более верно идеологически. За что приходится платить производительностью.
Вообще, тема сравнения строк — это из серии мемчиков "когда мне было 4 года, моей сестре было 2, сейчас мне 44, а сколько моей сестре?". Т.е. очевидный ответ оказывается далеко не единственно возможным, и эти прочие варианты настолько зубодробительны, что вместо функции-однострочника появляется едва ли не отдельный SDK. Одни только эмоджики чего стоят, с их расширенными атрибутами.