blob: 5262379a6228b2bca9d9bc3a2bbf35851ad625fc [file] [log] [blame]
// 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);
}
}
}