[Mono-bugs] [Bug 70337][Maj] New - Performance problem with TcpChannel
bugzilla-daemon@bugzilla.ximian.com
bugzilla-daemon@bugzilla.ximian.com
Wed, 8 Dec 2004 13:43:27 -0500 (EST)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by sebastien.robitaille@croesus.com.
http://bugzilla.ximian.com/show_bug.cgi?id=70337
--- shadow/70337 2004-12-08 13:43:27.000000000 -0500
+++ shadow/70337.tmp.3471 2004-12-08 13:43:27.000000000 -0500
@@ -0,0 +1,271 @@
+Bug#: 70337
+Product: Mono: Class Libraries
+Version: 1.0
+OS: Red Hat 9.0
+OS Details:
+Status: NEW
+Resolution:
+Severity:
+Priority: Major
+Component: CORLIB
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: sebastien.robitaille@croesus.com
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: Performance problem with TcpChannel
+
+Description of Problem:
+
+I developed a small client and a small server to test the performance of
+remoting. The execution results are very interesting.
+
+I ran the client and the server using all combinations of tcp, http,
+binary and soap.
+The execution was done for MS.NET on a Windows XP Pro 1GHz Pentium III.
+For Mono, it was done on a RH9 Xeon 1.5GHz 8CPUs.
+(Note: This test should be done on the same machine for both mono and
+MS.NET to make a better comparision).
+
+-----------------------------------
+The results (Requests per second):
+-----------------------------------
+ MS.NET Mono
+
+SOAP/HTTP 190 60
+SOAP/TCP 280 12
+BINARY/HTTP 340 100
+BINARY/TCP 1050 12
+-----------------------------------
+
+The interesting point here is that both SOAP and BINARY gave the same
+number for TCP in mono. While HTTP is slower in mono than in MS.NET, the
+results are at least consistents (SOAP is, as expected, slower tant
+Binary).
+
+Hint: I had a quick look at the TcpChannel code and I found many places
+that a networkStream was read or written one Byte at a time.
+
+Steps to reproduce the problem:
+[1] Create 3 files (Client.cs, Server.cs and IServerInterface.cs)
+containing the following code:
+
+----------------- Client.cs -----------------------------------------
+//#define HTTP
+//#define SOAP
+
+using System;
+using System.Collections;
+using System.Runtime.Remoting.Channels;
+using System.Runtime.Remoting.Channels.Tcp;
+using System.Runtime.Remoting.Channels.Http;
+using ServerInterface;
+
+namespace Client
+{
+ class Client
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ string serverName = "localhost";
+ int timeout = 1000;
+
+ if(args.Length > 0)
+ {
+ serverName = args[0];
+ }
+
+ if(args.Length > 1)
+ {
+ timeout = Int32.Parse(args[1]);
+ }
+#if SOAP
+ SoapClientFormatterSinkProvider formatterProvider
+= new SoapClientFormatterSinkProvider();
+#else
+ BinaryClientFormatterSinkProvider
+formatterProvider = new BinaryClientFormatterSinkProvider();
+#endif
+
+ Hashtable channelProperties = new Hashtable();
+ channelProperties["port"] = 0;
+
+#if HTTP
+ HttpClientChannel channel = new HttpClientChannel
+(channelProperties, formatterProvider);
+ string prefix = "http://";
+#else
+ TcpClientChannel channel = new TcpClientChannel
+(channelProperties, formatterProvider);
+ string prefix = "tcp://";
+#endif
+ ChannelServices.RegisterChannel(channel);
+
+ IServerInterface serverObject =
+(IServerInterface)
+ Activator.GetObject(typeof
+(IServerInterface), prefix + serverName + ":8999/IServerInterface");
+
+ while(true)
+ {
+ serverObject.ExecuteRequest(null);
+ }
+ }
+ }
+}
+
+
+
+-------------- Server.cs ---------------------------------------
+//#define HTTP
+//#define SOAP
+
+using System;
+using System.Collections;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Channels;
+using System.Runtime.Remoting.Channels.Tcp;
+using System.Runtime.Remoting.Channels.Http;
+using System.Runtime.Serialization.Formatters;
+using System.Threading;
+using ServerInterface;
+
+namespace Server
+{
+ class Server
+ {
+ static bool running = true;
+ static int refresh = 1000;
+
+ [STAThread]
+ static void Main(string[] args)
+ {
+ if(args.Length > 0)
+ {
+ refresh = Int32.Parse(args[0]);
+ }
+
+ RemotingConfiguration.RegisterWellKnownServiceType
+(
+
+ typeof(RemoteObject),
+
+ "IServerInterface",
+
+ WellKnownObjectMode.Singleton);
+#if SOAP
+ SoapServerFormatterSinkProvider formatterProvider
+= new SoapServerFormatterSinkProvider();
+#else
+ BinaryServerFormatterSinkProvider
+formatterProvider = new BinaryServerFormatterSinkProvider();
+#endif
+ Hashtable channelProperties = new Hashtable();
+ channelProperties["port"] = 8999;
+#if HTTP
+ HttpServerChannel channel = new HttpServerChannel
+(channelProperties, formatterProvider);
+#else
+ TcpServerChannel channel = new TcpServerChannel
+(channelProperties, formatterProvider);
+#endif
+ ChannelServices.RegisterChannel(channel);
+
+ System.Console.WriteLine("Press Enter to stop the
+program.");
+
+ ThreadPool.QueueUserWorkItem(new WaitCallback
+(StatsPrinter));
+
+ System.Console.ReadLine();
+ running = false;
+ }
+
+ private static void StatsPrinter(object o)
+ {
+ int count = 0;
+ while(running)
+ {
+ DateTime start = DateTime.Now;
+ Thread.Sleep(refresh);
+ int newCount =
+RemoteObject.GetRequestCount();
+ DateTime stop = DateTime.Now;
+ int diff = newCount - count;
+ TimeSpan timediff = stop - start;
+
+ int reqPerSec = (int) (diff /
+timediff.TotalSeconds);
+
+ System.Console.WriteLine
+("Request/sec: " + reqPerSec);
+ System.Console.WriteLine("Request
+Count: " + newCount);
+ System.Console.WriteLine();
+ count = newCount;
+ }
+ }
+ }
+
+ public class RemoteObject : MarshalByRefObject, IServerInterface
+ {
+ private static int requestCount = 0;
+
+ public RemoteObject()
+ {
+ }
+
+ static public int GetRequestCount()
+ {
+ int result = -1;
+ Interlocked.Exchange(ref result, requestCount);
+
+ return result;
+ }
+
+ public bool ExecuteRequest(object param)
+ {
+ Interlocked.Increment(ref requestCount);
+ return true;
+ }
+ }
+}
+
+
+
+--------------- IServerInterface.cs --------------------------------
+using System;
+
+namespace ServerInterface
+{
+ public interface IServerInterface
+ {
+ bool ExecuteRequest(object param);
+ }
+}
+
+
+[2] Uncomment the #defines at the begining of Client.cs and Server.cs to
+reflect what you need to test (HTTP/TCP and SOAP/Binary)
+
+[3]Use the following commands to compile the source code:
+
+mcs -out:ServerInterface.dll -target:library IServerInterface.cs
+
+mcs -r:ServerInterface.dll -r:System.Runtime.Remoting.dll -
+out:Server.exe -target:exe Server.cs
+
+mcs -r:ServerInterface.dll -r:System.Runtime.Remoting.dll -
+out:Client.exe -target:exe Client.cs
+
+
+[4] run Server.exe and Client.exe (in this order, with ou without
+parameters) and watch for the server's output.
+
+
+How often does this happen?
+Always
+
+Additional Information: