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

Сообщение Re[28]: Реальная производительность WebAssembly? от 19.09.2017 16:22

Изменено 19.09.2017 16:30 alexzzzz

Re[28]: Реальная производительность WebAssembly?
Убрал два косяка предыдущей версии (на скорость не влияли) и ещё ускорил. Пробовал заменить TestClass на TestStruct, но тут это ничего не даёт, разве что чуть экономит память.

  C#
using System;
using System.Diagnostics;
using System.Threading;

namespace QuickSort
{
    public class Program
    {
        private static int activeThreadCount;
        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++)
            {
                GC.Collect();
                watch.Restart();
                waitHandle.Reset();

                var vals = new TestClass[ARRAY_SIZE];
                activeThreadCount = 4;
                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)
        {
            int end = start + count;
            for (int i = start; i < end; i++)
            {
                array[i] = new TestClass();
            }

            Interlocked.Decrement(ref activeThreadCount);
            if (activeThreadCount == 0)
            {
                waitHandle.Set();
            }
        }
    }

    internal class TestClass
    {
        public string Id = CreateGuid();
        public string Value = CreateGuid();
        private static ThreadLocal<Random> localRandom = new ThreadLocal<Random>(() => new Random());

        public override string ToString() => Id;

        private static unsafe string CreateGuid()
        {
            var num = localRandom.Value.Next(100_000_000);
            var chars = stackalloc char[11]; // null-terminated 10-char string
            chars[0] = '0';
            chars[1] = '0';
            chars[2] = (char)('0' + num % 10); num /= 10;
            chars[3] = (char)('0' + num % 10); num /= 10;
            chars[4] = (char)('0' + num % 10); num /= 10;
            chars[5] = (char)('0' + num % 10); num /= 10;
            chars[6] = (char)('0' + num % 10); num /= 10;
            chars[7] = (char)('0' + num % 10); num /= 10;
            chars[8] = (char)('0' + num % 10); num /= 10;
            chars[9] = (char)('0' + num % 10);
            return new string(chars);
        }
    }
}

Total: 195 ms
Total: 177 ms
Total: 179 ms
Total: 169 ms
Total: 189 ms
GC: 113 46 13
Re[28]: Реальная производительность WebAssembly?
Убрал два косяка предыдущей версии (на скорость не влияли) и ещё ускорил. Пробовал заменить TestClass на TestStruct, но тут это ничего не даёт, разве что чуть экономит память. Ещё воткнул GC.Collect между итерациями, т.к. надоело видеть первую итерацию самой быстрой.

  C#
using System;
using System.Diagnostics;
using System.Threading;

namespace QuickSort
{
    public class Program
    {
        private static int activeThreadCount;
        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++)
            {
                GC.Collect();
                watch.Restart();
                waitHandle.Reset();

                var vals = new TestClass[ARRAY_SIZE];
                activeThreadCount = 4;
                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)
        {
            int end = start + count;
            for (int i = start; i < end; i++)
            {
                array[i] = new TestClass();
            }

            Interlocked.Decrement(ref activeThreadCount);
            if (activeThreadCount == 0)
            {
                waitHandle.Set();
            }
        }
    }

    internal class TestClass
    {
        public string Id = CreateGuid();
        public string Value = CreateGuid();
        private static ThreadLocal<Random> localRandom = new ThreadLocal<Random>(() => new Random());

        public override string ToString() => Id;

        private static unsafe string CreateGuid()
        {
            var num = localRandom.Value.Next(100_000_000);
            var chars = stackalloc char[11]; // null-terminated 10-char string
            chars[0] = '0';
            chars[1] = '0';
            chars[2] = (char)('0' + num % 10); num /= 10;
            chars[3] = (char)('0' + num % 10); num /= 10;
            chars[4] = (char)('0' + num % 10); num /= 10;
            chars[5] = (char)('0' + num % 10); num /= 10;
            chars[6] = (char)('0' + num % 10); num /= 10;
            chars[7] = (char)('0' + num % 10); num /= 10;
            chars[8] = (char)('0' + num % 10); num /= 10;
            chars[9] = (char)('0' + num % 10);
            return new string(chars);
        }
    }
}

Total: 195 ms
Total: 177 ms
Total: 179 ms
Total: 169 ms
Total: 189 ms
GC: 113 46 13