Информация об изменениях

Сообщение Re[5]: почему так медленно? от 11.06.2019 16:24

Изменено 11.06.2019 16:28 alexzzzz

Re[5]: почему так медленно?
Здравствуйте, CodeMonkey, Вы писали:

CM>Не 2/3, а 32% согласно профайлеру. Разницу в разы это не объясняет.


У меня заходит за 60%.

A>>Получается, рантайм NET Framework такой умный, что знает, что Windows отдаёт процессу уже занулённые страницы, поэтому самостоятельно массив нулями не инициализирует.

CM>Не такой и умный, если это просаживает производительность.

Так наоборот же. Рантайм не тратит время на то, что и так было сделано. В таком же тесте классов ошибок страниц в 1,5 раза больше, они просто не включались в измерения.

  C#
using System;
using System.Diagnostics;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var num = 10_000_000;
        var processName = Process.GetCurrentProcess().ProcessName;
        var pageFaultsCounter = new PerformanceCounter("Process", "Page Faults/sec", processName);

        {
            var data = new TestClass[num];
            Console.WriteLine($"1) {pageFaultsCounter.RawValue} page faults");

            //PrintGCollections();
            for (var i = 0; i < data.Length; i++)
            {
                data[i] = new TestClass();
            }
            //PrintGCollections();
            Console.WriteLine($"2) {pageFaultsCounter.RawValue} page faults");

            var watch = Stopwatch.StartNew();
            for (var i = 0; i < data.Length; i++)
            {
                data[i].Number0 = 10;
                data[i].Number1 = 20;
            }
            watch.Stop();
            Console.WriteLine($"3) {pageFaultsCounter.RawValue} page faults");
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }

        {
            var data = new TestStruct[num];
            Console.WriteLine($"1) {pageFaultsCounter.RawValue} page faults");

            Array.Clear(data, 0, data.Length);
            Console.WriteLine($"2) {pageFaultsCounter.RawValue} page faults");

            var watch = Stopwatch.StartNew();
            for (var i = 0; i < data.Length; i++)
            {
                data[i].Number0 = 10;
                data[i].Number1 = 20;
            }
            watch.Stop();
            Console.WriteLine($"3) {pageFaultsCounter.RawValue} page faults");
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }
    }

    private static void PrintGCollections()
    {
        Console.WriteLine("GC: " + string.Join(", ", Enumerable.Range(0, GC.MaxGeneration + 1).Select(GC.CollectionCount)));
    }

    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;
    }
}

1) 36837 page faults
2) 345167 page faults
3) 345640 page faults
0,1460079
1) 350326 page faults
2) 546109 page faults
3) 546580 page faults
0,1018719


Структуры стабильно быстрее.
Re[5]: почему так медленно?
Здравствуйте, CodeMonkey, Вы писали:

CM>Не 2/3, а 32% согласно профайлеру. Разницу в разы это не объясняет.


У меня заходит за 60%.

A>>Получается, рантайм NET Framework такой умный, что знает, что Windows отдаёт процессу уже занулённые страницы, поэтому самостоятельно массив нулями не инициализирует.

CM>Не такой и умный, если это просаживает производительность.

Так наоборот же. Рантайм не тратит время на то, что и так было сделано. В таком же тесте классов ошибок страниц в 1,5 раза больше, потому что памяти требуется больше, они просто не включались в измерения.

  C#
using System;
using System.Diagnostics;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var num = 10_000_000;
        var processName = Process.GetCurrentProcess().ProcessName;
        var pageFaultsCounter = new PerformanceCounter("Process", "Page Faults/sec", processName);

        {
            var data = new TestClass[num];
            Console.WriteLine($"1) {pageFaultsCounter.RawValue} page faults");

            //PrintGCollections();
            for (var i = 0; i < data.Length; i++)
            {
                data[i] = new TestClass();
            }
            //PrintGCollections();
            Console.WriteLine($"2) {pageFaultsCounter.RawValue} page faults");

            var watch = Stopwatch.StartNew();
            for (var i = 0; i < data.Length; i++)
            {
                data[i].Number0 = 10;
                data[i].Number1 = 20;
            }
            watch.Stop();
            Console.WriteLine($"3) {pageFaultsCounter.RawValue} page faults");
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }

        {
            var data = new TestStruct[num];
            Console.WriteLine($"1) {pageFaultsCounter.RawValue} page faults");

            Array.Clear(data, 0, data.Length);
            Console.WriteLine($"2) {pageFaultsCounter.RawValue} page faults");

            var watch = Stopwatch.StartNew();
            for (var i = 0; i < data.Length; i++)
            {
                data[i].Number0 = 10;
                data[i].Number1 = 20;
            }
            watch.Stop();
            Console.WriteLine($"3) {pageFaultsCounter.RawValue} page faults");
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }
    }

    private static void PrintGCollections()
    {
        Console.WriteLine("GC: " + string.Join(", ", Enumerable.Range(0, GC.MaxGeneration + 1).Select(GC.CollectionCount)));
    }

    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;
    }
}

1) 36837 page faults
2) 345167 page faults
3) 345640 page faults
0,1460079
1) 350326 page faults
2) 546109 page faults
3) 546580 page faults
0,1018719


Структуры стабильно быстрее.