Home  |  FAQ  |  About  |  Contact  |  View Source   
 
SEARCH:
 
BROWSE:
    My Hood
Edit My Info
View Events
Read Tutorials
Training Modules
View Presentations
Download Tools
Scan News
Get Jobs
Message Forums
School Forums
Member Directory
   
CONTRIBUTE:
    Sign me up!
Post an Event
Submit Tutorials
Upload Tools
Link News
Post Jobs
   
   
Home >  Tutorials >  General ASP.NET >  Performance Testing Visual Studio .NET
Add to MyHood
   Performance Testing Visual Studio .NET   [ printer friendly ]
Stats
  Rating: 4.76 out of 5 by 105 users
  Submitted: 01/31/02
Robert Wlodarczyk ()

 
Language Performance Test
Robert A. Wlodarczyk
Microsoft Student Consultant, SUNY Stony Brook



Overview
During the course of the Fall 2001, people throughout the computing industry have been learning more and more about Microsoft’s .NET Platform as a whole. We’ve seen a number of articles talking about how .NET will revolutionize the way the entire industry will develop applications over the next few years. Applications will become more and more ubiquitous, with users accessing their data from virtually anyplace in the globe off any device – desktop PC, tablet pc, PDA, or cell phone. .NET will be among the primary driving forces behind this.

Purpose
With the introduction of the .NET Framework, a few new languages, as well as new versions of existing languages are being released. It is important to take a look at how these languages stack up against languages and versions that currently exist and that many people are familiar with. In addition to see how all these languages compare, with the advent of the .NET Framework, applications are compiled to run on top of the Common Language Runtime (CLR). Here, applications run in a managed environment providing certain basic operations for your applications – type safety, code verifiability, memory management, thread management, and security. One important distinction between the CLR and other similar types of architectures, such as the Java Virtual Machine (JVM) or the Visual Basic Virtual Machine (VBVM), is that your code is never interpreted. This means that your code is being run at native machine speed. Such a performance test will be able to show that indeed this is the case. Finally, such a test will provide results showing the similarities and differences in speed between .NET languages and those that many are already familiar with.

How the test was performed
In this section, the details of the test will be discussed. This includes what languages and versions were used for the testing, as well as a description of the test machine. Finally, the way the tests were executed will be explained.

Languages Covered
Language Version
Sun Java 1.3.1_01
Microsoft C# 1.0 (Build 9466, RTM)
Microsoft Visual Basic 6.0 (SP5)
Microsoft Visual Basic .NET 7.0 (Build 9466, RTM)
Microsoft Visual C++ 6.0 (SP5)
Microsoft Visual C++ .NET 7.0 (Build 9466, RTM)
Table 1: List of all languages and versions used.

Test Machine
All tests were performed on a mid-range desktop consisting of the following setup:
  • ASUS P2B-F Revision 1011 Motherboard
  • Intel i440BX Chipset
  • Pentium III 600
  • 256Mb RAM, PC100, CAS #3

Testing was performed using the following software setup:
  • Windows 2000 Professional, Service Pack 2
  • Internet Explorer 6.0, all updates as of 12/21/2001
  • Visual Studio 6.0, Service Pack 5
  • Visual Studio .NET, Build 9466, RTM

Testing Code
For each of the tests, the essential basics of the performance are identical. Keeping such a performance test simple provides the end user with an easy way of interpreting the results. The core of each of the area of testing encompassed the use of the same code.
double tmrStart, tmrElapsed;
int i, j;

tmrStart = GetCurrentTime();
for(i = 0; i < 10000; i++)
{
for(j = 0; j < 10000; j++)
    {
        {do whatever test here}
    }
}
tmrElapsed = GetCurrentTime() - tmrStart;

Print(tmrElapsed);

Figure 1: Code framework used for all of the tests.

Since, in general, any single operation takes a considerably small amount of time, in order to be able to see a performance of a certain operation it must be repeated many times. In the case of these tests, a repetition of 100,000,000 was chosen. With such a high repetition rate, operations that would normally be nearly instantaneous take a considerable amount of time to complete.

When designing such tests, it is important to remember that the code that is adding in the {do whatever test here} section in Figure 1 must be written in such a way that the compiler cannot modify its operation. For example, if that code were x = 5, then most well optimizing compilers will remove the two for loops and just say x = 5 once. So, this code must be something that the compiler won’t have anyway to reduce to one operation.

