Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, Serginio1, Вы писали:
S>>Лучше взять эти тесты
I>О, круто, вот то что надо! И ты, конечно, портируешь их на JS, дабы мы могли созерцать разницу в перформансе ?
public class Test
{
public static void Main()
{
while (true)
{
var q = new Queue<int>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 100_000_000; i++)
{
q.Enqueue(i);
q.Dequeue();
}
Console.WriteLine(sw.Elapsed);
}
}
}
его трудно на TS перевести?
Кстати а как в Node.js с многопоточностью? Можно еще и parallel foreach проверить
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, Serginio1, Вы писали:
S>>первый тест I>... S>> его трудно на TS перевести?
I>Трудно, у тебя же на это времени нет, правильно ?
Нет. Просто вы тратите время, а я предложил варианты.
Ну не надо, так не надо
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Ikemefula, Вы писали:
A>>Оптимизированная версия C#: I> а зачем ты убрал сам алгоритм ? Мы же не сравниваем библиотеки. Вопрос в том, насколько качественный код будет выполняться.
Никуда я его не убрал, а исправил на качественную реализацию:
Array.Sort(vals, new TestClass.TestClassComparer());
Я ж не буду "библиотечный" ToString переписывать на голом C# без необходимости. И Array.Sort не буду, если моя реализация сортировки для конкретной задачи не окажется вдруг эффективнее. В реальном проекте я естественно выкину 30 строк нетривиального кода и заменю на одну тривиальную, если она не медленнее. А если быстрее, так вообще отлично. Постоянно так делаю.
A>>Одинаково. I>Да, серьезный тест, практичный и реальный.
Ну какой был. Его даже обсуждали тут и пытались делать выводы. Проверил из любопытства, хотел найти косяк. Нашёл.
A>>1. Я не вижу в коде никого, кому были бы нужны строковые представления гуидов. Ни одного их потребителя. Разве что TestClass.ToString, но и тот нигде не вызывается. A>>2. Guid — value-тип длинной 16 байт. В виде строки он занимает (навскидку) 32*2+6 байт + оверхед + 4/8 байт под ссылку на эту строку. Гуиды экономнее аналогичных строк раз в пять. I>А что, конверсия в строку при каждом доступе ничего не стоит ?
Конверсия в строку ничего не стоит, если она никогда не происходит. А тут она никогда не происходит.
I>Кроме того, в тесте ведь не важно, что в строке. Главное что бы одинаково в обоих языках и были более-менее случайные символы.
В тесте важна скорость получения результата. У исходной программы на входе ничего нет, а на выходе упорядоченная коллекция элементов, состоящих из двух гуидов, отсортированая по первому гуиду. И раз там гуиды, сравнивать их в виде строк довольно глупо, я считаю.
Если бы там были строки, содержащие не гуиды, а что-то другое (например, автомобильные номера), я бы тоже делал сортировку с учётом этого знания.
I>Тест он про сортировку массива объектов, у которых есть строковые свойства. Гуиды там или не гуиды, дело десятое.
В строках всегда содержится что-то конкретное. Как минимум, обычно заранее понятно, нужна для их сортировки культура или не нужна.
Здравствуйте, Serginio1, Вы писали:
S> Там код на TS один в один C# повский. При этом кода то всего раз два и обчелся. Возьми хотя бы S>http://rsdn.org/forum/dotnet/6808392.1
S>public class Test
S>{
S> public static void Main()
S> {
S> while (true)
S> {
S> var q = new Queue<int>();
S> var sw = Stopwatch.StartNew();
S> for (int i = 0; i < 100_000_000; i++)
S> {
S> q.Enqueue(i);
S> q.Dequeue();
S> }
S> Console.WriteLine(sw.Elapsed);
S> }
S> }
S>}
S>
S> его трудно на TS перевести?
Это микробенчмарки. Они дают приблизительно понять, сколько стоит то или иное действие; что более эффективнее, что менее. Такие тесты, не выполняющие полезной работы, интересны в рамках одного языка. У меня рука так и тянется выкинуть внутренний цикл нафик, потому что работать будет быстрее, а для внешнего наблюдателя ничего не изменится.
A>Это микробенчмарки. Они дают приблизительно понять, сколько стоит то или иное действие; что более эффективнее, что менее. Такие тесты, не выполняющие полезной работы, интересны в рамках одного языка. У меня рука так и тянется выкинуть внутренний цикл нафик, потому что работать будет быстрее, а для внешнего наблюдателя ничего не изменится.
как раз работа с очередями, коллекциями одни из основных рабочих алгоритмов.
Заметь на сколько они быстрее в .Net Core
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали: S> Кстати а как в Node.js с многопоточностью? Можно еще и parallel foreach проверить
Как в Node.js не знаю, а в C# как раз собирался проверить:
C#
using System;
using System.Diagnostics;
using System.Linq;
namespace QuickSort
{
public class Program
{
public static void Main(string[] args)
{
var watch = new Stopwatch();
for (int i = 0; i < 5; i++)
{
watch.Restart();
var vals = Enumerable.Range(0, 1000 * 1000).AsParallel().Select(x => new TestClass()).ToArray();
watch.Stop();
Console.WriteLine("Total secs: " + watch.Elapsed.TotalSeconds);
}
Console.WriteLine($"GC: {GC.CollectionCount(0)} {GC.CollectionCount(1)} {GC.CollectionCount(2)}");
Console.ReadLine();
}
}
internal class TestClass
{
public string Id = CreateGuid();
public string Value = CreateGuid();
private static readonly Random gen = new Random();
private static string CreateGuid() => gen.Next(100000000).ToString("0000000000");
}
}
Total secs: 0,2958201
Total secs: 0,398753
Total secs: 0,3198091
Total secs: 0,4641866
Total secs: 0,4886261
GC: 109 41 8
4-ядерник без гипертрединга. Большой разброс на таком коротком тесте. Первый результат стабильно 0.30±0.01, а дальше пляшет.
Здравствуйте, alexzzzz, Вы писали:
A>Здравствуйте, Serginio1, Вы писали:
S>> Кстати а как в Node.js с многопоточностью? Можно еще и parallel foreach проверить
A>Как в Node.js не знаю, а в C# как раз собирался проверить:
A>Total secs: 0,2958201 A>Total secs: 0,398753 A>Total secs: 0,3198091 A>Total secs: 0,4641866 A>Total secs: 0,4886261 A>GC: 109 41 8
A>4-ядерник без гипертрединга. Большой разброс на таком коротком тесте. Первый результат стабильно 0.30±0.01, а дальше пляшет.
То есть если сравнивать с
Total: 567 ms
Total: 652 ms
Total: 641 ms
Total: 606 ms
Total: 638 ms
То максимальный прирост в 2 раза?
Ну это нормально. Там процессор еще на чтонибудь расходуется.
Спасибо!
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, alexzzzz, Вы писали:
A>>>Оптимизированная версия C#: I>> а зачем ты убрал сам алгоритм ? Мы же не сравниваем библиотеки. Вопрос в том, насколько качественный код будет выполняться.
A>Никуда я его не убрал, а исправил на качественную реализацию: A>
Array.Sort(vals, new TestClass.TestClassComparer());
Это другой тест, он показыавет, какая из библиотечных функций качественнее сделана.
А предыдущий показывал какой из компилеров даёт более качественный код.
A>>>1. Я не вижу в коде никого, кому были бы нужны строковые представления гуидов. Ни одного их потребителя. Разве что TestClass.ToString, но и тот нигде не вызывается. A>>>2. Guid — value-тип длинной 16 байт. В виде строки он занимает (навскидку) 32*2+6 байт + оверхед + 4/8 байт под ссылку на эту строку. Гуиды экономнее аналогичных строк раз в пять. I>>А что, конверсия в строку при каждом доступе ничего не стоит ?
A>Конверсия в строку ничего не стоит, если она никогда не происходит. А тут она никогда не происходит.
Ага, ты сравниваешь гуиды. Так ? То есть, вместо "объект со строковыми филдами" ты влупил другой тест "объект с гуидами"
То есть, ты подменяешь яблоки грушами.
I>>Кроме того, в тесте ведь не важно, что в строке. Главное что бы одинаково в обоих языках и были более-менее случайные символы.
A>В тесте важна скорость получения результата. У исходной программы на входе ничего нет, а на выходе упорядоченная коллекция элементов, состоящих из двух гуидов, отсортированая по первому гуиду. И раз там гуиды, сравнивать их в виде строк довольно глупо, я считаю.
Оригинальный код принимает на вход данные в виде массива объектов со строковыми филдами.
Ты поменял данные в пользу C# версии.
A>Если бы там были строки, содержащие не гуиды, а что-то другое (например, автомобильные номера), я бы тоже делал сортировку с учётом этого знания.
Это всё разные тесты, груши и яблоки. Ты подгоняешь данные под сам тест.
I>>Тест он про сортировку массива объектов, у которых есть строковые свойства. Гуиды там или не гуиды, дело десятое. A>В строках всегда содержится что-то конкретное. Как минимум, обычно заранее понятно, нужна для их сортировки культура или не нужна.
В тестах принято входные данные не изменять, не подгонять под нужный результат.
Здравствуйте, alexzzzz, Вы писали:
A>Это микробенчмарки. Они дают приблизительно понять, сколько стоит то или иное действие; что более эффективнее, что менее. Такие тесты, не выполняющие полезной работы, интересны в рамках одного языка. У меня рука так и тянется выкинуть внутренний цикл нафик, потому что работать будет быстрее, а для внешнего наблюдателя ничего не изменится.
Даже с разными языками можно сравнивать, главное данные не подгонять под тест.
Здравствуйте, Serginio1, Вы писали: S> То максимальный прирост в 2 раза? S> Ну это нормально. Там процессор еще на чтонибудь расходуется.
Я на компьютере, где это выполняется, ещё сижу из-под Тимвьюера. Вот ещё вариант. Страшненький, но побыстрее и постабильнее:
C#
using System;
using System.Diagnostics;
using System.Threading;
namespace QuickSort
{
public class Program
{
private static int threadCount;
private static ManualResetEvent waitHandle = new ManualResetEvent(false);
public static void Main(string[] args)
{
const int ARRAY_SIZE = 1000 * 1000;
const int THREADS = 4;
var watch = new Stopwatch();
for (var i = 0; i < 5; i++)
{
watch.Restart();
waitHandle.Reset();
var vals = new TestClass[ARRAY_SIZE];
for (var j = 0; j < THREADS; j++)
{
int segmentIndex = j;
ThreadPool.QueueUserWorkItem(_ => Fill(vals, segmentIndex * (ARRAY_SIZE / THREADS), ARRAY_SIZE / THREADS));
}
waitHandle.WaitOne();
watch.Stop();
Console.WriteLine($"Total: {watch.ElapsedMilliseconds} ms");
}
Console.WriteLine($"GC: {GC.CollectionCount(0)} {GC.CollectionCount(1)} {GC.CollectionCount(2)}");
Console.ReadLine();
}
private static void Fill(TestClass[] array, int start, int count)
{
Interlocked.Increment(ref threadCount);
int end = start + count;
for (int i = start; i < end; i++)
{
array[i] = new TestClass();
}
Interlocked.Decrement(ref threadCount);
if (threadCount == 0)
{
waitHandle.Set();
}
}
}
internal class TestClass
{
public string Id = CreateGuid();
public string Value = CreateGuid();
private static readonly Random gen = new Random();
private static string CreateGuid() => gen.Next(100000000).ToString("0000000000");
}
}
Total: 302 ms
Total: 262 ms
Total: 368 ms
Total: 359 ms
Total: 384 ms
GC: 109 41 7
Здравствуйте, Ikemefula, Вы писали:
A>>Никуда я его не убрал, а исправил на качественную реализацию: A>>
Array.Sort(vals, new TestClass.TestClassComparer());
I> Это другой тест, он показыавет, какая из библиотечных функций качественнее сделана. I>А предыдущий показывал какой из компилеров даёт более качественный код.
Это тот же самый тест, решающий ту же самую задачу — сгенерировать из ничего упорядоченную коллекцию. На исполняемый код насрать. Он нужен, чтобы решить задачу, больше он ни зачем не нужен. Чем кода меньше, чем он быстрее работает, тем всегда лучше.
Если стоит задача из положения планет на небе получить число 42, её правильное решение на C# будет выглядеть так:
int Solve(input) => 42;
A>>Конверсия в строку ничего не стоит, если она никогда не происходит. А тут она никогда не происходит. I>Ага, ты сравниваешь гуиды. Так ? То есть, вместо "объект со строковыми филдами" ты влупил другой тест "объект с гуидами" I>То есть, ты подменяешь яблоки грушами.
Я вижу, что на входе программы ничего нет, а на выходе отсортированные гуиды. Конечно буду использовать гуиды вместо строк. Если там целые числа, буду использовать целые числа. Это понятнее и тупо эффективнее.
I>Оригинальный код принимает на вход данные в виде массива объектов со строковыми филдами. I>Ты поменял данные в пользу C# версии.
Оригинальный код измеряет время генерирования данных и их последующей обработки. Мы же смотрим на один и тот же код? На входе программы данных нет, на выходе как бы есть.
I>В тестах принято входные данные не изменять, не подгонять под нужный результат.
Входных данных нет. Время генерирования данных включено в измерения.
Здравствуйте, alex_public, Вы писали:
A>>Одинаково. _>Подтверждаю. Для данного C# кода и данного JS кода, запущенного через node, у меня очень близкие цифры. _>Только вот теперь рекомендую запустить этот же самый JS код в Firefox. Например с помощью такой странички:
Здравствуйте, alexzzzz, Вы писали:
_>>Подтверждаю. Для данного C# кода и данного JS кода, запущенного через node, у меня очень близкие цифры. _>>Только вот теперь рекомендую запустить этот же самый JS код в Firefox. Например с помощью такой странички:
A>
Хм, странно, у меня ни одного значение более 300 мс нет. Похоже у нас всё же разные по производительности компьютеры и разные .net рантаймы (в начале из-за большого совпадения предыдущих цифр я подумал что одинаковые).
Кстати, я тут ради развлечения засунул этот вроде как тест в C++, чтобы оценить насколько обсуждаемые языки отстают от максимальной производительности. И оказалось что не так уж и сильно. С конвертером строк из стандартной библиотеки получаем 130 мс. С быстрым конвертером из Boost'а получаем 70 мс, но это уже наверное "чит" (в обсуждаемых вариантах использовали только стандартную функцию).
_>Кстати, я тут ради развлечения засунул этот вроде как тест в C++, чтобы оценить насколько обсуждаемые языки отстают от максимальной производительности. И оказалось что не так уж и сильно. С конвертером строк из стандартной библиотеки получаем 130 мс. С быстрым конвертером из Boost'а получаем 70 мс, но это уже наверное "чит" (в обсуждаемых вариантах использовали только стандартную функцию).
Еще раз не языки, а платформы. Тот же C# в трех платформах. .Net, .Net Core и Net Native. Там и компиляторы разные и CLR и без CLR
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, alex_public, Вы писали:
_>Хм, странно, у меня ни одного значение более 300 мс нет. Похоже у нас всё же разные по производительности компьютеры и разные .net рантаймы (в начале из-за большого совпадения предыдущих цифр я подумал что одинаковые).
Core i5-2500K @4ГГц, рантаймы всякие есть, я запускал всё под Framework 4.0 в режиме x64.
Здравствуйте, alexzzzz, Вы писали:
_>>Хм, странно, у меня ни одного значение более 300 мс нет. Похоже у нас всё же разные по производительности компьютеры и разные .net рантаймы (в начале из-за большого совпадения предыдущих цифр я подумал что одинаковые). A>Core i5-2500K @4ГГц, рантаймы всякие есть, я запускал всё под Framework 4.0 в режиме x64.
Хм, по идее не должно сильно отличаться. Ладно, мне что-то наскучило гадать, как и вообще вся эта темка. Просто покажу голые результаты всех этих тестов на своей машине, а кто хочет — пускай анализирует и разбирается. )))
C# (.Net 4.6.0081.0 x64):
Total secs: 0,5065547
Total secs: 0,6101966
Total secs: 0,5638938
Total secs: 0,5944783
Total secs: 0,6446389