Monday, July 29, 2013

Finding the quietest time to do disruptive maintenance with IIS

Some changes to production environments may be much simpler if a little downtime is acceptable (such as migrating hosting providers). Using hard data to find that time to determine the impact on customers is possible using IIS logs and the LogParser tool.

  1. Get hold of the IIS logs from all production servers and copy them into a single folder e.g. 
    • Server1
      • W3SVC1
        • ex12345.log
    • Server2
      • W3SVC1
        • ex12345.log
  2. Download and install LogParser, if you don't have it.
  3. Run the following PowerShell from within the log folder root:
    & 'C:\Program Files (x86)\Log Parser 2.2\LogParser.exe' -i:iisw3c -recurse:-1 "select to_localtime(to_timestamp(date, quantize(time, 3600))) as LocalTimeBlock, count(*) as Count into Logs.csv from *.log where date is not null and `"cs(User-Agent)`" not like '%pingdom%' group by LocalTimeBlock"
    This query converts all dates and times into one hour blocks int local time and excludes requests from Pingdom, which we use for uptime monitoring.
  4. Load the generated Log.csv in Excel and create a scatter plot from the two columns. 

Saturday, July 20, 2013

Latency timings for various Azure datacentres.

I have published a tool that 'pings' various Azure datacentres around the world from your browser to see which have the lowest / highest latency. This obviously is most useful if most of your customers are in a single location, but I suspect that scenario is quite common.

The tool can be found at http://azureping.info.

Wednesday, July 17, 2013

Disable the "Attach Security Warning" dialog box

When remote debugging with Visual Studio, you may get an "Attach Security Warning" dialog for every process you want to attach to. There is no obvious way to stop this from popping up, and it can be quite frustrating when remote debugging several application pools. Microsoft's rationale for the security warning is here.

For those who want to silence this dialog forever, run the following PowerShell one-liner:
taskkill /IM devenv.exe; while(get-process -ea 0 devenv) { Write-Host "Waiting for Visual Studio to shut down..."; Start-Sleep -sec 1 }; ls HKCU:\Software\Microsoft\VisualStudio | % { $_.PSPath + "\Debugger" } | % { sp -ea 0 $_ DisableAttachSecurityWarning -Type DWORD -Value 1 }

Tuesday, July 16, 2013

Format a drive from PowerShell

After adding a new drive to a Windows Server 2012 Core machine, you will need to format it and assign a drive letter. This is how to do it.

$disk = Get-Disk | ? PartitionStyle -eq Raw
$disk | Initialize-Disk
$part = New-Partition -DiskNumber $disk.Number -UseMaximumSize
Initialize-Volume -Partition $part -FileSystem ReFS
Add-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $part.PartitionNumber -AccessPath D:\

Thursday, July 4, 2013

Overhead of using async and await in C# 4.5

Although asynchronous code is touted as allowing for more scalable architectures through less threads (a la nodejs), there must be a latency overhead to this technology. While the total throughput of the system may be higher, an individual request must be slowed down due to increased context switching.

I was interested in seeing how much of a performance impact there is to using the new Async pattern in .NET (and simplified using the fantastic async / await keywords in C#).

I wrote an application that compares the FileStream.Read and FileStream.ReadAsync calls in a tight loop, reading one byte into a byte array 1 million times. Tweaking the file size and other parameters resulted in very different results, although the synchronous call was always at least five times faster than the asynchronous call.

Results

File length: 1000000 bytes.
Running 100 loops of Preload...
Done in 0 ms.
Running 1000000 loops of Asynchronous...
Done in 2452 ms.
Running 1000000 loops of Synchronous...
Done in 17 ms.

Conclusion:

In this single test scenario, using this particular method of file access, the overhead of using asynchronous calls for very fast operations is significant in that an operation that takes around 20 ms synchronously runs at 2500 ms asynchronously (125 times slower). In practice, this is an overhead of 0.00000248 seconds (2.5 μs) per asynchronous call. Whether this overhead is acceptable, and whether the reduction in system resources that asynchronous calls are supposed to yield is worth this slowdown is application dependent.

Source code

Wednesday, June 19, 2013

Ping using PowerShell

To 'ping' a machine using PowerShell, use Test-Connection:
Test-Connection -Quiet machine

Friday, May 17, 2013

Why can't I copy and paste a URL from a Gmail subject line?

Sometimes I send myself quick emails with only the URL of a website pasted into the subject line. Unfortunately, I have been frustrated by not being able to copy and paste those URLs from Gmail into a browser from Internet Explorer 10. This does not seem to affect Chrome.


TL;DR

If you are having trouble copying and pasting a URL from a Gmail subject line, paste it here and click Go:


Detail


Steps to reproduce:

  1. Visit a website:
  2. Copy the URL and send it to your Gmail account as the subject line.
  3. Open your Gmail account and copy the URL from the email you just sent yourself:
  4. Paste this URL into your browser's address bar.
  5. See the result:


Why does this happen?

It seems that Google must be inserting a special character called a Zero Width Space (Unicode 8203) at certain positions in the URL to prevent copying and pasting. I can only presume that this is some kind of security measure. For example, the URL I used in this example actually looked like this behind the scenes: http://www.iana.org/?domains/re?served, where the question marks (?) are the special zero width space characters.

Point to note: the DNS protocol seems to ignore this character. Pasting http://example.iana.org/ (which mapped to http://exa?mple.iana.?org/ when I tried it) into the browser will work fine.

The value is not a copy / paste artefact; it is in the DOM node value:
document.getElementById(':np').firstChild.nodeValue 
"http://www​.iana.org/​domains/re​served"
document.getElementById(':np').firstChild.nodeValue.length 
39

'http://www.iana.org/domains/reserved'.length 
36