Areas Covered
For purposes of this test, we looked at a number of different basic areas. Each area looks at potentially different implementations within the compilers.
Type of Test Class of Test
Integer Addition Integer Arithmetic
Integer Multiplication Integer Arithmetic
Double Addition Double Arithmetic
Double Multiplication Double Arithmetic
Object Instantiation Object Creation
Object Property Get Object Use
Object Property Set Object Use
Object Method Call Object Use
Table 2: List of types of test and their classifications.

Execution of Tests
All tests were run using an execution script that was written using VBScript and the Windows Scripting Host. All tests were repeated fifty times in order to reduce the variability of execution times. This provided us with variability of less than 2.5%, but on average less than 1.7%. Thus, our results have a very high confidence level. In Figure 2, you can see the general idea of how the VBScript was written to run all the performance tests.
for each language
    for each test type
        for 1 to N
            {perform the test}
            {wait M seconds}
        next
        {print the results from all the runs}
    next
    {wait Q seconds}
next

Figure 2: General schema of how the tests were executed.

For our particular instance, we chose M to be 10 seconds, and Q to be 150 seconds (2.5 minutes). The M time interval allows the system to “rest” for a brief period of time before running the test again. The Q time interval allows the system to “recover” from a particular language’s full run of tests. This may include memory cleanup or other such things. Essentially, this is provided to stabilize the system enough so that the next language is running under similar conditions as the first language did.

Results of the Test
All of these tests running on the machine, all as described above, took approximately 30 hours to run. Each type of test was later analyzed and compared to each other. In brief, we found that C# code is on average 3.30 times faster than native Java code. An interesting benchmark we found was that C# was on average 3.11 times faster than Visual C++ 6.0. Also, Visual Basic .NET code ran 46.45 times faster, on average, than Visual Basic 6.0 code.

On a category basis, we find that C# is 2.68 times faster in integer arithmetic than Java, 1.46 times faster in double arithmetic than Java, 1.93 times faster in object instantiation than Java, and 5.38 times faster in object use than Java.

A listing of all the average runtimes for all the languages and types of test are in Table 3. Also provided is a table listing the variability for each of the tests performed. These results can be seen in Table 4. For graphs of the data, take a look at Graph 1, Graph 2, and Graph 3.
Integer Addition Double Addition Integer Multiplication Double Multiplication Object Instantiation Object Property Get Object Property Set Object Method Call
C# 505 1515 506 1517 5349 335 334 334
VB.NET 342 6078 343 6074 5183 342 342 677
VC++.NET 0 1653 0 1655 85111 0 1093 3070
VB 6.0 670 1892 1346 2529 1212860 18705 16853 18369
VC++ 6.0 505 1598 676 1659 79329 0 337 1517
Java 1.3.1 1185 2192 1521 2246 10341 1017 1020 3364
Table 3: Listing of all the run average runtimes for each of the tests and languages. All times are presented in milliseconds.


Integer Addition Double Addition Integer Multiplication Double Multiplication Object Instantiation Object Property Get Object Property Set Object Method Call
Variability Min 0.00% 0.05% 0.00% 0.10% 0.03% 0.00% 0.02% 0.05%
Variability Max 2.21% 0.65% 2.02% 0.67% 2.37% 2.10% 1.48% 1.47%
Variability Average 1.03% 0.28% 0.86% 0.31% 0.56% 0.83% 0.88% 0.51%
Variability SD 0.69% 0.19% 0.74% 0.18% 0.87% 0.90% 0.62% 0.50%
Table 4: Composite listing of the variability of the test results for each type of test. Notice that all variability is below 2.5%, and on average below 1.7%.


Graph 1: All the data, graphed. Please note, some data is way off the graph. It's displayed like that so that you can see the bars for all the data.


Graph 2: C# vs. Java


Graph 3: C# vs. VC++ 6.0 vs. Java

References




