class Program
{
static void Main(string[] args)
{
var num = 10_000_000;
{
var watch = Stopwatch.StartNew();
var data = new TestClass[num];
for (var i = 0; i < data.Length; i++)
{
data[i] = new TestClass
{
Number0 = 10,
Number1 = 20,
};
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
}
{
var watch = Stopwatch.StartNew();
var data = new TestStruct[num];
for (var i = 0; i < data.Length; i++)
{
data[i].Number0 = 10;
data[i].Number1 = 20;
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
}
}
struct TestStruct
{
public long Number0;
public long Number1;
public long Temp0;
public long Temp1;
public long Temp2;
public long Temp3;
public long Temp4;
public long Temp5;
public long Temp6;
public long Temp7;
}
class TestClass
{
public long Number0;
public long Number1;
public long Temp0;
public long Temp1;
public long Temp2;
public long Temp3;
public long Temp4;
public long Temp5;
public long Temp6;
public long Temp7;
}
}
GC.TryStartNoGCRegion(10_000_000 * 128, true);
var watch = Stopwatch.StartNew();
var data = new TestClass[num];
for (var i = 0; i < data.Length; i++)
{
data[i] = new TestClass
{
Number0 = 10,
Number1 = 20,
};
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
GC.EndNoGCRegion();
Здравствуйте, vorona, Вы писали:
V>У меня получилось V>0,4047961 V>0,2600024
А у меня получилось
System.ArgumentOutOfRangeException: 'totalSize is too large. For more information about setting the maximum size, see "Latency Modes" in http://go.microsoft.com/fwlink/?LinkId=522706
Parameter name: totalSize'
Профайлер вам в помощь.
Но если гадать, ставлю на очевидное -- выделение места по экземпляр ссылочного типа.
Еще, вероятно, запись в поле элемента массива быстрее, чем в объект. Оно вроде бы делается через "ссылку на экзепляр" ссылочного типа.
Здравствуйте, CodeMonkey, Вы писали:
CM>А чего там делать то так долго? Обнулить нужное количество памяти, поинкрементить указатель на свободное место. Всё.
Не все. У тебя 10_000_000 * 80 байт. Вспоминаем про виртуальную память, так как реальная память выделяется по мере необходимости.
Второй прогон по идее должен быть быстрее после сборки мусора, если GC оставит память зарезервированной.
и солнце б утром не вставало, когда бы не было меня
Помоему очевидно, в первом цикле есть постоянное дергание new что достаточно дорогая операция по сравнению с доступом по индексу и копированием long, во втором нету.
Второй момент структуры оптимизируются под стек насколько мне известно и даже если структура будет во втором цикле не явно создаваться, то пара процессорных операций со стеком аля push будет дешевле, чем целая логика менеджера памяти который работает с кучей. Не утверждаю что все именно так, не проверял.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
CM>System.ArgumentOutOfRangeException: 'totalSize is too large. For more information about setting the maximum size, see "Latency Modes" in http://go.microsoft.com/fwlink/?LinkId=522706
CM>Parameter name: totalSize'
Здравствуйте, okon, Вы писали:
O>Второй момент структуры оптимизируются под стек насколько мне известно и даже если структура будет во втором цикле не явно создаваться, то пара процессорных операций со стеком аля push будет дешевле, чем целая логика менеджера памяти который работает с кучей. Не утверждаю что все именно так, не проверял.
CM>А чего там делать то так долго? Обнулить нужное количество памяти, поинкрементить указатель на свободное место. Всё.
Это не долго. Но в первом варианте не надо делать _вообще_ ничего.
Здравствуйте, CodeMonkey, Вы писали:
CM>Здравствуйте, Serginio1, Вы писали:
S>> Второй прогон по идее должен быть быстрее после сборки мусора, если GC оставит память зарезервированной.
CM>Ни фига подобного, получается даже медленнее.
Тогда проблема со сборкой мусора как правильно указал vorona GC.TryStartNoGCRegion(10_000_000 * 128, true);
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, CodeMonkey, Вы писали:
CM>Здравствуйте, Serginio1, Вы писали:
S>> Тогда проблема со сборкой мусора как правильно указал vorona GC.TryStartNoGCRegion(10_000_000 * 128, true);
CM>Вполне возможно, но почему?
Сборка мусора возникает при выполнении одного из следующих условий:
Память, используемая объектами, выделенными в управляемой куче, превышает допустимый порог. Этот порог непрерывно корректируется во время выполнения процесса.
Там же про Эфемерные поколения и сегменты
и еще про параллелизмом
Для компьютера с одним процессором всегда используется сборка мусора рабочей станции, независимо от значения элемента <gcServer>. Если задана сборка мусора сервера, среда CLR использует сборку мусора рабочей станции с выключенным параллелизмом.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Условия для сборки мусора
S>
S>Сборка мусора возникает при выполнении одного из следующих условий:
S>Память, используемая объектами, выделенными в управляемой куче, превышает допустимый порог. Этот порог непрерывно корректируется во время выполнения процесса.
S>Там же про Эфемерные поколения и сегменты
S> и еще про параллелизмом
S>
S>Для компьютера с одним процессором всегда используется сборка мусора рабочей станции, независимо от значения элемента <gcServer>. Если задана сборка мусора сервера, среда CLR использует сборку мусора рабочей станции с выключенным параллелизмом.