示例#1
0
        public async Task Start(IDictionary <string, List <string> > args)
        {
            await Task.Delay(0);

            if (args.ContainsKey("+all"))
            {
                args.Add("-store", new List <string>()
                {
                    "mh", "mmf", "nh"
                });
            }

            args.AssertAll("-store");
            var opt = args["-store"];

            opt.AssertNothingOutsideThese("mh", "mmf", "nh");

            var allocArgs = new AllocTestArgs()
            {
                Count                  = 5,
                Size                   = 5_000_000,
                InParallel             = 2,
                RandomizeAllocDelay    = true,
                RandomizeFragDisposal  = false,
                RandomizeLength        = false,
                AwaitFragmentDisposal  = true,
                AllocDelayMS           = 0,
                FragmentDisposeAfterMS = 2000                 // keep them alive
            };

            if (allocArgs.Count * allocArgs.Size < 12_000_000)
            {
                Passed         = false;
                FailureMessage = "The default highway capacity can handle all fragments. Should test out of the capacity bounds.";
                return;
            }

            Print.Trace(allocArgs.FullTrace(), ConsoleColor.Cyan, ConsoleColor.Black, null);

            var stg_ignore = new HighwaySettings(8_000_000, 2, 10_000_000);
            var stg_throw  = new HighwaySettings(8_000_000, 2, 10_000_000);

            stg_ignore.OnMaxLaneReached = () =>
            {
                Print.AsInnerInfo("OnMaxLaneReached(), allowing it to continue. ");
                return(true);
            };

            stg_ignore.OnMaxTotalBytesReached = () =>
            {
                Print.AsInnerInfo("OnMaxTotalBytesReached(), ignoring. ");
                return(true);
            };

            var iH = new Dictionary <string, IMemoryHighway>();

            iH.Add("mh", new HeapHighway(stg_ignore));
            iH.Add("nh", new MarshalHighway(stg_ignore));
            iH.Add("mmf", new MappedHighway(stg_ignore));

            var dH = new Dictionary <string, IMemoryHighway>();

            dH.Add("mh", new HeapHighway(stg_throw));
            dH.Add("nh", new MarshalHighway(stg_throw));
            dH.Add("mmf", new MappedHighway(stg_throw));

            // The ignoring case
            try
            {
                foreach (var kp in iH)
                {
                    if (opt.Contains(kp.Key))
                    {
                        var hw     = kp.Value;
                        var hwName = hw.GetType().Name;
                        using (hw)
                        {
                            hw.AllocAndWait(allocArgs);
                            if (hw.GetTotalActiveFragments() > 0)
                            {
                                Passed         = false;
                                FailureMessage = $"The {hwName} has active fragments after the AllocAndWait()";
                                return;
                            }
                            if (hw.GetLanesCount() > stg_ignore.MaxLanesCount)
                            {
                                Passed         = false;
                                FailureMessage = $"The {hwName} has more than {stg_ignore.MaxLanesCount} lanes.";
                                return;
                            }
                            Print.Trace(hw.FullTrace(), 2, true, ConsoleColor.Cyan, ConsoleColor.Black, null);
                        }
                    }
                }

                "The limits ignoring case.".AsSuccess();

                // The default case: throws MemoryLaneExceptions
                foreach (var kp in dH)
                {
                    if (opt.Contains(kp.Key))
                    {
                        var hw     = kp.Value;
                        var hwName = hw.GetType().Name;
                        using (hw)
                        {
                            try { hw.AllocAndWait(allocArgs); }
                            catch (AggregateException aggr)
                            {
                                Interlocked.Exchange(ref allocArgs.Trace, 0);

                                foreach (var ex in aggr.Flatten().InnerExceptions)
                                {
                                    var mex = ex as MemoryLaneException;

                                    if (mex != null)
                                    {
                                        if (mex.ErrorCode != MemoryLaneException.Code.MaxLanesCountReached &&
                                            mex.ErrorCode != MemoryLaneException.Code.MaxTotalAllocBytesReached)
                                        {
                                            Passed         = false;
                                            FailureMessage = string.Format(
                                                "The {0} should have failed with MaxLanesCountReached or MaxTotalAllocBytesReached",
                                                hwName);
                                            return;
                                        }

                                        $"{mex.ErrorCode} in {hwName} as expected".AsSuccess();
                                    }
                                    else
                                    {
                                        Passed         = false;
                                        FailureMessage = ex.Message;
                                        return;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Passed         = false;
                                FailureMessage = ex.Message;
                                return;
                            }

                            if (hw.GetLanesCount() > stg_throw.MaxLanesCount)
                            {
                                Passed         = false;
                                FailureMessage = $"The {hwName} has more than {stg_throw.MaxLanesCount} lanes, should have failed. ";
                                return;
                            }

                            Print.Trace(hw.FullTrace(), 2, true, ConsoleColor.Cyan, ConsoleColor.Black, null);
                        }
                    }
                }

                "The default - throwing exceptions case.".AsSuccess();
            }
            catch (Exception ex)
            {
                Passed         = false;
                FailureMessage = ex.Message;
                return;
            }

            if (!Passed.HasValue)
            {
                Passed = true;
            }
            IsComplete = true;
        }
    }
示例#2
0
        public Task Start(IDictionary <string, List <string> > args)
        {
            const int IN_PARALLEL = 30;
            var       T           = new Task[IN_PARALLEL];

            try
            {
                using (var hw = new HeapHighway(2000))
                {
                    // Alloc +1 ints, the last cell will be concurrently read/written by each task.
                    // When the task id is successfully stored, the task is allowed to update its on cell.
                    var frag = hw.Alloc((IN_PARALLEL + 1) * 4);

                    // Launch multiple tasks
                    for (int i = 0; i < IN_PARALLEL; i++)
                    {
                        T[i] = Task.Factory.StartNew((idx) =>
                        {
                            var intSpan = frag.ToSpan <int>();
                            int pos     = (int)idx;
                            var laps    = 0;

                            // Await with terrible cache flushing
                            while (Interlocked.CompareExchange(ref intSpan[IN_PARALLEL], pos, 0) != 0)
                            {
                                laps++;
                            }

                            var posAndLaps = laps + (pos * 10_000_000);

                            Volatile.Write(ref intSpan[pos], posAndLaps);

                            // Release
                            Interlocked.Exchange(ref intSpan[IN_PARALLEL], 0);
                        }, i);
                    }

                    Task.WaitAll(T);

                    // Check if all tasks have updated their corresponding cells
                    var theSpan = frag.ToSpan <int>();
                    for (int i = 0; i < theSpan.Length - 1; i++)
                    {
                        if (theSpan[i] < 0)
                        {
                            Passed         = false;
                            FailureMessage = $"The Task {i} hasn't touched its cell.";
                            break;
                        }
                        else
                        {
                            Print.AsInnerInfo($"{i}: {theSpan[i]} laps");
                        }
                    }

                    Passed = true;
                    Print.Trace(hw.FullTrace(), 2, true, ConsoleColor.Cyan, ConsoleColor.Black, null);
                }
            }
            catch (Exception ex)
            {
                Passed         = false;
                FailureMessage = ex.Message;
            }

            return(Task.Delay(0));
        }
示例#3
0
        public async Task Start(IDictionary <string, List <string> > args)
        {
            await Task.Delay(0);

            if (args.ContainsKey("+all"))
            {
                args.Add("-store", new List <string>()
                {
                    "mh", "mmf", "nh"
                });
            }

            args.AssertAll("-store");
            var opt = args["-store"];

            opt.AssertNothingOutsideThese("mh", "mmf", "nh");

            var allocArgs = new AllocTestArgs()
            {
                Count                  = 6000,
                Size                   = 1200,
                InParallel             = 12,
                RandomizeAllocDelay    = false,
                RandomizeFragDisposal  = true,
                RandomizeLength        = false,
                AllocDelayMS           = 10,
                AllocTries             = 20,
                AwaitFragmentDisposal  = false,
                FragmentDisposeAfterMS = 100,
                Trace                  = 0
            };

            var H     = new Dictionary <string, IMemoryHighway>();
            var ms    = new HighwaySettings(300_000, 300, 700_000_000);
            var lanes = new int[10];

            Array.Fill(lanes, 300_000);

            H.Add("mh", new HeapHighway(ms, lanes));
            H.Add("nh", new MarshalHighway(ms, lanes));
            H.Add("mmf", new MappedHighway(ms, lanes));

            Print.Trace(allocArgs.FullTrace(), ConsoleColor.Cyan, ConsoleColor.Black, null);

            foreach (var kp in H)
            {
                if (opt.Contains(kp.Key))
                {
                    var hw     = kp.Value;
                    var hwName = hw.GetType().Name;

                    using (hw)
                    {
                        hw.AllocAndWait(allocArgs);
                        var fragsCount = hw.GetTotalActiveFragments();

                        if (fragsCount < args.Count)
                        {
                            Passed         = false;
                            FailureMessage = string.Format(
                                "{0}: Failed to allocate all {1} fragments, got {2}.",
                                hwName, allocArgs.Count, fragsCount);

                            return;
                        }

                        Print.AsInnerInfo(
                            "{0}: Total lanes count: {1} Total active fragments: {2}",
                            hwName, hw.GetLanesCount(), hw.GetTotalActiveFragments());

                        Print.Trace(hw.FullTrace(), 2, true, ConsoleColor.Cyan, ConsoleColor.Black, null);
                    }
                }
            }

            if (!Passed.HasValue)
            {
                Passed = true;
            }
            IsComplete = true;
        }
示例#4
0
        bool reset(List <string> opt)
        {
            var stg = new HighwaySettings(4000, 8, 10000);
            var iH  = new Dictionary <string, IMemoryHighway>();

            iH.Add("mh", new HeapHighway(stg, 4000));
            iH.Add("nh", new MarshalHighway(stg, 4000));
            iH.Add("mmf", new MappedHighway(stg, 4000));

            foreach (var kp in iH)
            {
                var hwName = kp.Value.GetType().Name;
                var F      = new List <MemoryFragment>();

                if (opt.Contains(kp.Key))
                {
                    var hw = kp.Value;
                    using (hw)
                    {
                        F.Add(hw.AllocFragment(500));
                        F.Add(hw.AllocFragment(500));
                        F.Add(hw.AllocFragment(500));
                        hw.AllocFragment(1000);                         // lost
                        F.Add(hw.AllocFragment(500));
                        F.Add(hw.AllocFragment(1000));

                        foreach (var f in F)
                        {
                            f.Dispose();
                        }

                        var af = hw.GetTotalActiveFragments();
                        if (af == 1)
                        {
                            Print.AsInnerInfo("{0} has {1} non disposed fragments", hwName, af);
                            af = hw.GetTotalActiveFragments();

                            if (af != 1)
                            {
                                Passed         = false;
                                FailureMessage = string.Format("{0}: expected one ghost fragment, found {1}.", hwName, af);
                                return(false);
                            }

                            Print.Trace("Forcing reset.. ", ConsoleColor.Magenta, hwName, af);
                            var lane0 = hw[0];
                            lane0.Force(false, true);
                            af = hw.GetTotalActiveFragments();


                            if (af != 0)
                            {
                                Passed         = false;
                                FailureMessage = string.Format("{0}: expected 0 ghost fragments after forcing a reset, found {1}.", hwName, af);
                                return(false);
                            }
                            else
                            {
                                Print.Trace("{0} has {1} allocations and offset {2}", ConsoleColor.Green, hwName, lane0.Allocations, lane0.Offset);
                            }
                        }
                        else
                        {
                            Passed         = false;
                            FailureMessage = string.Format("{0}: the active fragments count is wrong, should be 1.", hwName);
                            return(false);
                        }

                        Print.Trace(hw.FullTrace(), 2, true, ConsoleColor.Cyan, ConsoleColor.Black);
                    }
                }
            }

            return(true);
        }
示例#5
0
        async Task Process(AllocType at, Socket client, Action <int> onmessage, bool stop = false)
        {
            Print.AsInfo(at.ToString() + Environment.NewLine);

            try
            {
                Print.AsInfo("New client" + Environment.NewLine);

                IMemoryHighway hw    = null;
                var            lanes = new int[] { 1025, 2048 };

                switch (at)
                {
                case AllocType.Heap:
                    hw = new HeapHighway(lanes);
                    break;

                case AllocType.MMF:
                    hw = new MappedHighway(lanes);
                    break;

                case AllocType.Marshal:
                    hw = new MarshalHighway(lanes);
                    break;

                default:
                    throw new ArgumentNullException();
                }

                using (hw)
                    using (var ns = new NetworkStream(client))
                    {
                        var header   = new byte[4];
                        var spoon    = new byte[16000];
                        var total    = 0;
                        var read     = 0;
                        var frameLen = 0;

                        while (!stop)
                        {
                            total = 0;
                            read  = await ns.ReadAsync(header, 0, 4).ConfigureAwait(false);

                            Print.AsInfo("Received header bytes: {0}.{1}.{2}.{3}", header[0], header[1], header[2], header[3]);

                            // The other side is gone.
                            // As long as the sender is not disposed/closed the ReadAsync will wait
                            if (read < 1)
                            {
                                Print.AsError("The client is gone.");
                                break;
                            }

                            frameLen = BitConverter.ToInt32(header, 0);

                            if (frameLen < 1)
                            {
                                Print.AsError("Bad header, thread {0}", Thread.CurrentThread.ManagedThreadId);
                                break;
                            }

                            using (var frag = hw.AllocFragment(frameLen))
                            {
                                Print.AsInfo("Frame length:{0}", frameLen);

                                // The sip length guards against jumping into the next frame
                                var sip = 0;
                                while (total < frameLen && !stop)
                                {
                                    sip = frameLen - total;
                                    if (sip > spoon.Length)
                                    {
                                        sip = spoon.Length;
                                    }

                                    // the read amount could be smaller than the sip
                                    read = await ns.ReadAsync(spoon, 0, sip).ConfigureAwait(false);

                                    frag.Write(spoon, total, read);
                                    total += read;

                                    Print.AsInnerInfo("read {0} on thread {1}", read, Thread.CurrentThread.ManagedThreadId);

                                    if (total >= frameLen)
                                    {
                                        onmessage?.Invoke(total);
                                        break;
                                    }
                                }
                            }
                        }
                    }
            }
            catch (MemoryLaneException mex)
            {
                Print.AsError(mex.Message);
                Print.AsError(mex.ErrorCode.ToString());
                Print.AsError(mex.StackTrace);
            }
            catch (Exception ex)
            {
                Print.AsError(ex.Message);
            }
        }