Other
All the code will be submitted as a tool to DevHood (hopefully it's approved). If you have any questions, please feel free to email me!

Credits
Visual Studio .NET, C#, Visual Basic, Visual C++ are copyrights of the Microsoft Corporation. Java is a copyright of the Sun Corporation. Performance test results are copyright Robert A. Wlodarczyk, 2002.

Return to Browsing Tutorials

Email this Tutorial to a Friend

Rate this Content:  
low quality  1 2 3 4 5  high quality

Reader's Comments Post a Comment
 
This is really interesting. Can you tell me why the MC++ numbers seem to be "goofy" in comparison to the others?
-- Chris Mitchell, January 31, 2002
 
I would be interersted the compiler options that were specified in the tests for the various languages. Without this information, it seems to me that the performance of the different languages can be "cooked up" to suit the author's believe. Now, I am by no means accusing the good author in any way (did someone say he crippled Java before the test? 8). But for example, since VC++ 6.0 only includes CPU-specific optimizations up to the Pentium Pro, but VC++ .Net has P4 SSE2 optimizations turned on (I know this didn't happen, since the testbed was only a PIII. It's just an example.), the it is natural to expect VC++ .Net to be faster.

Now, I know VC++ .Net wasn't faster than VC++ 6.0. But I'm just saying that such a technique could have been used to "prepare" the data in a certain way, and I'd appreciate it if we can see a little more of the methodology being discussed.
-- Rick Leung, January 31, 2002
 
Rick,
I've posted all the code (in the tools section) and the project files for VS.NET and VS 6.0 and VB 6. You can take a look at how the compiler options are set since I compiled from within the VS.NET environment (not command line)[in retrospect, maybe i should have extended the "RunTests.bat" file to compile for me too...]. For java compilation, I just copied all the .java files to the jdk1.3.1_01\bin directory and ran "javac *.java" which created for me all the .class binaries.
Rob.
-- Robert Wlodarczyk, January 31, 2002
 
Great article, but I was curious if this technique can be ported to say a perl or korn shell platform
-- Matt Trepina, February 01, 2002
 
Those numbers strike me as odd. For example, VB.NET code is about a third faster than VC++ at integer addition? I don't see how that's possible because addition in VC++ comes down to a simple add, and mov. I don't see how it's possible to get much faster than that, especially with an interpreted language. Also, C# is actually slower than VB.NET code, when both compile to managed code. Why would there be any difference between integer addition in different languages in MSIL? Also VB.NET is almost 17 times faster than VC++.NET for object instantiation? If those numbers are right, then it seems that the expectation that all languages would run about the same in .NET was completely incorrect, and it would seem that there are some strange quirks with managed code.
-- Jason Bouzane, February 01, 2002
 
Well, remember that there are 3 different compilers: C#, VB.NET, VC++.NET. Each one may optimize the code differently. Further, each of the .NET comiler will generate slightly different MSIL code (this can be more or less efficient MSIL code ie: 5 lines vs. 8 lines).
-- Robert Wlodarczyk, February 01, 2002
 
This is a great article. Rob excellent job.
I will like to point out that the numbers for Visual C++ do make sense because object instantions mean the construction and destruction of object including allocation and deallocation of memory. Microsoft's memory implementation is not the greatest and suffers greatly when its put to the limit. DO REMEMBER that GC'd languages recycle freed objects for reuse so that test is misleading. To replicate what occurs in .NET and java you would have a freed class pool or some other impl. Therefore what was written may be equivalent however without writing your own GC system into the C++ code the program does not compile into the same program.
-- Kryspin Ziemski, February 01, 2002
 
I would love to see first-hand the capabilities of this product. The download should be helpful, however are there any development sites with tutorials that help you become acquainted with this .net product?
-- Steve Hulin, February 01, 2002
 
Sure, you're at one right now. :-)
-- Bryan Hassin, February 01, 2002
 
It would be nice to have a summary of the flags/settings for each language, so we don't have to download and pore over the code to discover these things. From experience, these can have a significant impact on the performance of benchmarks.
-- Adrian Solis, February 01, 2002
 
Actually, come to think about it, it would be nice to try to optimize the programs for each platform, then run the benchmarks again. As it is, the results seem to be measuring "out-of-the-box" functionality. A test to measure the "true potential" of each language would be interesting indeed.
-- Adrian Solis, February 01, 2002
 
I think the tests are too simple. One of the problem with the "jitted" languages with a stack IL is probably that the code optimization for instruction level paralelism (superscalar architecture) is not that good. But there is no way a compiler can show its power with a simple loop and some simple arithmetic instructions.

The MSVC numbers are suspiciously low. Did you turn on optimizations ? Did you bother trying the intel C++ compiler ?


-- Michael Ho, February 01, 2002
 
For VC++ 6 & .NET, I used the default settings for a 'Release' build. For C# I also used the default settings. For VB.NET and VB 6, I used the default settings with a change for 'Remove integer overflow checks' since in C#, VC++, and Java (as far as I know) this option is turned on by default since there isn't an option for this in the IDE. For java compilation, I used 'javac *.java'.

Some of the VC++ data looks low (ie: the 0 ms values), I agree. However, there may be something slick that the compiler is doing there. I'm going to try to follow up on this after looking specifically at the VC++ "issues" in some more details with a few other people.
-- Robert Wlodarczyk, February 01, 2002
 
I just looked at the source for IntegerAdditionCPP7, decompiled the executable, and compared the results. The compiler is definitely pulling some tricks here, as there appears to be no sign of either for loop. This optimization is valid, because the value of iTest being painstakingly calculated in the loop is not used anyway. The C++.NET compiler must have recognized this and eliminated the loop entirely.

I suspect a similar thing is happening with the integer multiplication and object property access tests. Glancing at the source code, it seems that these tests follow the pattern of doing a bunch of calculations and not using the result. (Modifying the object property test to actually make the program access the property each time through the loop might be a little tricker -- a good compiler may be able to pick up on the fact that the object is not modified during the loop and choose to access the member only *once*, then using the same value as it goes through the loop.)
-- Adrian Solis, February 02, 2002
 
An interesting area to increase programming performance.
-- Sunny Lam, February 02, 2002
 
That certainly explains the result. However, I think we should move this discussion to the thread Robort started on the subject (Performance in the Common Language Runtime forum) as the comments area wasn't meant for discussion.
-- Jason Bouzane, February 03, 2002
 
I posted some critiques of the comparison on the Performance thread in the Common Language Runtime area. See:
http://www.devhood.com/messages/message_view-2.aspx?current=last&thread_id=4898
-- John Lambert, February 04, 2002
 
One thing to note, the build from the .NET Framework is 3705 and the build for the VS.NET IDE is 9466. You list the languages as build 9466, but I think it should be listed as 3705, since it's more related to the Framework.
-- Andrew Ma, February 04, 2002
 
Great article, but I was curious if this technique can be ported to say a perl or korn shell platform
-- manuel torres, February 14, 2002
 
After reading this article it got me thinking about the difference in the performance between Java and C#.

I thought that I would conduct my own tests, based on the source code you provided. I modified a few things. I made all tests run from a single Class, with each test being its own method. Then within the main method I called all tests 10 times each, to attempt to get the VM optimisations to work. I also added an extra test, with regards to strings, as I have always felt that Java strings are one of poor performing areas, and I wanted to see if C# did any better.

Rather than just use the Sun JVM Client, I thought I would try out a few of different available JVM's to see if it made much of a difference.

The tests were all run on a AMD 1.2GHz PC, with 768MB of memory.

The results suprised me:

Test Description C# SUN SUN SUN IBM JRockit
JVM JVM JVM JVM JVM
1.3.1 1.4.0 1.4.0 1.3.0 3.1
Client Client Server

Integer Addition 260.4 350.8 421.4 95.2 202.2 246.6
Integer Multiplication 783.1 598.8 600.0 39.1 519.9 515.4
Double Addition 1341.9 2800.0 2628.7 3777.3 712.0 633.2
Double Multiplication 1194.7 2790.0 2623.8 3835.6 521.7 548.8
String Addition 671.0 4469.4 4147.9 3903.6 4604.6 3916.5
Object Instantiation 1543.2 9113.1 8298.0 7800.2 11921.2 7519.8
Object Method Call 261.4 1271.9 432.7 3.0 219.4 211.7
Object Property Get 174.3 1793.6 366.4 5.0 172.2 211.5
Object Property Set 174.3 1397.7 357.7 20.0 174.2 210.0


Based on these results, the Java VM is faster than the C# in many of the tests.

It does however proove that Java has a very large weak point, at that is how it handles Strings and creation of Objects. If it was not for these 2 tests, I would conclude that as long as you are using the correct JVM with the correct settings, the performance can be on pare or better than that of C#.

Interesting.
-- Matthew Winter, February 22, 2002
 
Good stuff! ****
-- Sean Fitzgerald, March 14, 2002
 
Very interesting article.
I had done a very basic double multiply benchmark which might be of interest:
http://home.iSTAR.ca/~neutron/dotnet/BenchMarks/
(note that the VC++6 was for Standard Edn. so no optimation was possible)
-- Mitch Gallant, March 17, 2002
 
Good tutorial.
-- Brian Simoneau, March 18, 2002
 
Good piece of work .. but:
Object creation comparision .NetFramework vs. VC++6.0 does not make sense

Make Your test TRUE - for .Net vs VC6.0 comparision
set VBScript M parameter to 0 (zero) - and then publish results..... ;)

