1 // Licensed to the Apache Software Foundation(ASF) under one
2 // or more contributor license agreements.See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 using System;
19 using System.Collections.Generic;
20 using System.Text;
21 using ThriftTest;
22 using Thrift.Collections;
23 using Thrift.Protocol;
24 using System.Threading;
25 using Thrift.Transport.Client;
26 using System.Threading.Tasks;
27 using System.Diagnostics;
28 using Thrift.Transport;
29 
30 namespace Client.Tests
31 {
32     public class PerformanceTests
33     {
34         private CancellationTokenSource Cancel;
35         private CrazyNesting Testdata;
36         private TMemoryBufferTransport MemBuffer;
37         private TTransport Transport;
38         private LayeredChoice Layered;
39 
Execute()40         internal static int Execute()
41         {
42             var instance = new PerformanceTests();
43             instance.ProtocolPeformanceTestAsync().Wait();
44 
45             // debug only
46             if (Debugger.IsAttached)
47             {
48                 Console.Write("Hit ENTER ...");
49                 Console.ReadKey();
50             }
51 
52             return 0;
53         }
54 
ProtocolPeformanceTestAsync()55         private async Task ProtocolPeformanceTestAsync()
56         {
57             Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ...");
58             Cancel = new CancellationTokenSource();
59             Testdata = TestDataFactory.CreateCrazyNesting();
60 
61             foreach (var layered in Enum.GetValues(typeof(LayeredChoice)))
62             {
63                 Layered = (LayeredChoice)layered;
64 
65                 await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TBinaryProtocol>(b); });
66                 await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TCompactProtocol>(b); });
67                 //await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TJsonProtocol>(b); });
68             }
69         }
70 
71         private Task<TProtocol> GenericProtocolFactory<T>(bool forWrite)
72             where T : TProtocol
73         {
74             var oldTrans = Transport;
75             try
76             {
77                 // read happens after write here, so let's take over the written bytes
78                 if (forWrite)
79                     MemBuffer = new TMemoryBufferTransport();
80                 else
81                     MemBuffer = new TMemoryBufferTransport(MemBuffer.GetBuffer());
82 
83                 //  layered transports anyone?
84                 switch (Layered)
85                 {
86                     case LayeredChoice.None:
87                         Transport = MemBuffer;
88                         break;
89                     case LayeredChoice.Framed:
90                         Transport = new TFramedTransport(MemBuffer);
91                         break;
92                     case LayeredChoice.Buffered:
93                         Transport = new TBufferedTransport(MemBuffer);
94                         break;
95                     default:
96                         Debug.Assert(false);
97                         break;
98                 }
99 
100                 if (!Transport.IsOpen)
101                     Transport.OpenAsync().Wait();
102 
103                 var instance = (T)Activator.CreateInstance(typeof(T), Transport);
104                 return Task.FromResult<TProtocol>(instance);
105             }
106             finally
107             {
108                 if (oldTrans is IDisposable)
109                     (oldTrans as IDisposable).Dispose();
110             }
111         }
112 
GetProtocolTransportName(TProtocol proto)113         private string GetProtocolTransportName(TProtocol proto)
114         {
115             var name = Transport.GetType().Name;
116             if (name.Equals(MemBuffer.GetType().Name))
117                 name = string.Empty;
118             else
119                 name = " + " + name;
120 
121             name = proto.GetType().Name + name;
122             return name;
123         }
124 
125 
RunTestAsync(Func<bool, Task<TProtocol>> factory)126         private async Task RunTestAsync(Func<bool, Task<TProtocol>> factory)
127         {
128             var stop = new Stopwatch();
129 
130             var proto = await factory(true);
131             stop.Start();
132             await Testdata.WriteAsync(proto, Cancel.Token);
133             await Transport.FlushAsync(Cancel.Token);
134             stop.Stop();
135             Console.WriteLine("RunTestAsync({0}): write = {1} msec",
136                 GetProtocolTransportName(proto),
137                 stop.ElapsedMilliseconds);
138 
139             var restored = new CrazyNesting();
140             proto = await factory(false);
141             stop.Start();
142             await restored.ReadAsync(proto, Cancel.Token);
143             stop.Stop();
144             Console.WriteLine("RunTestAsync({0}): read = {1} msec",
145                 GetProtocolTransportName(proto),
146                 stop.ElapsedMilliseconds);
147         }
148 
149     }
150 }
151