| ||
|
Get the sample source code! Tests To find out how much can be achieved in terms of performance, bandwidth, and consequently saved communication costs, here are some test results. The absolute numbers may not be as interesting as the relations between the measured values. Let's start by looking at the actual win in terms of bandwidth, and the first measures are for a small payload: ![]() Figure 1. Compression of small payload The uncompressed small payload was almost 2 KB (1878 bytes), and when compressed it was reduced to about half that size (for gzip to 955 and for deflate to 935). Note that all measured payload values are including the HTTP headers that are never compressed. Then, the large payload: ![]() Figure 2. Compression of large payload The uncompressed large payload was almost half a megabyte (456804 bytes), and when compressed it was reduced to about a tenth of that size (for gzip to 45322 and for deflate to 45303). The conclusion is that the larger the payload, the more we gain in terms of saved bandwidth with compression, and also that there is not much difference if we use "gzip" or "deflate" to compress. Therefore, the fact that the preferred format is "gzip" is no problem. When we look at performance, these are the measures for the small payload: ![]() Figure 3. Performance for small payload The uncompressed small payload was retrieved in a tenth of a second (100 ms). When the same payload was compressed (to about half the size, see Figure 1 above), retrieved, and uncompressed, the total time increased about a fifth (for both gzip and deflate to 120). This means that for small payloads, we save about 50% of the bandwidth, but have to pay with a performance penalty of about 20%. What about the large payload? The measures look like this: ![]() Figure 4. Performance for large payload The uncompressed large payload was retrieved in a little more than 9 seconds (9336 ms). When the same payload was compressed (to about tenth of the size, see Figure 2 above), retrieved, and uncompressed, the total time decreased to about half (for gzip to 5299 and for deflate to 5052). This means that for larger payloads, we save about 90% of bandwidth, and we also gain a performance win of about 50%. A few words about how the tests were done: The small payload was created from a DataSet with the Shippers table, and the large payload with the Orders table. Both tables come from the standard Northwind database. The tests were made with the emulator which means optimal network conditions and a fast processor, but other tests were made on physical devices (PXA255 processor) and with real-world network conditions (802.11b WLAN with my son gaming heavily online) that show very similar results (the relations between the values are almost identical). For example, a PXA255 on a WLAN retrieved the small payload in 330 ms, and compressed (retrieved and uncompressed) it took 360 ms (only a performance hit of about 10%). For the large payload, the uncompressed took 24 seconds to retrieve, and compressed it took 13 seconds (a performance win of about 45%). See the conclusion at the end of the article for a summary of the tests. Background The HTTP 1.1 Specification (RFC 2616) includes a specification for content compression, and in the latest version of IIS (Internet Information Services, 6.0), there is built-in support for this compression. This means that you can enable compression for all your ASP.NET and ASP.NET Web Service applications without changing any code. However, to use those applications from a client, you need to make some changes to the Web Reference (the generated proxy) to make it work. The details for doing that is nicely explained in the article Retrieving Data from Web Services using Standard HTTP 1.1 Compression by Jacek Chmiel. When trying to do the same thing with .NET CF, you encounter that you get a compilation error that can be fixed by the advice expressed in the excellent blog post Getting Web Services using HTTP 1.1 Compression to work in Compact Framework by Alex Yakhnin. Although parts of the solution can be found on the links mentioned, this article includes all the steps necessary to make a Pocket PC .NET CF application make calls to XML Web Services (written in ASP.NET and running on IIS 6.0) that uses HTTP 1.1 Compression. HTTP 1.1 Compression As described in the HTTP 1.1 Specification, content from a web server can be compressed using a number of algorithms. The client request compressed content by including a header named "Accept-Encoding" with the compressed formats it supports in a comma-separated list. The mostly used formats are "gzip" (RFC 1952) and "deflate" (RFC 1951), where "gzip" is the preferred format. If the server supports compression, the response will be compressed according to the format(s) specified in the request header ("Accept-Encoding"). To make all this work, there are some necessary preparations. First, HTTP 1.1 Compression must be enabled in IIS 6.0, and then the .NET CF files on the development PC must be updated. HTTP 1.1 Compression in IIS 6.0 To enable HTTP 1.1 Compression on IIS 6.0, you need to make some updates to the web server configuration. First, you need to enable compression for the file extensions that you want to use. As ASP.NET Web Services has the file extension ".asmx", that extension need to be enabled. First, we enable this extension (together with the default ones) for "gzip" compression by opening a Command Prompt, and running the following command (on one line):
cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs
set W3Svc/Filters/Compression/gzip/HcScriptFileExtensions "asp" "dll" "exe" "aspx" "asmx"
Note that compression is now also enabled for ASP.NET applications (using the file extension
".aspx"). Staying in the same folder, we can enable the file extensions for "deflate" compression
as well with the following command (on one line):
cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs
set W3Svc/Filters/Compression/deflate/HcScriptFileExtensions "asp" "dll" "exe" "aspx" "asmx"
Then, the default compression level (0) should be increased to make the compression rate higher
(9) without increasing the CPU usage too much. Here's what Scott Forsyth says in his article
IIS
Compression in IIS6.0:
"HcDynamicCompressionLevel has a default value of 0. Basically this means at if you did everything else right, the compression for dynamic contact is at the lowest level. The valid range for this is from 0 to 10. I had the opportunity of receiving an internal testing summary from Chris Adams from Microsoft regarding the compression level -vs- CPU usage which showed that the CPU needed for levels 0 - 9 is fairly low but for level 10 it hits the roof. Yet the compression for level 9 is nearly as good as level 10. I write all this to say that I recommend level 9 so make sure to change HcDynamicCompressionLevel to 9. Do this for both deflate and gzip." This level is changed (still in the same folder) for "gzip" by entering the command:
cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs
set W3SVC/Filters/Compression/gzip/HcDynamicCompressionLevel "9"
The same change is done for "deflate" with the command:
cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs
set W3SVC/Filters/Compression/deflate/HcDynamicCompressionLevel "9"
To make all these changes active, IIS needs to be restarted, and that can be done with the following command:
iisreset /restartThe above changes can also be done directly in the file C:\WINNT\system32\inetsrv\Metabase.xml (or C:\Windows\system32\inetsrv\Metabase.xml), but be sure to make a backup copy before you change it! Editing the Metabase.xml file also requires the IIS to be stopped before, and restarted only after the changed file has been saved. As this also means that you easier risk messing up your web server configuration, the above way (using the adsutil.vbs script) is clearly the recommendation. Just for reference, the two updated sections of the Metabase.xml file should look like this:
<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/deflate"
HcCompressionDll="C:\WINNT\system32\inetsrv\gzip.dll"
HcCreateFlags="0"
HcDoDynamicCompression="TRUE"
HcDoOnDemandCompression="TRUE"
HcDoStaticCompression="TRUE"
HcDynamicCompressionLevel="9"
HcFileExtensions="htm
html
txt"
HcMimeType=""
HcOnDemandCompLevel="10"
HcPriority="1"
HcScriptFileExtensions="asp
dll
exe
aspx
asmx"
>
</IIsCompressionScheme>
<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/gzip"
HcCompressionDll="C:\WINNT\system32\inetsrv\gzip.dll"
HcCreateFlags="1"
HcDoDynamicCompression="TRUE"
HcDoOnDemandCompression="TRUE"
HcDoStaticCompression="TRUE"
HcDynamicCompressionLevel="9"
HcFileExtensions="htm
html
txt"
HcMimeType=""
HcOnDemandCompLevel="10"
HcPriority="1"
HcScriptFileExtensions="asp
dll
exe
aspx
asmx"
>
</IIsCompressionScheme>
Now, you need to enable compression for dynamic content (application files) by following two steps:
cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs
set W3SVC/1/Root/WSCompression/DoDynamicCompression True
Ok, now HTTP 1.1 compression should be enabled on your web server, so let's go on and update the development tools.
Update Development Tools To allow the sample (see below) to compile in your development environment, you need to replace a file on the development PC. This is because the Service Pack 2 of .NET CF 1.0 support overriding some needed methods, but the SP2 installation does not update the development environment. But the files can be updated manually by following this procedure:
WSCompress Anyplace Sample Building on the samples mentioned (see the background above), the sample show how to call XML Web Services that use HTTP 1.1 Compression in your Pocket PC applications. This sample application is built for .NET CF with Visual Studio .NET 2003 and it looks like this: ![]() Figure 5. WSCompress Anyplace Sample The sample takes an entered table name (from the Northwind sample database) and sends it off to an XML Web Service on a server. That XML Web Service queries the Northwind database (SELECT * FROM
| ||||||||||||||||||||||||||||||||