Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does my application wait for synchronization so much?
    text
    copied!<p>I am working on a performance test which involves several clients bombarding the server with 150 requests each, as fast as they can.</p> <p>The server is constructed from 3 WCF services, one is opened to outside with httpbinding, it talks to 2 other services via net.pipe (IPC). one of the services is in charge of DB connections (SQL server 2008 R2).</p> <p>This DB connection service uses the following connection string enhancments:</p> <pre><code>Min Pool Size=20; Max Pool Size=1000; Connection Timeout=20; </code></pre> <p>and is WCF throttled(like all other WCF services).</p> <p>I noticed that when I activate 1 client it may take 3 seconds, but when I activate 3 clients it may take 8-9 or more.</p> <p>I checked with the SQL server profiler to see how many concurrent processes are used, and I saw that only about 8 processes are being used.</p> <p>So I realized that somewhere in the server the requests get queued instead of concurrently processed.</p> <p>In order to get to the bottom of it I've used a performance profiler (ANTS to be exact) which showed me that about 70% of the time was wasted on <strong>"Waiting for synchronization</strong></p> <p>When I open the call graph I find two things that look strange but I'm not sure what they mean:</p> <ol> <li>System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke is being used in the top of the tree, is that ok for concurrent processing?</li> <li>All synchronized problems involve some kind of SQL Server activity, like ExecuteNonQuery, ExecuteReader and so on (When I get to the bottom of the call tree)</li> </ol> <p>I noticed that the DB connection service uses a DAL project(some legacy code, unfortunately) which is totally static.</p> <p>After reading <a href="https://stackoverflow.com/questions/3037637/c-sharp-what-if-a-static-method-is-called-from-multiple-threads">this</a> I'm not sure if DAL's code is problematic or not, here is a sample of a stored procedure call.</p> <pre><code> public static int PerformStoredProcedure(string storedP,string ext,out string msg) { msg = ""; SqlCommand command = GetSqlCommand(storedP,ext); command.Connection.Open(); int result = (int)PerformStoredProcedure(command,out msg); command.Connection.Close(); return result; } </code></pre> <p>This Method is usualy called from the DB connection service:</p> <pre><code> public static int PerformStoredProcedureWithParams(string storedP,string ext,out string msg, params object[] pars) { msg = ""; SqlCommand command = GetSqlCommand(storedP,ext); UpdateCommandParams(command, pars); command.Connection.Open(); int result = (int)PerformStoredProcedure(command,out msg); command.Connection.Close(); return result; } </code></pre> <p>So, is there anything wrong here?</p> <p>Or maybe I should look somewhere else?</p> <p><strong>Edit:</strong></p> <p>After Brijesh's comment I realized I hadn't change the default InstanceContextMode and ConcurrencyMode of the WCF services... Kind of beginner's mistake I guess.</p> <p>I'm still not certain if I should use PerSession/Multiple or PerCall/ Single. As I see it each service should handle each request as on object, regardless of the client.</p> <p>What should I use?</p> <p><strong>2nd EDIT:</strong></p> <p>After using PerCall and PerSession/Multiple, I noticed that there is still no change (at least in the DB service). what I see is that the main entry point service may open up alot of threads, but only a few (still around 8-10 threads) are opened at the DB connection service.</p> <p>is there any other reason why this can happen? I ruled out DAL being a problem because not enough requests go in the DB service so I figure its something in the service or something in the clients...</p> <p><strong>3rd EDIT:</strong></p> <p>Here are the config files:</p> <p>Manager's config wcf service section:</p> <pre><code>&lt;services&gt; &lt;service behaviorConfiguration="ServicesBehavior" name="Verifone.GenericPP.GPPManagerService.GPPManagerServiceImpl"&gt; &lt;host&gt; &lt;baseAddresses&gt; &lt;add baseAddress="http://localhost:9090/GPPManagerService/"/&gt; &lt;/baseAddresses&gt; &lt;/host&gt; &lt;endpoint contract="Verifone.GenericPP.GPPManagerService.IGPPManagerService" binding="basicHttpBinding" address="GPPManagerService"&gt;&lt;/endpoint&gt; &lt;/service&gt; &lt;/services&gt; &lt;behaviors&gt; &lt;serviceBehaviors&gt; &lt;behavior name="ServicesBehavior"&gt; &lt;!--amith 13-05-2012--&gt; &lt;serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000" maxConcurrentInstances="1000" /&gt; &lt;serviceMetadata httpGetEnabled="true" /&gt; &lt;serviceDebug includeExceptionDetailInFaults="true" /&gt; &lt;/behavior&gt; &lt;/serviceBehaviors&gt; &lt;/behaviors&gt; &lt;bindings&gt; &lt;basicHttpBinding&gt; &lt;binding name="basicHttpBinding" maxBufferSize="10000000" maxReceivedMessageSize="10000000"&gt; &lt;readerQuotas maxStringContentLength="10000000" maxArrayLength="10000000"/&gt; &lt;security mode="None"&gt; &lt;transport clientCredentialType="None"/&gt; &lt;/security&gt; &lt;/binding&gt; </code></pre> <p>Manager's clients:</p> <pre><code> &lt;endpoint name="endpoint1" contract="IDBConnectionContract" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9010/DBConnectionService/DBService"&gt;&lt;/endpoint&gt; &lt;endpoint name="endpoint2" contract="IGPPService" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9095/GenericPPService/GenericPPService"&gt;&lt;/endpoint&gt; </code></pre> <p>DB Connection Service:</p> <pre><code>&lt;service behaviorConfiguration="ServicesBehavior" name="Verifone.DBConnectionService.DBConnectionContracImpl"&gt; &lt;host&gt; &lt;baseAddresses&gt; &lt;add baseAddress="http://localhost:9010/DBConnectionService/"/&gt; &lt;add baseAddress="net.pipe://localhost/DBConnectionService/"/&gt; &lt;/baseAddresses&gt; &lt;/host&gt; &lt;endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="basicHttpBinding" address="DBService"&gt;&lt;/endpoint&gt; &lt;endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_Configuration" address="" name="pipeEndpoint"/&gt; &lt;/service&gt; </code></pre> <p>The business logic service's client is pretty much the same like the Manager's.</p> <p>All services are self hosted and I have a DBConnectionProxy class at Manager's and Business code which they activate like this:</p> <pre><code> DBConnectionContractClient _dbConnectionContractClient = null; try { objDBConnectionContractClient = new DBConnectionContractClient(); objDBConnectionContractClient.ExecuteStoredProcedure(input, out result); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload