Importance of trace enabled=”false”

I was reading through some posts on ASP.NET best practices, and a lot is mentioned about <compilation debug=”false” /> on production machines. One thing that seems to be glossed over is <trace enabled=”false” />. Obviously, tracing is a security concern, but does it hurt your application in other ways?

The biggest area I thought tracing could effect an application was memory, so I wanted to see the memory differences of having trace enabled, vs having it disabled.

Test #1 – Trace enabled

<trace requestLimit="5000" enabled="true" mostRecent="false"/>

I loaded up an instance of one of our ASP.NET applications on my machine, and ran a script that generated random hits on a few of the pages.

After about ~4500 requests, here is what perfmon read.
trace

Test #2 – No Tracing

<trace requestLimit="5000" enabled="false" mostRecent="false"/>

Ran the script again, and saw some pretty interesting results.

notrace

The Word

At first, the results look the same, but look closer. With tracing enabled the # of Bytes in all Heaps is 710MB, vs 72MB without tracing. That’s a 10x difference! The Gen 2 heap is where most of the difference lies, which is a whopping 692MB vs 65MB. This heap should only contain very long lived objects. Having a growing Gen 2 heap is also going to indicate the need for IIS to recycle soon, since memory obviously isn’t getting deallocated.

If you are running with <deployment retail=”true”/>, then you don’t have to worry about this on production machines. Still, it is important to know the effects that tracing can have on you live environment.

If this graph isn’t making a lot of sense, check out this article on debugging memory problems.

System.ArgumentOutOfRangeException at System.Web.HttpCachePolicy.UtcSetLastModified (DateTime utcDate)

I spent most of yesterday configuring a server, then delving into the aforementioned error with a few other devs. Here is basically what we did to figure it out, and what the cause was.

The error

The day started by setting up a new server, and getting our ASP.NET application up and running. At first, the error wasn’t apparent. It was when we started seeing javascript errors on different pages. It looked as though one javascript includes was causing the error, /WebResource.axd?d=KadOK03KouGAGUGwjTWw4w2&t=633707613869062500.

When pulling up the included javascript file directly in the browser, the full error was seen.

       Type : System.ArgumentOutOfRangeException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
       Message : Specified argument was out of the range of valid values.
Parameter name: utcDate
       Source : System.Web
       Help link :
       ActualValue :
       ParamName : utcDate
       Data : System.Collections.ListDictionaryInternal
       TargetSite : Void UtcSetLastModified(System.DateTime)
       Stack Trace :    at System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate)
          at System.Web.Handlers.AssemblyResourceLoader.System.Web.IHttpHandler.ProcessRequest(HttpContext context)
          at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
          at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

The problem

Google quickly helped me figured out what was causing it, some assemblies were dated in the future.

I was a little confused as to why though. I looked at the timestamp portion of the request, to see what its value was, /WebResource.axd?d=KadOK03KouGAGUGwjTWw4w2&t=633707613869062500.

PS C:\> new-object DateTime 633707613869062500
 
Friday, February 20, 2009 9:16:26 PM
 
PS C:\> [DateTime]::Now
 
Friday, February 20, 2009 1:21:22 PM

So the assembly trying to be loaded is ~8 hours in the future, not good.

Who is causing the problem?

Now I know what the problem is, but looking through all the DLL’s for timestamp problems could take forever. Powershell to the rescue.

gci -recurse | where { $_.LastWriteTime -gt [DateTime]::Now }

I ran this on the application directory, then C:\Windows\Microsoft.NET, then C:\Windows\assemblies.

Bam. The problem was in C:\Windows\Microsoft.NET and C:\Windows\assemblies.

(Side note: Smarty pants Lamar showed this could be done with just Windows search and ordering by the date column.)

My first idea

Can I change the LastWriteTime of a file?

PS C:\> gi c:\ | get-member LastWriteTime
 
   TypeName: System.IO.DirectoryInfo
 
Name          MemberType Definition
----          ---------- ----------
LastWriteTime Property   System.DateTime LastWriteTime {get;set;}

Yes, there is a setter!

gci -recurse | 
  where { $_.LastWriteTime -gt [DateTime]::Now } | 
  %{ $_.LastWriteTime = [DateTime]::Now }

Well, that worked for C:\Windows\Microsoft.NET, but not C:\Windows\assemblies since all the DLLs in there are in use.

The final solution

Reinstall .NET framework, entirely. I know, you were expecting something amazing, and I failed you. Well, sorry. I was annoyed too, but it was the easiest way I could think accomplish the task. What is important is how I was able to use Powershell to test out different scenarios and possible solutions. If I would have had to write a command line program in Visual Studio to figure out what different timestamp values actually were, I wouldn’t have done it.

The other question you might have is why were times so off? Well, the server was a fresh install and the time wasn’t set properly for some reason. .NET was installed before checking the time that was set. This would have been fine, but the server was added to the AD domain, which quickly changed the time to the correct time.

Script of the gods

Setting up new IIS 6 servers can be a pain. The config is so daunting they call it a metabase! Backing up the metabase is super important, but did you know you can copy the entire metabase to another server? Yes you can, and its pretty awesome.

cscript iiscnfg.vbs /copy /ts ANOTHER_SERVER /tu domain\user /tp password

Perfect for web farms where you are adding new servers and need to script setup. It may not be as pretty as Apache or Lighttpd configs, but it works and saves hours of error prone setup.