| // Licensed to the Apache Software Foundation(ASF) under one |
| // or more contributor license agreements.See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership.The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Text; |
| using ThriftTest; |
| using Thrift.Collections; |
| using Thrift; |
| using Thrift.Protocol; |
| using System.Threading; |
| using Thrift.Transport.Client; |
| using System.Threading.Tasks; |
| using System.Diagnostics; |
| using Thrift.Transport; |
| |
| namespace Client.Tests |
| { |
| public class PerformanceTests |
| { |
| private CancellationTokenSource Cancel = new(); |
| private CrazyNesting? Testdata; |
| private TMemoryBufferTransport? MemBuffer; |
| private TTransport? Transport; |
| private LayeredChoice Layered; |
| private readonly TConfiguration Configuration = new(); |
| |
| internal static async Task<int> Execute() |
| { |
| var instance = new PerformanceTests(); |
| await instance.ProtocolPeformanceTestAsync(); |
| |
| // debug only |
| if (Debugger.IsAttached) |
| { |
| Console.Write("Hit ENTER ..."); |
| Console.ReadKey(); |
| } |
| |
| return 0; |
| } |
| |
| public PerformanceTests() |
| { |
| Configuration.MaxFrameSize = Configuration.MaxMessageSize; // default frame size is too small for this test |
| } |
| |
| private async Task ProtocolPeformanceTestAsync() |
| { |
| Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ..."); |
| Cancel = new CancellationTokenSource(); |
| Testdata = TestDataFactory.CreateCrazyNesting(); |
| |
| foreach (var layered in Enum.GetValues(typeof(LayeredChoice))) |
| { |
| Layered = (LayeredChoice)layered; |
| await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TBinaryProtocol>(b); }); |
| await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TCompactProtocol>(b); }); |
| await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TJsonProtocol>(b); }); |
| } |
| } |
| |
| private async Task<TProtocol> GenericProtocolFactory<T>(bool forWrite) |
| where T : TProtocol |
| { |
| var oldTrans = Transport; |
| try |
| { |
| Transport = null; |
| |
| // read happens after write here, so let's take over the written bytes |
| if (forWrite) |
| MemBuffer = new TMemoryBufferTransport(Configuration); |
| else |
| MemBuffer = new TMemoryBufferTransport(MemBuffer?.GetBuffer(), Configuration); |
| |
| // layered transports anyone? |
| Transport = Layered switch |
| { |
| LayeredChoice.None => MemBuffer, |
| LayeredChoice.Framed => new TFramedTransport(MemBuffer), |
| LayeredChoice.Buffered => new TBufferedTransport(MemBuffer), |
| _ => throw new Exception("Unhandled case " + Layered.ToString()), |
| }; |
| ; |
| |
| if (!Transport.IsOpen) |
| await Transport.OpenAsync(); |
| |
| if (Activator.CreateInstance(typeof(T), Transport) is T instance) |
| return instance; |
| |
| throw new Exception("Unexpected."); |
| } |
| finally |
| { |
| oldTrans?.Dispose(); |
| } |
| } |
| |
| private string GetProtocolTransportName(TProtocol proto) |
| { |
| var name = Transport?.GetType().Name; |
| var bufnm = MemBuffer?.GetType().Name; |
| if ((name is null) || name.Equals(bufnm)) |
| name = string.Empty; |
| else |
| name = " + " + name; |
| |
| name = proto.GetType().Name + name; |
| return name; |
| } |
| |
| |
| private async Task RunTestAsync(Func<bool, Task<TProtocol>> factory) |
| { |
| var stop = new Stopwatch(); |
| |
| if (Testdata is null) |
| throw new Exception("unexpected internal state"); |
| |
| var proto = await factory(true); |
| if (Transport is null) |
| throw new Exception("unexpected internal state"); |
| stop.Start(); |
| await Testdata.WriteAsync(proto, Cancel.Token); |
| await Transport.FlushAsync(Cancel.Token); |
| stop.Stop(); |
| Console.WriteLine("RunTestAsync({0}): write = {1} msec", |
| GetProtocolTransportName(proto), |
| stop.ElapsedMilliseconds); |
| |
| var restored = new CrazyNesting(); |
| proto = await factory(false); |
| if (Transport is null) |
| throw new Exception("unexpected internal state"); |
| stop.Start(); |
| await restored.ReadAsync(proto, Cancel.Token); |
| stop.Stop(); |
| Console.WriteLine("RunTestAsync({0}): read = {1} msec", |
| GetProtocolTransportName(proto), |
| stop.ElapsedMilliseconds); |
| } |
| |
| } |
| } |