for each language
for each test type
for 1 to N
{perform the test}
{wait M seconds}
next
{print the results from all the runs}
next
{wait Q seconds}
next

I am afraid, You will have to wait far far longer than 30 h
to get .Net framework finished its work....

best rgrds

Lukasz Wilczynski
MCSD

PS.
M=10 sec ;)) - I must admit - it was pretty smart move to get
"fantastic" results ;)))))
PS2.
"An interesting benchmark we found was that C# was on average 3.11 times faster than Visual C++ 6.0" - ROTFL - about word "average"
-- Lukasz Wilczynski, March 26, 2002
 
Re-ran the tests on a Intel P4 2.2Ghz box with 512 MB DDR RAM. I made the following changes:

- 1 sec. rather than 10 sec. break between execution of each test.

- 1 minute rather than 2.5 minute break between language suites.

- Added a Native VC.Net test. The original test used C++ compiled for the CLR (not native execution) and did not make this clear. IMHO, this is important information to have because many corporate applications and a majority of commercial applications will probably run native C++ for years to come. It also shows that the Native .Net C++ compiler appears to do a pretty good job at some optimizations like hoisting invariant or unused stuff out of loops.

- Java 1.3.1_02
- Rather than one test, I seperated it into two - one for server Hotspot and the other for the client Hotspot. The server hotspot uses more aggressive optimizations, but also more resources (and actually uses a different Hotspot jvm.dll).

