Ответы пользователя по тегу Unity
  • Как считать время у большого количества объектов?

    AleksejMsk
    @AleksejMsk
    Программирую от души за деньги
    У меня есть готовая реализации (thread safe) когда надо найти объекты с временем жизни среди миллионов с минимальным расходованием CPU.
    Nuget https://www.nuget.org/packages/ShtrihM.Wattle3.Con...

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    using NUnit.Framework;
    using ShtrihM.Wattle3.Containers.DateTimeCollections;
    using ShtrihM.Wattle3.DomainObjects;
    using ShtrihM.Wattle3.DomainObjects.Common;
    
    namespace ShtrihM.Wattle3.Tests.DomainObjects.TestsContainers;
    
    [TestFixture]
    public class TestsDateTimeEntries
    {
        public class DateTimeEntry : IDateTimeEntry
        {
            public static long CountCanTake;
    
            public DateTimeEntry(DateTime point, long identity)
            {
                Point = point;
                Identity = identity;
            }
    
            public bool CanTake(DateTime takePoint)
            {
                Interlocked.Increment(ref CountCanTake);
    
                var result = Point <= takePoint;
    
                return result;
            }
    
            public DateTime Point { get; }
            public long Identity { get; }
        }
    
        [Test]
        [TestCase(1_000_000, 1)]
        [TestCase(1_000_000, 2)]
        [TestCase(1_000_000, 1_0)]
        [TestCase(1_000_000, 1_00)]
        [TestCase(1_000_000, 1_000)]
        [TestCase(1_000_000, 1_00_000)]
        public void Test_Metrics(int size, int factor)
        {
            var instance =
                new DateTimeEntries<DateTimeEntry>(
                    new LocksPoolAsync<long>(
                        Guid.NewGuid(),
                        "Test",
                        "Test",
                        new TimeService()));
            var entries = new ConcurrentDictionary<long, DateTimeEntry>(Environment.ProcessorCount, size);
            var startPoint = new DateTime(2023, 5, 5, 5, 5, 5);
            Parallel.For(0, size,
                i =>
                {
                    var point = startPoint.AddMinutes(i);
                    var temp = new DateTimeEntry(point, i);
                    Assert.IsTrue(instance.TryAdd(point, temp));
                    Assert.IsTrue(entries.TryAdd(temp.Identity, temp));
                });
    
            // ReSharper disable once PossibleLossOfFraction
            var point = startPoint.AddMinutes(size / factor - 1);
    
            Console.WriteLine($"Элементов : {size}");
            Console.WriteLine($"Выбор первых : {size / factor}");
            Console.WriteLine();
            Console.WriteLine("DateTimeEntries :");
            var sw = Stopwatch.StartNew();
            DateTimeEntry.CountCanTake = 0;
            var items = instance.Take(point, false);
            sw.Stop();
            Assert.AreEqual(size / factor, items.Count);
            Console.WriteLine($"Count = {items.Count}");
            Console.WriteLine($"Time = {sw.Elapsed}");
            Console.WriteLine($"CanTake = {DateTimeEntry.CountCanTake}");
    
            Console.WriteLine();
            Console.WriteLine("ConcurrentDictionary + Parallel.ForEach :");
            sw = Stopwatch.StartNew();
            DateTimeEntry.CountCanTake = 0;
            items = new List<DateTimeEntry>(size);
            Parallel.ForEach(entries,
                @entry =>
                {
                    if (false == @entry.Value.CanTake(point))
                    {
                        return;
                    }
    
                    lock (items)
                    {
                        items.Add(@entry.Value);
                    }
                });
            sw.Stop();
            Assert.AreEqual(size / factor, items.Count);
            Console.WriteLine($"Count = {items.Count}");
            Console.WriteLine($"Time = {sw.Elapsed}");
            Console.WriteLine($"CanTake = {DateTimeEntry.CountCanTake}");
        }
    }
    Ответ написан
    Комментировать