c# - Slow WCF Host when hosted in another AppDomain -
i having weird problem. if wcf host hosted in original appdomain, code takes 1.25s execute. if put in new appdomain, despite fact still use net.pipe or net.tcp talk it, process takes 4.7s run. here code app.config in commented out block on bottom.
namespace consoleapplication2 { using system; using system.collections.concurrent; using system.diagnostics; using system.linq; using system.net; using system.net.networkinformation; using system.reflection; using system.servicemodel; using system.threading.tasks; using client; internal class program { #region methods private static void main(string[] args) { var p = new program(); p.execute(); } #endregion public void execute() { var hosts = enumerable.range(0, 1).select(createnewhost).toarray(); var r = new random(); var cb = new concurrentdictionary<int, string>(); action = () => { try { parallel.for( 0, 10000, => { //string ep = string.format("net.pipe://localhost/iservice{0}", hosts[r.next(0, hosts.length)]); string ep = string.format("net.tcp://localhost:{0}/iservice", hosts[r.next(0, hosts.length)]); string s=null; //using (var cli = new serviceclassclient("netnamedpipebinding_iserviceclass", ep)) using (var cli = new serviceclassclient("nettcpbinding_iserviceclass", ep)) { s = cli.ping(); } if (!string.isnullorempty(s)) { cb[i] = s; } }); } catch (aggregateexception aggregateexception) { console.writeline(aggregateexception); } }; console.writeline("\n\nit took {0:g}", a.timethis()); console.readkey(); } static int createnewhost(int s) { //uncomment in-process host //var h1 = new host(); //return h1.port; var appdomain = appdomain.createdomain( "a" + s, null, new appdomainsetup { loaderoptimization = loaderoptimization.multidomain, disallowbindingredirects = true }); var assemblyname = assembly.getassembly(typeof(host)).fullname; var h = appdomain.createinstanceandunwrap(assemblyname, typeof(host).fullname) host; return h.port; } } //comment out marshalbyrefobject in-process host public class host:marshalbyrefobject { #region fields private readonly servicehost host; private readonly int port; #endregion #region constructors , destructors public host() { this.port = this.getfreeport(); var ub = new uribuilder { host = "localhost", port = this.port, scheme = "net.tcp" }; var = new uribuilder { host = "localhost", scheme = "net.pipe", path = "iservice" + this.port }; this.host = new servicehost(typeof(serviceclass), ub.uri); var netnamedpipebinding = new netnamedpipebinding(netnamedpipesecuritymode.none); this.host.addserviceendpoint(typeof(iserviceclass), netnamedpipebinding, up.uri); var un = new uribuilder { host = "localhost", port = this.port, scheme = "net.tcp", path = "iservice" }; var nettcpbinding = new nettcpbinding(securitymode.none); this.host.addserviceendpoint(typeof(iserviceclass), nettcpbinding, un.uri); //#if debug //var = new uribuilder { host = "localhost", port = this.port, scheme = "http", path = "iservicemeta" }; //var smb = new servicemetadatabehavior { httpgetenabled = true, httpgeturl = us.uri }; //this.host.description.behaviors.add(smb); //#endif this.host.open(); console.writeline("listening @ {0}", this.host.baseaddresses[0].absoluteuri); } #endregion #region public properties public int port { { return this.port; } } public servicehost servicehost { { return this.host; } } #endregion #region methods private int getfreeport() { tcpconnectioninformation[] connections = ipglobalproperties.getipglobalproperties().getactivetcpconnections(); ipendpoint[] listeners = ipglobalproperties.getipglobalproperties().getactivetcplisteners(); var udps = ipglobalproperties.getipglobalproperties().getactiveudplisteners(); var r = new random(); int port; { port = r.next(1025, 65534); } while (listeners.any(a => a.port == port) || connections.any(a => a.localendpoint.port == port) || udps.any(a=>a.port==port)); return port; } #endregion } [servicecontract] internal interface iserviceclass { #region public methods , operators [operationcontract] string ping(); #endregion } internal class serviceclass : iserviceclass { #region public methods , operators public string ping() { return ((new random()).nextdouble() * (new random()).nextdouble()).tostring("f11"); } #endregion } public static class extensions { #region public methods , operators public static timespan timethis(this action action) { var sw = new stopwatch(); sw.start(); action.invoke(); sw.stop(); return sw.elapsed; } #endregion } } //------------------------------------------------------------------------------ // <auto-generated> // code generated tool. // runtime version:4.0.30319.18033 // // changes file may cause incorrect behavior , lost if // code regenerated. // </auto-generated> //------------------------------------------------------------------------------ namespace client { [system.codedom.compiler.generatedcodeattribute("system.servicemodel", "4.0.0.0")] [system.servicemodel.servicecontractattribute(configurationname = "iserviceclass")] public interface iserviceclass { [system.servicemodel.operationcontractattribute(action = "http://tempuri.org/iserviceclass/ping", replyaction = "http://tempuri.org/iserviceclass/pingresponse")] string ping(); } [system.codedom.compiler.generatedcodeattribute("system.servicemodel", "4.0.0.0")] public interface iserviceclasschannel : iserviceclass, system.servicemodel.iclientchannel { } [system.diagnostics.debuggerstepthroughattribute()] [system.codedom.compiler.generatedcodeattribute("system.servicemodel", "4.0.0.0")] public partial class serviceclassclient : system.servicemodel.clientbase<iserviceclass>, iserviceclass { public serviceclassclient() { } public serviceclassclient(string endpointconfigurationname) : base(endpointconfigurationname) { } public serviceclassclient(string endpointconfigurationname, string remoteaddress) : base(endpointconfigurationname, remoteaddress) { } public serviceclassclient(string endpointconfigurationname, system.servicemodel.endpointaddress remoteaddress) : base(endpointconfigurationname, remoteaddress) { } public serviceclassclient(system.servicemodel.channels.binding binding, system.servicemodel.endpointaddress remoteaddress) : base(binding, remoteaddress) { } public string ping() { return base.channel.ping(); } } } /* <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.servicemodel> <bindings> <netnamedpipebinding> <binding name="netnamedpipebinding_iserviceclass"> <security mode="none" /> </binding> </netnamedpipebinding> <nettcpbinding> <binding name="nettcpbinding_iserviceclass"> <security mode="none" /> </binding> </nettcpbinding> </bindings> <client> <endpoint address="" binding="netnamedpipebinding" bindingconfiguration="netnamedpipebinding_iserviceclass" contract="iserviceclass" name="netnamedpipebinding_iserviceclass" /> <endpoint address="" binding="nettcpbinding" bindingconfiguration="nettcpbinding_iserviceclass" contract="iserviceclass" name="nettcpbinding_iserviceclass" /> </client> </system.servicemodel> </configuration> */
you might improved performance decorating main method loaderoptimization attribute. shares common resources across app domains.
[loaderoptimization(loaderoptimization.multidomain)] see this answer more details.
Comments
Post a Comment