January 2010 - Posts
In one of my sessions I demonstrated how PLINQ uses two CPU-s instead of one and has better performance than non-parallel processing. In this posting I will introduce my experiment and show you my example results. In the end of this posting you can find source code that is ready for demonstration.
I used prime numbers finding code as example and I want to say thanks for great example to keeper of Non-Destructive Me blog. You can find example code from his or her blog entry Using PLINQ to Speed Up CPU Bound Operations - Demo. I modified demo code a little bit to fit my needs. In this posting I am using modified example. You can find link to my code from the end of this posting.
Demo code uses two methods to find prime numbers – LINQ and PLINQ. PLINQ – Parallel LINQ – is able to use all CPU-s available in machine. When you go through this demonstration you will see how easily you can move from LINQ to PLINQ.
Demo
PrimeNumberDemo.cs contains the following code block that measures time for LINQ and PLINQ version of prime numbers finding code. Leave this code as it is if you just want to see how much time one or another method takes.
//Run the demos for both parallel and sequential runs
long sequentialTime = RunSequentialTest(numbersToCheck);
long parallelTime = RunParallelTest(numbersToCheck);
If you want to get better idea what happens with CPU-s you should run LINQ and PLINQ version separately. Open Task Manager and make it stay always on top and make the following modifications to source code before running it.
If you want to see how LINQ works then use this code.
//Run the demos for both parallel and sequential runs
long sequentialTime = RunSequentialTest(numbersToCheck);
long parallelTime = 10000; //RunParallelTest(numbersToCheck);
If you want to see how PLINQ works then use this version of code.
//Run the demos for both parallel and sequential runs
long sequentialTime = 0; //RunSequentialTest(numbersToCheck);
long parallelTime = RunParallelTest(numbersToCheck);
Results
If everything worked like expected then last two modifications to code should produce something like this in Task Manager.
You can see that LINQ uses resources of one CPU and it is therefore a little bit slower in our example. PLINQ uses both CPU-s at same time and performs faster. If you compare times you should get results similar to mine. Take a look at the following screenshot – click on it to resize it. Your results may be different and it depends on hardware of your computer (I expect you don’t have many background processes running).
When we put the results on chart we can see that there is not hard differences between LINQ and PLINQ when we don’t have much processing to do. But when our processes grow and need more resources then PLINQ performs very well.
Horizontal axis shows the maximum number we are walking to when finding prime numbers. Vertical axis shows time in milliseconds that LINQ (serial) and PLINQ (parallel) need to find prime numbers in this range.
If you want more comparisons then take a look at Stefan Cruysberghs blog posting .NET - Performance comparison with Parallel Extensions .NET 3.5.
Source code
Click here to download VS2010B2 solution with demo code.
About week ago I introduced IIS Application Warm-up Module. ASP.NET 4.0 provides separate mechanism for same purposes. ASP.NET 4.0 application warm-up is different and if you like you can use both warm-up methods together. In this posting I will show you how to make ASP.NET 4.0 application warm-up work.
Warm-up class
At first you need ASP.NET 4.0 web application (Forms, MVC or Dynamic Data – you choose) that contains public class for warm-up. In this class we can do all work that needs to be done before application accepts requests. Let’s write simple class that cleans up cache folder.
C#
using System.Web.Hosting;
using System.IO;
namespace MyWebApp
{
public class PreWarmUp : IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
var cacheFolder = "e:\\cache";
string[] files = Directory.GetFiles(cacheFolder);
foreach (var file in files)
{
File.Delete(file);
}
}
}
}
VB.NET
Imports System.Web.Hosting
Imports System.IO
Namespace MyWebApp
Public Class PreWarmUp
Implements IProcessHostPreloadClient
Public Sub Preload(ByVal parameters As String()) _
Implements IProcessHostPreloadClient.Preload
Dim cacheFolder = "e:\cache"
Dim files As String() = _
Directory.GetFiles(cacheFolder)
For Each file__1 In files
File.Delete(file__1)
Next
End Sub
End Class
End Namespace
Now we have class that cleans up cache folder and we can configure IIS now.
NB! Don’t forget to create cache folder on hard disc. Put some files in it and give IIS permissions to read and write to this folder. You need those files to check out if ASP.NET 4.0 application warm-up works.
Configuring IIS
To configure IIS you have to perform steps given below.
- Open %WINDOWSDIR%\system32\inetsrv\config\applicationHost.config.
- Locate <sites> block.
- Find your application definition and add the following attributes to <application> tag:
serviceAutoStartEnabled="true" serviceAutoStartProvider="PrewarmMyApp" - Add the following XML after </site>:
<serviceAutoStartProviders>
<add
name="PrewarmMyApp"
type="MyWebApp.PreWarmUp, MyWebApp" />
</serviceAutoStartProviders>
- Save changes and close applicationHost.config (IIS should detect changes immediately).
Test your class
Now let’s see if our class works like expected. Open the folder with files you created in first step. Also open command prompt. Open it in administrative privileges and run iisreset. You should see files disappearing from your cache folder.
If it doesn’t happen then open Event Viewer and look for errors. If you have errors during warm-up then these errors are written to Event Log. If you compiled your application using Debug configuration you should get from Event Viewer all information about the error.
Current limitations
There are some limitations you should know about. You don’t have HTTP context available during warm-up. Your class must know where resources are located and how to access them. If you really need some warm-up work done under HTTP context then you can use IIS Application Warm-up Module. You can use both methods if you like.
I hope that in the future we have also method in IProcessHostPreloadClient interface that enables working under HTTP context. VS2010 RC is coming and I hope to find more warm-up options for ASP.NET 4.0 applications.
If you read documentation about IProcessHostPreloadClient interface you can find the following remark:
This interface is intended primarily for use by WCF applications that are non-HTTP applications. ASP.NET developers who want to preload ASP.NET Web applications should use the simulated HTTP requests in IIS 7.0 combined with the Application_Start method in the Global.asax file.
Keep it in mind when creating warm-up mechanism to your web application.
Currently it is not possible to make changes to web.config file that is hosted on Windows Azure. If you want to change web.config you have to deploy your application again. If you want to be able to modify configuration you must use web role settings. In this blog post I will show you how to write configuration wrapper class that detects runtime environment and reads settings based on this knowledge.
The following screenshot shows you web role configuration that is opened for modifications in Windows Azure site.
My solution is simple – I will create one interface and two configuration reading classes. Both classes – WebConfiguration and AzureConfiguration – implement IConfiguration interface.
C#
using System.Web.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;
namespace MyWebApp
{
public interface IConfiguration
{
string GetSetting(string name);
}
public class AzureConfiguration : IConfiguration
{
public string GetSetting(string name)
{
return
RoleEnvironment.GetConfigurationSettingValue(name);
}
}
public class WebConfiguration : IConfiguration
{
public string GetSetting(string name)
{
return WebConfigurationManager.AppSettings[name];
}
}
}
VB.NET
Imports System.Web.Configuration
Imports Microsoft.WindowsAzure.ServiceRuntime
Namespace MyWebApp
Public Interface IConfiguration
Function GetSetting(ByVal name As String) As String
End Interface
Public Class AzureConfiguration
Implements IConfiguration
Public Function GetSetting(ByVal name As String) _
As String Implements IConfiguration.GetSetting
Return _
RoleEnvironment.GetConfigurationSettingValue(name)
End Function
End Class
Public Class WebConfiguration
Implements IConfiguration
Public Function GetSetting(ByVal name As String) _
As String Implements IConfiguration.GetSetting
Return WebConfigurationManager.AppSettings(name)
End Function
End Class
End Namespace
Now we need something that we can use to read configuration settings without worrying about what settings exactly are read. I write simple static class that detects configuration reader and reads configuration settings we ask.
C#
using Microsoft.WindowsAzure.ServiceRuntime;
namespace MyWebApp
{
public static class Conf
{
private static IConfiguration _conf;
public static string GetSetting(string name)
{
if (_conf == null)
_conf = GetConf();
return _conf.GetSetting(name);
}
private static IConfiguration GetConf()
{
// If we are running in cloud
if (RoleEnvironment.IsAvailable)
return new AzureConfiguration();
return new WebConfiguration();
}
}
}
VB.NET
Imports Microsoft.WindowsAzure.ServiceRuntime
Namespace MyWebApp
Public Module Conf
Private Sub New()
End Sub
Private _conf As IConfiguration
Public Function GetSetting(ByVal name As String) As String
If _conf Is Nothing Then
_conf = GetConf()
End If
Return _conf.GetSetting(name)
End Function
Private Function GetConf() As IConfiguration
' If we are running in cloud
If RoleEnvironment.IsAvailable Then
Return New AzureConfiguration()
End If
Return New WebConfiguration()
End Function
End Module
End Namespace
We can use Conf.GetSetting(name) to read configuration parameters from currently active environment. Note how we are using RoleEnvironment to detect if we are in cloud. If you need the value of some setting you can just write code like this.
var appMode = Conf.GetSetting("WLA_ApplicationMode");
That’s it for now. As you can see it was not hard to extend our web application so we can read settings based on current environment. Static class is not maybe the best choice but it works for me. Now we have short and simple syntax for asking values of settings and if something changes we can make those changes to configuration classes and therefore we don’t have to modify classes that use those settings.
During one of my sessions I demonstrated how to use IIS Application Warm-Up Module. Some applications need to perform initialization tasks before taking requests from users. Application warm-up module is very good tool for this because it does not depend on script language or any other aspect of web application. In this posting I will show you how to use application warm-up module with simple PHP script.
To get PHP up under IIS I suggest you to follow the guide on IIS website Using FastCGI to Host PHP Applications on IIS 7.0. It applies to IIS 7.5 too. And, of course, you have to install Application Warm-Up Module.
Creating test-application
To test warm-up functionality we need warm-up script.
- Create new IIS web application.
- Create subfolder and name it as warmup.
- Create file start.php and move it to warmup folder.
- Insert the following script to start.php:
<?php
$fp = fopen("start.txt","w");
fwrite($fp, date('d.m.Y H:i:s', time()));
fclose($fp);
?>
- Save file and close it.
In this point I recommend you to make warmup folder unaccessible from other machines. You can easily force IP-based rule that allows requests to this folder only from 127.0.0.1.
Registering start-up script
Now let’s make start.php run when application starts.
- Open your PHP application folder in IIS Manager and click on Application Warm-Up icon.
- On Actions panel click on Settings. You should see window like this.
- Check both checkboxes and click OK.
- On Actions panel click on Add Request.
- Insert location of your warm-up script to URL field (like shown on screenshot above) and click OK.
Now we have warm-up script registered and we are ready to test it.
Testing application warm-up
Now you have warm-up script that creates new file with current date in the same folder. I suggest you to open Event Viewer so you can easily see error messages if there are any problems.
- Open warmup folder in Windows Explorer so you can see files in it.
- Open command prompt in administrative permissions and run iisreset.
- Wait while IIS is up again and look at warmup folder.
- You should see file called start.txt there.
Why application warm-up with warm-up module?
Using application warm-up module has some very important advantages.
- Users are not able to access application while it is warming up.
- Warm-up scripts are run under application’s HTTP context.
- Application warm-up module knows only requests it must send but it is not aware of scripting language or technology behind those requests.
ASP.NET 4.0 has also the other mechanism for application warm-up. I will blog about it soon.
More Posts