public void interlock_exchange_delegate_pointer() { var subject = new IEDP(); var switches = new bool[500]; var dispatcher = Dispatch <int> .CreateDefaultMultithreaded($"TEST: {nameof(interlock_exchange_delegate_pointer)}", threadCount : 10); for (int i = 0; i < 500; i++) { dispatcher.AddWork(i); } dispatcher.AddConsumer(i => { Thread.Sleep(i % 20); var x = subject.TryGetNextPage(); Console.Write($"{i}=>{x}, "); switches[x] = true; }); dispatcher.Start(); dispatcher.WaitForEmptyQueueAndStop(TimeSpan.FromSeconds(10)); Assert.That(switches.All(v => v), Is.True, "Not all switches were set"); // Thought... keep a pool of about 32 slots that we keep free page indexes in. (that's about 128kb worth) // Each requester goes through the IEDP to get a number from 0..31, and pulls the page from there. // If there isn't a page in our slot, we hit the slow path and rebuild the slots. }
public void reading_documents_in_multiple_threads_works_correctly() { using (var doc = MakeTestDocument()) using (var ms = new MemoryStream()) { var subject = Database.TryConnect(ms); Console.WriteLine("Writing doc"); doc.Seek(0, SeekOrigin.Begin); subject.WriteDocument("test/data-path/doc", doc); var dispatcher = Dispatch <int> .CreateDefaultMultithreaded("MyTask", threadCount : 10); for (int i = 0; i < 500; i++) { dispatcher.AddWork(i); } dispatcher.AddConsumer(i => { //Thread.Sleep(i % 8); Console.Write($"{i}, "); subject.Get("test/data-path/doc", out _); subject.Get("this document is not here", out _); }); dispatcher.Start(); dispatcher.WaitForEmptyQueueAndStop(TimeSpan.FromSeconds(10)); } }
static void Main() { using (var subject = new DirectServer(@"C:\Temp\WrappedSites_Disabled\no_appins")) // a published site { var request = new SerialisableRequest { Method = "GET", RequestUri = "/values", Headers = new Dictionary <string, string> { { "Content-Type", "application/json" } }, Content = null }; // Make a whole load of calls for profiling int i; var dispatcher = Dispatch <SerialisableRequest> .CreateDefaultMultithreaded("LoadTest", 4); dispatcher.AddConsumer(rq => { // ReSharper disable once AccessToDisposedClosure var result = subject.DirectCall(request); if (rq.CommandControl != null) { var resultString = Encoding.UTF8.GetString(result?.Content ?? new byte[0]); Console.Write(rq.CommandControl); Console.WriteLine(resultString); } }); var sw = new Stopwatch(); sw.Start(); dispatcher.Start(); for (i = 0; i < 10000; i++) { if (i % 100 == 0) { var traceRequest = request.Clone(); traceRequest.CommandControl = i.ToString(); dispatcher.AddWork(traceRequest); } else { dispatcher.AddWork(request); } } dispatcher.WaitForEmptyQueueAndStop(); // only call this if you're not filling the queue from elsewhere sw.Stop(); var rate = i / sw.Elapsed.TotalSeconds; Console.WriteLine("calls per second: " + rate); Console.WriteLine("[Done]"); Console.ReadLine(); } }
public void writing_documents_in_multiple_threads_works_correctly() { using (var ms = new MemoryStream()) { var subject = Database.TryConnect(ms); var dispatcher = Dispatch <int> .CreateDefaultMultithreaded("MyTask", threadCount : 10); const int rounds = 50; for (int i = 0; i < rounds; i++) { dispatcher.AddWork(i); } dispatcher.AddConsumer(i => { var j = (5 * i) % rounds; Console.Write($"W{i},R{j}; "); // ReSharper disable AccessToDisposedClosure subject.WriteDocument($"test/data-path/{i}", MakeTestDocument()); subject.Get($"test/data-path/{j}", out _); // ReSharper restore AccessToDisposedClosure }); dispatcher.Start(); dispatcher.WaitForEmptyQueueAndStop(); subject.Flush(); ms.Rewind(); var rawData = ms.ToArray(); // Check we can still load and read the database var result = Database.TryConnect(new MemoryStream(rawData)); Console.WriteLine(string.Join(", ", result.Search("test"))); var failed = new List <int>(); for (int i = 0; i < rounds; i++) { var ok = result.Get($"test/data-path/{i}", out _); if (!ok) { failed.Add(i); } } Assert.That(failed, Is.Empty, "Failed lookups: " + string.Join(", ", failed)); } }
public void Listen(CancellationToken token, IEnumerable <Endpoint> endpoints) { ThreadPool.SetMaxThreads(Parallelism, Parallelism); ThreadPool.SetMinThreads(1, 1); _dispatcher = Dispatch <IContext> .CreateDefaultMultithreaded("ResponderThreads", Parallelism); _dispatcher.AddConsumer(_handler.Handle); _dispatcher.Start(); // To use thread pool instead of dispatcher: don't call this and change the code in ListenerCallback var listener = new HttpListener(); Trace.TraceInformation("Binding..."); MainRequestHandler.HttpsAvailable = false; foreach (var endpoint in endpoints) { try { var name = endpoint.Name; var baseUri = $"{endpoint.Protocol}://{endpoint.IPEndpoint}/"; if (endpoint.Protocol == "https") { MainRequestHandler.HttpsAvailable = true; } listener.Prefixes.Add(baseUri); Trace.TraceInformation("Adding listener for '" + name + "' on " + baseUri); } catch (Exception ex) { Trace.Fail("BINDING FAILED! " + ex); return; } } Trace.TraceInformation("Starting..."); try { listener.IgnoreWriteExceptions = false;//true; listener.Start(); } catch (Exception ex) { Trace.Fail("STARTING FAILED! " + ex); return; } Trace.TraceInformation("Started"); while (!token.IsCancellationRequested) { var asctx = listener.BeginGetContext(ListenerCallback, listener); var gotOne = asctx.AsyncWaitHandle.WaitOne(1500, true); // break out of wait loop to allow cancellation to happen. if (gotOne) { Trace.TraceInformation("Incoming message"); } else { OnPeriodicCheck(); } } listener.Stop(); listener.Close(); _dispatcher.Stop(); }