- Added Java 1.4.0
- Both server and client jvm's as above.

------------------------------------------------
*** C# TESTS ***
Integer Addition:
93.75, 93.75, 78.125, 78.125, 93.75,

Double Addition:
1296.875, 1281.25, 1265.625, 1281.25, 1281.25,

Integer Multiplication:
78.125, 93.75, 93.75, 93.75, 78.125,

Double Multiplication:
1281.25, 1281.25, 1281.25, 1296.875, 1281.25,

Object Instantiation:
1296.875, 1296.875, 1296.875, 1296.875, 1312.5,

Object Property Get:
62.5, 78.125, 78.125, 78.125, 78.125,

Object Property Set:
93.75, 93.75, 109.375, 93.75, 93.75,

Object Method Call:
78.125, 78.125, 78.125, 78.125, 78.125,

------------------------------------------------
*** VB .NET TESTS ***
Integer Addition:
62.5, 62.5, 62.5, 62.5, 62.5,

Double Addition:
5609.375, 5593.75, 5593.75, 5593.75, 5593.75,

Integer Multiplication:
78.125, 62.5, 62.5, 62.5, 62.5,

Double Multiplication:
5593.75, 5593.75, 5593.75, 5593.75, 5593.75,

Object Instantiation:
1265.625, 1265.625, 1265.
-- Dave Fladebo, May 28, 2002
 

I previewed the last post, and it did not cut the message off as it showed up. To see the complete post, look for it under the "Performance Comparison" topic in:

news:microsoft.public.dotnet.framework.performance
-- Dave Fladebo, May 28, 2002
 
very thorough and well presented!
-- Edward Kim, May 29, 2002
 
Wow, how'd i miss this one for so long. This was one of the more interesting readings i've done in awhile, great job Rob. Rating: a legitimate 5 *'s.
-- Lee B, September 28, 2002
 
Can anyone explain the huge differnce in performance between C# and VB.NET?
-- Big Taco, January 30, 2003
 
The VB.Net benchmarks are all incorrect.
When you disassemble the code, you'll see that what's really being measured is the time of the loop, not the time to perform the math tests.
The VB.Net for-next loop does not correspond exactly to the C# loop. This is because C# puts the onus of a correct conditional on you (in the conditional statement) whereas VB.Net takes responsibility for incrementing or decrementing the step, and doing the appropriate comparison. When using floating point numbers, this involves calling a function, which involves overhead.
Change the loop index variables to integer type, and you'll find the VB.Net results are, as expected, virtually identical to the C# results.

Benchmarking is VERY difficult to do correctly. It is essential to always examine the assembly to be sure you are measuring what you think you are measuring.

Dan

-- Dan Appleman, January 30, 2003
 
Copyright © 2001 DevHood® All Rights Reserved