How to diagnostic slow code with Visual Studio

During the development of one feature, I noticed the performance to be very slow in some scenario. It was not obvious at first because the task was to simply update a user profile. The user profile in question is stored in a single table. It’s a pretty straight forward task. Before persisting the data, some validations are done but that is it.

This is where Visual Studio can be very useful with the integrated Diagnostic Tools. The diagnostic tools provide information about event and on any of them, you can come back in time and replay the call stacks which is pretty useful. It also gives some timing information, cpu usage and memory usage. To start diagnosing, simply attach Visual Studio to the process you want to diagnostic. After, open Visual Studio’s diagnostic tools that is located in the top menu under Debug > Profiler > Performance Explorer > Show Performance Explorer.

Here is an example of the output that I got from my performance problem.

DiagnosticTool

Visual Studio Diagnostic tools events include Entity Framework SQL statements. This is where I realized that the user’s table was updated but also hundred of others which looks to be a table linked to this one. Here was the performance bottleneck, the culprit! I never expected to update anything related to that table — just the main user’s table.

Entity Framework code was like this:

public void Update(ApplicationUser applicationModel)
{
	//Update the password IF necessary
	var local = UnitOfWork.Set<ApplicationUser>().Local.FirstOrDefault(f => f.Id == applicationModel.Id);
	if (local != null)
	{
		UnitOfWork.Entry(local).State = EntityState.Detached;
	}
	UnitOfWork.Entry(applicationModel).State = EntityState.Modified;
	if (string.IsNullOrEmpty(applicationModel.PasswordHash))
	{
		UnitOfWork.Entry(applicationModel).Property(f => f.PasswordHash).IsModified = false;
	}
	UnitOfWork.Entry(applicationModel).Property(f => f.UserName).IsModified = false;
	UnitOfWork.Entry(applicationModel).Property(f => f.CreationDateTime).IsModified = false;
	UnitOfWork.Entry(applicationModel).Property(f => f.ValidationDateTime).IsModified = false;
	UnitOfWork.Entry(applicationModel).Property(f => f.LastLogin).IsModified = false;
	UnitOfWork.Entry(applicationModel).Property(f => f.SecurityStamp).IsModified = false;
	UnitOfWork.Entry(applicationModel).Property(f => f.Language).IsModified = false;
}

As you can notice, nothing is done directly on the property that has the collection of “reputation”. The problem is that if the user as in that collection 250 objects, that for an unknown reason, Entity Framework does 250 updates. Since we want just to update first name, last name and few other basic properties than we need to be sure to remove those unwanted updates. After some modification with Entity Framework, like nulling every collection before updating, The SQL provided was only a single SQL, whence the performance at full speed.

SQL Arithmetic overflow error converting numeric to data type numeric

When you are using straight ADO.Net with SQL you may come when using an operation that produce an overflow. This is often hard to debug if you are inside an update statement which update several fields. You may think than using cast or convert to the type of the destination field solve the problem, but it is not actually valid.

Here is two examples that show that even if you convert or cast it won’t be enough.

declare @dob1 as decimal(16,4)
set @dob1 = cast(554656545465486786844864613 as decimal(16,4))
select @dob1

declare @dob2 as decimal(16,4)
set @dob2 = CONVERT(decimal(16,4),5455531234268.68423224224244864613 )
select @dob2

In my case, the problem was that I was performing an update in a field by executing a multiplication. field = field * 1/2. The problem was that field was already, in some case, at 0 and sometime above the maximum which is 12 (16-4) digits. Even if the following code work fine.

declare @dob3 as int
set @dob3 = cast(0*1/2 as int)
select @dob3

This one was not:

declare @fromValue as int
declare @toValue as int

set @fromValue = 1
set @toValue = 2

SELECT cast(Quantity * @fromValue/@toValue as int) as newQuantity
FROM [Trading].[Stock]

However, adding a where clause eliminates edge cases to be proceeded. The trick is to handle result of 0 and result above the limit.

declare @fromValue as int
declare @toValue as int

set @fromValue = 1
set @toValue = 2

SELECT cast(Quantity * @fromValue/@toValue as int) as newQuantity
FROM [Trading].[Stock]
WHERE Quantity > 0
AND Quantity  < 999999999999

Azure Website 404 woff, otf and ttf Fonts

Website that use custom fonts in .woff, woff2, .otf or .ttf can works fine on your local IIS and not working at all on Azure. You can have a 404 response or the following message.

The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

Azure doesn’t have a mime type associated for .woff, woff2, .otf or .ttf and it requires to setup those mime types.

Fortunately, this is simple to do and can be done directly in the web.config.

<configuration>
  <system.webServer>
    <staticContent>
      <mimeMap fileExtension="woff" mimeType="application/font-woff" />
      <mimeMap fileExtension="woff2" mimeType="application/font-woff2" />
      <mimeMap fileExtension=".otf" mimeType="font/otf" />
      <mimeMap fileExtension=".ttf" mimeType="font/ttf" />
    </staticContent>
  </system.webServer>
</configuration>

The mimeMap‘s element needs to be added for each font type. The mimeMap goes under configuration > system.WebServer > staticContent.

If you publish to Azure, your font should be render correctly. However, maybe in your local IIS you have no more any static resource loading. No more CSS, no more JavaScript! This is because your IIS may already have the .otf and .ttf font defined, whence having them defined twice creates an error. To resolve that issue, remove the mimemap for these fonts.

    <staticContent>
      <mimeMap fileExtension="woff" mimeType="application/font-woff" />
      <mimeMap fileExtension="woff2" mimeType="application/font-woff2" />
      <remove fileExtension =".otf"/>
      <mimeMap fileExtension=".otf" mimeType="font/otf" />
      <remove fileExtension =".ttf"/>
      <mimeMap fileExtension=".ttf" mimeType="font/ttf" />
    </staticContent>

Removing the font and adding this one right after it make sure that it works locally and on Azure.

Asp.Net MVC Bundle does not Render

Asp.Net MVC 4.5 introduced Bundling resource for styles and for scripts. Its role is to minimize the size of your resource by aggregating files in 1 and reducing the size by compressing the string. In Asp.Net 5, it’s gone. Asp.Net team with the newest version took out some features that can be handled by non-Microsoft solutions. However, the Asp.Net MVC 4.5 bundling is still present in many websites. One problem that can occur is that your styles render but not your scripts. This problem is the result of the hidden rule which is that your CSS bundle name cannot be the same name of your script. If you created a style bundle with the name of your page, you cannot have the same one for your script. It’s better to prefix it with your intention.

This is an example that will render only CSS and not JavaScript.

@Styles.Render("~/bundles/mywebsite")
@Scripts.Render("~/bundles/mywebsite")

The solution is to have unique name.

@Styles.Render("~/bundles/css/mywebsite")
@Scripts.Render("~/bundles/javascript/mywebsite")

Do not forget to change the BundleConfig.cs file to have names matching Html helpers.