public void AddWorkItem_ItemsProcessed(int totItems, int totThreads, int maxQueuedItems) { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); var cfg = GetConfig(totThreads, maxQueuedItems); using (FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, mw.DoMockWork_Simple)) { foreach (int inputIx in Enumerable.Range(1, totItems)) { foreach (var outItem in fifo.AddWorkItem(new MockWorkIn(inputIx), ts.Token)) { doneWork.Add(outItem); } } foreach (var outItem in fifo.Flush(ts.Token)) { doneWork.Add(outItem); } } Assert.AreEqual(Enumerable.Range(1, totItems), doneWork.Select(f => f.originalInputItem.ix)); Assert.AreEqual(Enumerable.Range(1, totItems), mw.doneWork.Where(f => !f.Item1).OrderBy(f => f.Item2.ix).Select(f => f.Item2.ix)); }
public void AddWorkItem_OneItemProcessed() { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); int inputIx = 1; int totThreads = 1; int maxQueuedItems = 1; var cfg = GetConfig(totThreads, maxQueuedItems); using (FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, mw.DoMockWork_Simple)) { foreach (var outItem in fifo.AddWorkItem(new MockWorkIn(inputIx), ts.Token).Concat(fifo.Flush(ts.Token))) { doneWork.Add(outItem); } } Assert.AreEqual(1, doneWork.Count); Assert.AreEqual(inputIx, doneWork.First().originalInputItem.ix); Assert.AreEqual(1, mw.doneWork.Count); Assert.AreEqual(false, mw.doneWork.First().Item1); Assert.AreEqual(inputIx, mw.doneWork.First().Item2.ix); Assert.AreEqual(inputIx, mw.doneWork.First().Item3.originalInputItem.ix); }
public void AddWorkItem_Cancels(int totThreads) { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); var cfg = new FIFOWorkerConfig(totThreads); FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, mw.DoMockWorkBlocking); int countTask = fifo.AddWorkItem(new MockWorkIn(1), ts.Token).Count(); mw.TriggerOnBlockedWork(() => ts.Cancel()); Assert.Throws <TaskCanceledException>(() => { try { fifo.Dispose(); } catch (AggregateException ag) { throw ag.GetBaseException(); } }); Assert.AreEqual(1, mw.doneWork.Count(f => f.Item1)); Assert.AreEqual(1, mw.doneWork.Count()); }
public void Dispose_ExceptionInWorkerPropagates(int totThreads) { TaskCompletionSource <object> taskBlocker1 = new TaskCompletionSource <object>(); MockWorkOut DoMockWorkBlocking(MockWorkIn work, CancellationToken token) { taskBlocker1.Task.Wait(); throw new MockException(); } CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); var cfg = new FIFOWorkerConfig(totThreads); FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, DoMockWorkBlocking); int count = fifo.AddWorkItem(new MockWorkIn(1), ts.Token).Count(); Assert.Throws <MockException>(() => { try { taskBlocker1.SetResult(null); fifo.Dispose(); } catch (AggregateException ag) { throw ag.GetBaseException(); } }); }
public void Dispose_CancelsPendingTasks(int totThreads) { TaskCompletionSource <object> taskBlocker1 = new TaskCompletionSource <object>(); TaskCompletionSource <object> taskBlocker2 = new TaskCompletionSource <object>(); bool completed = false; int totBlockCalled = 0; MockWorkOut DoMockWorkBlocking(MockWorkIn work, CancellationToken token) { Interlocked.Increment(ref totBlockCalled); taskBlocker2.SetResult(null); taskBlocker1.Task.Wait(); Task.Delay(1, token).Wait(); completed = true; return(new MockWorkOut(work)); } CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); var cfg = new FIFOWorkerConfig(totThreads); FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, DoMockWorkBlocking); int count = fifo.AddWorkItem(new MockWorkIn(1), ts.Token).Count(); taskBlocker2.Task.Wait(); taskBlocker1.SetResult(null); Assert.AreEqual(1, totBlockCalled); Assert.AreEqual(0, count); Assert.DoesNotThrow(fifo.Dispose); Assert.AreEqual(true, completed); }
public CollectionDeserializerAsync(FIFOWorkerConfig fifowConfig, TypeModel typeModel, int desiredBatchSize_bytes = 1024 * 64) { this.desiredBatchSize_bytes = desiredBatchSize_bytes; fifow = new FIFOWorker <BatchIn, BatchOut>(fifowConfig, HandleWorkerOutput); this.typeModel = typeModel; t_ParallelServices_ArrayWrapper = typeof(ParallelServices_ArrayWrapper <T>); typeModel.SetupParallelServices <T>(); objPoolBufferWriterSerializedBatch = new DefaultObjectPool <ArrayPoolBufferWriter <byte> >( new ArrayPoolBufferWriterObjectPoolPolicy <byte>(Math.Max(1024 * 64, desiredBatchSize_bytes)), fifowConfig.MaxQueuedItems); objPoolList = new DefaultObjectPool <List <int> >(new ListObjectPoolPolicy <int>(64), fifowConfig.MaxQueuedItems); }
protected virtual void Dispose(bool disposing) { if (disposing) { fifow.Dispose(); } fifow = null; objPoolBufferWriterSerializedBatch = null; objPoolList = null; typeModel = null; t_ParallelServices_ArrayWrapper = null; }
protected virtual void Dispose(bool disposing) { if (disposing) { fifow?.Dispose(); } fifow = null; r_opts = null; objPoolBufferWriterBodies = null; objPoolBufferWriterBodyLengths = null; arrPoolOutputBatch = null; }
public CollectionDeserializerAsync(FIFOWorkerConfig fifowConfig, MessagePackSerializerOptions r_opts, int desiredBatchSize_bytes = 1024 * 64) { fifow = new FIFOWorker <BatchWithBufferWriters, BatchWithFramesArray>(fifowConfig, HandleWorkerOutput); this.desiredBatchSize_bytes = desiredBatchSize_bytes; objPoolBufferWriterBodies = new DefaultObjectPool <ArrayPoolBufferWriter <byte> >( new ArrayPoolBufferWriterObjectPoolPolicy <byte>(Math.Max(1024 * 64, desiredBatchSize_bytes)), fifowConfig.MaxQueuedItems); objPoolBufferWriterBodyLengths = new DefaultObjectPool <ArrayPoolBufferWriter <int> >( new ArrayPoolBufferWriterObjectPoolPolicy <int>(1024), fifowConfig.MaxQueuedItems); arrPoolOutputBatch = ArrayPool <Frame <T> > .Shared; this.r_opts = r_opts; }
public CollectionSerializerAsync(Stream stream, FIFOWorkerConfig fifowConfig, BatchSizeEstimatorConfig estimatorConfig, TypeModel typeModel) { this.stream = stream; fifow = new FIFOWorker <List <T>, MemoryStream>(fifowConfig, HandleWorkerOutput); this.typeModel = typeModel; typeModel.SetupParallelServices <T>(); batchEstimator = new BatchSizeEstimator(estimatorConfig); objPoolList = new DefaultObjectPool <List <T> >(new ListObjectPoolPolicy <T>(64), fifowConfig.MaxQueuedItems); objPoolMemoryStream = new DefaultObjectPool <MemoryStream>( new MemoryStreamObjectPoolPolicy(Math.Max(1024 * 64, estimatorConfig.DesiredBatchSize_bytes)), fifowConfig.MaxQueuedItems); desiredBatchSize = 1; currentBatch = objPoolList.Get(); }
protected virtual void Dispose(bool disposing) { if (disposing) { FlushAsync().Wait(); fifow.Dispose(); } fifow = null; batchEstimator = null; objPoolList = null; objPoolMemoryStream = null; currentBatch = null; typeModel = null; }
public CollectionSerializerAsync(Stream stream, FIFOWorkerConfig fifowConfig, BatchSizeEstimatorConfig estimatorConfig, MessagePackSerializerOptions w_opts) { this.stream = stream; fifow = new FIFOWorker <ArrayPoolBufferWriter <T>, BatchWithBufferWriters>(fifowConfig, HandleWorkerOutput); batchEstimator = new BatchSizeEstimator(estimatorConfig); this.w_opts = w_opts; objPoolBufferWriterBodies = new DefaultObjectPool <ArrayPoolBufferWriter <byte> >( new ArrayPoolBufferWriterObjectPoolPolicy <byte>(Math.Max(1024 * 64, estimatorConfig.DesiredBatchSize_bytes)), fifowConfig.MaxQueuedItems); objPoolBufferWriterBodyLengths = new DefaultObjectPool <ArrayPoolBufferWriter <int> >( new ArrayPoolBufferWriterObjectPoolPolicy <int>(1024), fifowConfig.MaxQueuedItems); objPoolOutputBatch = new DefaultObjectPool <ArrayPoolBufferWriter <T> >( new ArrayPoolBufferWriterObjectPoolPolicy <T>(1024), fifowConfig.MaxQueuedItems); currentBatch = objPoolOutputBatch.Get(); desiredBatchSize = 1; formatterT = w_opts.Resolver.GetFormatterWithVerify <T>(); }
public void Dispose_ThrowsOnCancelledTasks(int totThreads) { TaskCompletionSource <object> taskBlocker1 = new TaskCompletionSource <object>(); TaskCompletionSource <object> taskBlocker2 = new TaskCompletionSource <object>(); bool completed = false; int totBlockCalled = 0; MockWorkOut DoMockWorkBlocking(MockWorkIn work, CancellationToken token) { Interlocked.Increment(ref totBlockCalled); taskBlocker2.SetResult(null); taskBlocker1.Task.Wait(); Task.Delay(1, token).Wait(); completed = true; return(new MockWorkOut(work)); } CancellationTokenSource ts = new CancellationTokenSource(); List <MockWorkOut> doneWork = new List <MockWorkOut>(); var cfg = new FIFOWorkerConfig(totThreads); FIFOWorker <MockWorkIn, MockWorkOut> fifo = new FIFOWorker <MockWorkIn, MockWorkOut>(cfg, DoMockWorkBlocking); int count = fifo.AddWorkItem(new MockWorkIn(1), ts.Token).Count(); taskBlocker2.Task.Wait(); ts.Cancel(); Assert.Throws <TaskCanceledException>(() => { try { taskBlocker1.SetResult(null); fifo.Dispose(); } catch (AggregateException ag) { throw ag.GetBaseException(); } }); Assert.AreEqual(1, totBlockCalled); Assert.AreEqual(0, count); Assert.AreEqual(false, completed); }
protected virtual void Dispose(bool disposing) { if (disposing) { FlushAsync().Wait(); fifow?.Dispose(); if (currentBatch != null) { objPoolOutputBatch?.Return(currentBatch); } } w_opts = null; objPoolBufferWriterBodies = null; objPoolBufferWriterBodyLengths = null; objPoolOutputBatch = null; fifow = null; batchEstimator = null; currentBatch = null; formatterT = null; }
public void Serialize(ref MessagePackWriter writer, TFrameList value, MessagePackSerializerOptions options) { if (value == null) { writer.WriteNil(); return; } Interlocked.Increment(ref ParallelGatekeeperSingleton.wrapperDepth); try { FrameFormatterSerializationOptions frameOptions = options.GetOptionParams(); if (frameOptions.FIFOWorkerConfig.MaxConcurrentTasks < 1 || ParallelGatekeeperSingleton.wrapperDepth != 1) { SerializeSynchronous(ref writer, value, options); return; } int count = value.Count; writer.WriteArrayHeader(count); BatchSizeEstimator batchEstimator = new BatchSizeEstimator(frameOptions.BatchSizeEstimatorConfig); IMessagePackFormatter <T> formatterT = options.Resolver.GetFormatterWithVerify <T>(); bool isOldSpec = writer.OldSpec; BatchWithBufferWriters ProcessItems(ArraySegment <Frame <T> > batch, CancellationToken token) { BatchWithBufferWriters batchOut = new BatchWithBufferWriters(); batchOut.concatenatedBodies = objPoolBufferWriterBodies.Get(); batchOut.lengths = objPoolBufferWriterBodyLengths.Get(); MessagePackWriter writerBody = new MessagePackWriter(batchOut.concatenatedBodies) { OldSpec = isOldSpec, CancellationToken = token }; var spanIn = batch.AsSpan(); int prevWrittenBytesCount = 0; int sumLen = 0; for (int ix = 0; ix < spanIn.Length; ix++) { formatterT.Serialize(ref writerBody, spanIn[ix], options); writerBody.Flush(); int currWrittenBytesCount = batchOut.concatenatedBodies.WrittenCount; int objLen = currWrittenBytesCount - prevWrittenBytesCount; prevWrittenBytesCount = currWrittenBytesCount; batchOut.lengths.GetSpan(1)[0] = objLen; batchOut.lengths.Advance(1); sumLen += objLen; } if (spanIn.Length > 0) { batchEstimator.UpdateEstimate((float)sumLen / (float)spanIn.Length); // update with avg instead of updating for every loop item. It's not exact, but it's faster } return(batchOut); } ListFrameWrapper valueWrapper = GetTFrameListWrapper(value); Frame <T>[] valueArray = valueWrapper.AsFrameArray(); using (var fifow = new FIFOWorker <ArraySegment <Frame <T> >, BatchWithBufferWriters>(frameOptions.FIFOWorkerConfig, ProcessItems)) { int i = 0; while (i < count) { int batchSize = Math.Min(count - i, batchEstimator.RecomendedBatchSize); if (batchSize <= 0) { throw new StreamSerializationException($"Invalid batch sequence length: {batchSize}"); } ArraySegment <Frame <T> > sourceSegment = new ArraySegment <Frame <T> >(valueArray, i, batchSize); foreach (BatchWithBufferWriters batchOutput in fifow.AddWorkItem(sourceSegment, writer.CancellationToken)) { BatchToStream(ref writer, batchOutput); } i += batchSize; } foreach (BatchWithBufferWriters batchOutput in fifow.Flush(writer.CancellationToken)) { BatchToStream(ref writer, batchOutput); } } } finally { Interlocked.Decrement(ref ParallelGatekeeperSingleton.wrapperDepth); } }