Slow performance on ASP.NET MVC application using EntityFramework + SQL Server

Used technologies and software:

  •  ASP.NET MVC 5
  • Entity Framework Code First 6.x
  • SQL Server 2014 Express
  • Windows Server 2012
  • IIS 8.0
  • Hyper-V Virtual Machine (SSD and 8GB RAM set dynamic with 4GB as start up value).
  • Visual Studio 2013

Problem:

Website in production is slow, takes several seconds (+30s) or even minutes to load a page. But this does not always happen.
In development everything works always fast.

Steps taken to figure out the problem:

  • Netword config, NIC, IP, DNS, … –> ok
  • Checking if connection string is set correctly. –> ok
    (tip: see https://teusje.wordpress.com/2012/02/21/how-to-test-an-sql-server-connection/ )
  • Adding caching to the ASP.NET MVC application. –> ok, but still too slow
  • SQL Server 2014 Profiler:
    Trying to figure out if it is the application or the SQL Server, so we ran the Profiler and copy several queries and executed them directly on the SQL Server without any problem.
  • Log files:
    Custom log file in the ASP.NET MVC application gave us a good hint:

    Exceptions:

     sqlexception: Timeout expired EntityCommandExecutionException
    
     SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
     Stack:    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
        at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
        at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
        at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
        at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
        at System.Data.SqlClient.SqlDataReader.get_MetaData()
        at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
        at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
        at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
        at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
        at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
        at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
        at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
        at Glimpse.Ado.AlternateType.GlimpseDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
        at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
        at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.b__c(DbCommand t, DbCommandInterceptionContext`1 c)<
        at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
        at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
        at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
        at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
        at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

Start Microsoft SQL Server Management Studio and navigate to:
[Server Instance] –> [Management] –> [SQL Server Logs] –> double click [Current – …] there you select [Windows NT]

There we’ve seen the real problem several times in the logs:

"AppDomain 50 (master.sys[runtime].48) is marked for unload due to memory pressure."

sql server problem

Now we simply started Task Manager on the server and watched the ‘Memory’ in the ‘Performance’ tab.
The memory was constantly at 3.7GB or 3.8GB when we visited the website.

vm memory
Hooray! We found the problem. 🙂 Now we need to find a solution.

As you might remember from the beginning of this post, we’ve configured our Hyper-V Virtual Machine with the Dynamic Memory option.
This had a start up value of 4GB… and our server was constantly at 3.7GB or 3.8GB…

So why does our server not dynamically increase the RAM of the virtual machine?

It turns out that Hyper-V Dynamic Memory, introduced in Windows Server 2008 R2 SP1, is only supported in SQL Server Enterprise and Datacenter Editions!

Solution:

Don’t enable Hyper-V Dynamic Memory for your virtual machine but set it static with a value of e.g. 8GB RAM.

Voila:

vm memory fixed

🙂

Your Host Operating System needs to be at least Windows Server 2008 R2 SP1 or Microsoft Hyper-V Server 2008 R2 SP1 as your Hyper-V host.
The Guest Operating System edition (= your virtual machine) needs to be Web, Standard, Enterprise or Datacenter.
You need SQL Server Enterprise or Datacenter edition if you want that SQL Server automatically uses more RAM when needed using the Hyper-V Dynamic Memory feature.
In case you just have a Windows Server Standard and SQL Server Express and you have the same symptoms as described above just set your virtual machine RAM to a static value instead of using Hyper-V Dynamic Memory.

Extra information:

Advertisements

Visual Studio 2013 – Clean Solution

I recently upgraded a project from Visual Studio 2010 / .NET4.0 to Visual Studio 2013 (update 4) / .NET 4.5.
Code that was working for weeks, didn’t work anymore (exceptions in Caliburn.Micro).

Summary:
I reinstalled all my Nuget packages, verified the public key tokens of the libraries via the Strong Name Tool (SN.exe -T my.dll), did “Clean Solution”, “Rebuild Solution”, rewritten code, etc…

In a desperate action I manually cleaned every bin and obj folder in my Workspace.
After this action the code started to work again.

Then I was wondering: Does the “Clean Solution” in Visual Studio 2013 work different compared to Visual Studio 2010.
An internet stranger gave me a good hint:

“Sorry, but this is simply not true. It does not delete the contents of /obj which are the root of the problem. At least this is the situation with VS 2013 update 3.”

http://stackoverflow.com/questions/755382/i-want-to-delete-all-bin-and-obj-folders-to-force-all-projects-to-rebuild-everyt#comment41784938_755390

After searching some more, I was happy that I was not the only one who had problems with Visual Studio 2013 and the Clean Solution:

“However, once I’ve converted my projects to Visual Studio 2013 I star receiving error on build or deploy:”

http://kitsula.com/Article/How-to-remove-bin-obj-folder-before-build-deploy

Conclusion: if you upgrade to Visual Studio 2013 and receive strange exceptions, clean the obj directories manually or change your project file to remove the obj directory before each build via the BaseIntermediateOutputPath property/parameter.

By default the BeforeBuild and AfterBuild are not used. You can see this by unloading your project in Visual Studio and then right-mouse click it and select Edit:

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->

Uncomment the BeforeBuild.
Your project file should now contain this:

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets. -->
  <Target Name="BeforeBuild">
    <RemoveDir Directories="$(BaseIntermediateOutputPath)" />
  </Target>
  <!--<Target Name="AfterBuild">
  </Target>-->

Information on the BaseIntermediateOutputPath property/parameter:

 “The top-level folder where all configuration-specific intermediate output folders are created. The default value is obj\. The following code is an example:  <BaseIntermediateOutputPath>c:\xyz\obj\</BaseIntermediateOutputPath>”

If you receive the Error after changing the project:

 Unable to remove directory “obj\”. The directory is not empty

Go have a look at this url: http://forums.asp.net/t/1976253.aspx
It might also be related to Visual Studio 2013…

Info:
https://msdn.microsoft.com/en-us/library/k5b5tt23(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/5ak1w89s.aspx
https://msdn.microsoft.com/en-us/library/bb629394.aspx

The Bing Code Search Add-in for Visual Studio 2013

Maybe you already know the Bing Code Search Add-in for Visual Studio 2013. If not, you can see it here:

http://research.microsoft.com/apps/video/default.aspx?id=208988

The cool thing is, that you can also test it online at: http://codesnippet.research.microsoft.com/

Here I asked “how to save an image?” where I directly got some suggestions with code samples:

bing code search

Coding made easy! 😉

Fixing comctl32.dll WIN32Exception

A C# project was recently upgraded from .NET 3.5 to .NET 4.0.
The program worked fine, except on a Windows 8 Pro x64 machine where this error was given:

Win32Exception: Cannot load the “comctl32.dll” DLL into memory.

The solution that worked for us (after a long search) was removing CorFlags to set the application to 32-bits mode. When a new build was created without CorFlags and setting Visual Studio to build the project to x86 instead of x64 solved the problem.

It looks like CorFlags is not reliable…

WebMatrix 3 (preview)

webmatrix 3 preview

WebMatrix3 preview is available for download.

New changes for even simpler website creation

In addition to everything which WebMatrix 2 offers, WebMatrix 3 brings you easy access to your Windows Azure websites. Icon-sized previews of your sites make them easy to find and open. Access your remote sites as seamlessly as local sites. When you need to protect your work or collaborate on team projects, you’ll love our integration of Git and TFS source control systems. These are just a few of the highly requested features we’ve added in WebMatrix 3!
http://www.microsoft.com/web/post/webmatrix-3-preview-how-to-articles

 

Try it out today on http://www.microsoft.com/web/webmatrix/next/

Disable the Toggle Completion Mode in Visual Studio

When writing code in Visual Studio, the shortkey Ctrl+Alt+Space toggles the completion mode of IntelliSense in the Text Editor.
The completion mode can be manually changed by going to this menu in VS2012:
EDIT > IntelliSense > Toggle Completion Mode

However the shortkey can be annoying while coding, depending on your keyboard configuration and language.

To disable this shortkey command in Visual Studio 2012 follow these steps:

  • Go to TOOLS
  • Select Options…
  • Go to Environment > Keyboard
  • Below the Show commands containing: type the word completion and hit the TAB-key
  • The filtered listbox should now contain a command called Edit.ToggleCompletionMode
  • Select it and hit the button Remove
  • Click OK to close the Options form

visual studio 2012 keyboard command options

These steps are very similar to Visual Studio 2010.

Get information from Team Foundation Server (TFS) via C# code

This code shows you how you could interact with your team foundation server. In my case a TFS 2010.

Open a new console application in Visual Studio and add these references:

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.VersionControl.Client
TeamFoundationServer tfs = new TeamFoundationServer("http://yourtfsserver:port/something");
List<string> changedFiles = new List<string>();

VersionControlServer VCServer = (VersionControlServer)tfs.GetService<VersionControlServer>();

try
{
string path = @"C:\Users\<username>\Documents\Visual Studio 2010\Projects\just the path to your solution";
VersionSpec version = VersionSpec.Latest;
int deletionId = 0;
RecursionType recursion = RecursionType.Full;
string user = @"domain\yourusername";

foreach (Changeset item in VCServer.QueryHistory(path, version, deletionId, recursion, user, null, null, Int32.MaxValue, true, false, true))
{
  foreach (Change c in item.Changes)
  {
	// c.Item.ServerItem;
  }
}
}
catch { }

Happy coding 😉

Visual Studio Achievements

A software engineer’s glory so often goes unnoticed. Attention seems to come either when there are bugs or when the final project ships. But rarely is a developer appreciated for all the nuances and subtleties of a piece of code–and all the heroics it took to write it.  With Visual Studio Achievements Beta, your talents are recognized as you perform various coding feats, unlock achievements and earn badges.

link ] [ link2 ]

BugAid for Visual Studio: Enhance your debugging experience

BugAid is an extension for Visual Studio that can help you whenever you debug C# code. Using our unique features you can debug faster than ever before and have more time for writing quality code!

P.S.: If you buy BugAid, I would appreciate it if you leave them a message that you got the news from this blog 😉

[ link ]