Does C# Measure Up?
An anonymous reader queries: "Windows::Developer is offering a detailed, quantitative examination [free login required] of C#'s performance versus Java, C, C++ and D. 'Overall the results were surprising, although perhaps unexciting, in showing that C# (and to a less extent Java) is, to a good degree, on a par in efficiency terms with its older and (presumed to be) more efficient counterparts C and C++ at least as far as the basic language features compared in this analysis are concerned,' writes the author, Matthew Wilson. I'm only an amateur coder, and confess to not understanding most of the two-part article. I'd love to hear how true programmers view his results, which are too wide-ranging to summarize easily here. How about it Slashdot, as this special edition asks, 'Can C# keep up with compiled languages like C, C++, and D or byte-code based Java?'"
While we're on the topic of C#, rnd() queries: "It's been a while now, since Mono and DotGnu have begun eroding the market power of Microsoft by creating open source implementations of C# and the Common Language Runtime. Over the weekend I loaded Mono and did some informal benchmarking of object creation, intensive message passing, massive iteration, etc., and the results show that Mono is about 90% as fast as Microsoft's implementation after a very short time. I now want to switch my .NET development over to Linux/Mono exclusively, but I want to first settle on a free alternative to Visual Studio .NET 2003. Any suggestions?"
How about Eclipse?
Actually VB apps tend to run just fine through Wine, or at least a few little projects I've done in VB have worked for me...
I'm assuming you're asking for an IDE alternative to Visual Studio .Net. Take a look at SharpDevelop. According to its authors, it's open source under the GPL. I've given it a try on my old P2 300, and it's not bad at all IMO. It takes a little longer to load, but it has solid functionality and tons of features on an interface that looks very familiar to that of Visual Studio .Net
Java SDK v1.5 (not yet released) contains support for 'generics', which are very much like C++ templates for Java:
l
http://java.sun.com/features/2003/05/bloch_qa.htm
Java has received alot of attention over the last 7 or 8 years or so. It's a great idea in theory, but it falls way short in practice. It does remain viable for a few select uses, though: small widgets, servlets and web app servers. Pretty much other than that, using Java will mean excessive memory usage and slow performance.
Garbage collection in Java is not guranteed. It's what I call Union. It'll clean up when it god damn well feels like it. In the meantime, the system slows to a crawl.
Graphics in Java are abysmally slow. Even basic UIs lack the speed and responsiveness of GUIs written in C, C++ or similar languages.
Java was supposed to be: Write once, run anywhere, but what it is in reality is: Write once, debug everywhere... over and over and over. Or perhaps more appropriately it is" Write once, run screaming.
I've worked in a variety of Java development projects in the past and not once has it ever risen to the task to show itself as a worthy choice and/or a mature language. Instead it has invariably wasted companies time and money. Primarily because they failed to realize that Java is a small task tool, not suitable for major applications or those requiring performance.
I know a lot of engineers like Java because it makes life easier for them by doing things for them, but those things it does it does very poorly.
I'm sure I'll be marked as flamebait or troll by some Java loving mod, but what I've stated are facts and experiences from real life Java development. The results are in and frankly... Java sucks! Stick with C and C++ for most development, there's a reason they are the standard: they work.
- C# fares rather well.
- ... but almost never as well as native C and C++ implementations done "smartly".
- Java suffers from runtime-based overhead, with the advantage of a well-tested set of runtimes for various platforms. Unfortunately, due to the Java implementation of client-side runtime libraries, programming in Java is still "write once, test everywhere. curse. port everywhere" for real applications.
And most importantly, as a game programmer, I'm going to pay attention to the relative performance the author received from the Intel-branded compiler, written to the metal of the Pentium IV with streaming SIMD instructions. -andyHad no idea what you were talking about so I looked it up. From College Campus:
Weasel words. If your information is less than conclusive, acknowledge that either in summary or by choosing another argument. But don't undercut your argument with weasel words -- empty palliatives such as "to a certain degree," "it may seem likely that," or "in some cases." If your points are weak, they need no additional burdens. Note how much stronger the following become as the bracketed words drop out:
* [It may even be, as] some experts have hinted that Thomas More was [somewhat] suicidal [anyway].
* Josiah Royce was [to some extent] the Hegel of American philosophy.
Weasel words dilute your thought, and hence your argument.
Linkers already do this. At this point, it is ubiquitous functionality. The linker has a list of functions that are referenced, and functions that are not referenced. Functions and libraries not referenced are discarded. I know for MSVC, this is done by using /opt:ref which is part of the default RELEASE builds. This all works for OO code like C++ as well since the methods boils down to functions as far as the linker is concerned.
There are some special cases:
1) You mentioned strcat() which can be inlined by many compilers. In this case, you trade speed for code bloat - the library isn't really used at all here. In MSVC this is an "intrinsic" function.
2) Dynamic libraries may be treated differently. It is more difficult to try to partially load them. I'm not sure how Linux handles this. Windows allows for a DLL to contain multiple code and data segments, which can be loaded individually if needed.
Huh? Wine is a reimplementation of the Win32 API and some other stuff. It uses the C libraries directly; there is no emulation. Look at the code sometime.
Some of the largest online systems in the world run Java. On the server, Java is unbeatable. I've personally witnessed massive uptimes with none of the degradation you mention. And there's this company called IBM that bases much of their server business on Java (both through WebSphere and through their consulting arm.) These apps do not perform "small activities".
Your one little client app is probably written poorly, or with a buggy Java implementation. In short, you don't know what the hell you're talking about.
I do a lot of ASP3.0/SQL2k and some utility development on Win32, taking a stab at .NET. It would be nice to move over to Mono.
Anyway, I've done a bit of poking around and ran across SharpDevelop - AKA #develop . It's open source a la GPL and looks a lot like Visual Studio, and compiles C# and VB.NET; has C# => VB.NET code conversion; does projects or files; has syntaxing for the whole MS shebang. It's a .97 - this build was released Friday 9/12/2K3, officially in beta, and you can get the binaries here, go snag the source here, and get the MS.NET1.1SDK here.
To those folks who hiss and moan about the whole GNOME/.NET/Mono thing, take a gander at the rationale before playing jump to conclusions (mp3).
SharpWT - AKA #WT is a .NET port of Java SWT on both Windows/.NET and Linux/Mono platforms. So...you can develop your .NET apps to run on both Win32 and Linux with pretty much the same GUI. Neat, eh?
Anyway, intrepid Windows Developer, if you can pry yourself away from the MSDN Library for a few minutes, you might find there's something to this Mono business.
"For something that will do big work, require lots of memory and run for long periods, Java will come to bite you in the ass."
Like, say, large scale enterprise/website computing? Oh, wait, that is exactly the area Java excels at. Swing is a notorious hog, and I'm not familiar with your exact circumstance, so I can't really comment on it. But Java is pretty damn rock solid for long, throughput intensive tasks. I say throughput as opposed to latency because low-latency gui stuff is exactly where a VM (and garbage collection) will bite you in the ass. If performance is unbearable there is the native SWT library (like AWT redone from the ground up, but right). Java is not known for its good GUI/client side performance.
On the other hand, on the server side, latency is usually not the issue - most time will be spent on the network and database, NOT in your code. On the server side, VMs are here to stay. Python, PHP, Perl, Java, C#/Mono, all use VMs. The only real issue with VMs is latency, and with garbage collection its memory usage. I would strongly suggest though, that the vast vast vast majority of user-level/space applications in which C/C++ is being [ab]used, would be better written in a "safe", simpler, language like Java, precisely because in the vast majority of cases, CPU performance does not need to be optimized, and security, reliability, maintainability, and let's not forget, new features, take higher importance.
It's 10 PM. Do you know if you're un-American?
share portability in common. I can write an app in C, and run it on my server, laptop, palmtop, ancient SunServer, or even a Windows machine. The same goes for Java and C++.
.NET. Mono is a good start, but not enough to make my code reliably portable.
.NET is to make the platform compatibility promised by NT 4 available without opening the source.
If I use C#, I'm effectively locked into
C# has all the speed of Java with all the portability of X86 assembly linked to Windows libraries. Microsoft's BS patents will help ensure that the portability problems aren't corrected.
The real purpose behind
You can't judge a book by the way it wears its hair.
There are enough answers here, but I can't resist jumping in and clarifying.
Most modern compilers in conjunction with OS's already basically do this. GCC and MSVC and the like all will link in only the functions that they deem referenced by your program and it's dependencies, provided you statically link the library.
Dynamic link or shared libraries work differently. The OS "loads" them once and uses that one copy for all programs that require that library. The linker that builds the DLL has no way of knowing which functions in the library will be needed by the programs that may use. Some programs may only need one, others may need them all. So the DLL *has* to contain everything it needs to provide.
The tradeoff is that while static linking means the linker only links in what's nescessary, all executables that use it must provide the same copies of those functions linked into each one. DLL's have to have the whole kit-and-kaboodle, but there can be a single, globaly available copy on this system shared by each.
It's really a matter of pickin' yer poison.
Very complicated question. Ughh, there are answers at many levels, and they are all different. But here goes.
Any decent linker nowadays is "smart." This means that it already does what you are asking for -- it knows how to figure out exactly what the dependencies are, and bring in only the symbols (a symbol in this context is a chunk of code or data) that are (directly or indirectly) referenced by your code. Even though you link against all of the C Runtime, or all of the string library, the linker realizes that you are only using strcat. For this example, we'll assume that strcat uses strlen and strcpy. So your call to strcat pulls in strcat, strcpy, and strlen, but nothing else. So what you mention actually is already happening. (Unless you turn off the "smart" linking, as is common for debugging purposes.)
However, there are some additional factors at work. The first is the C Runtime (CRT). ANSI C has some very specific requirements about how the environment is to be set up before main() is called, and how the system is to be cleaned up after main() exits. C also has specs about how to prepare the system for unexpected termination and signal handling. Setup and cleanup reference a bunch of additional symbols, so you end up with much more than just main(), strcat(), strcpy(), and strlen() -- you also have atexit(), exit() and etc. There is usually a process by which you can get rid of this and start directly in main with no setup code, but then you can't use any of the CRT-supplied functions (since the CRT isn't initialized) -- you have to set up your process yourself, handle signals yourself, and are limited to calling OS functions directly (no nice wrappers like fopen, printf or such).
Then there is the issue of linking. Static or dynamic? Static linking means that all of the symbols you reference, directly or indirectly, are compiled into your binary. Dynamic linking means that all of the symbols are converted to references to external binaries, and when your binary loads, the external binaries will also load and you will use the symbol as defined in the external binary. Static linking means everything you need (and nothing you don't) is right there, compiled into your binary, so you'll never load anything you don't need. On the other hand, every program that is statically linked has its own copy of the linked-in routines, which can be wasteful of disk space and memory. With dynamic linking, the entire external binary has to be available, even if you only need one symbol from it. On the other hand, there only needs to be one copy of the binary on disk, no matter how many times it is used. And most of the time, the operating system can arrange things so that only one copy of the binary's code is loaded into memory, no matter how many processes are using it. This can save a lot of memory. For most systems, it turns out to be much more efficient to load a multi-megabyte dynamic link library into every process rather than statically link just the 200k that you actually need from that library.
Finally, there is the OS involvement. The OS has to do a certain amount of setup for any process, no matter how trivial that process is. It has to allocate a stack, map the process into memory, set up virtual memory tables for it, etc. On a modern OS, in order for it to provide the services we expect, it has to set up a bunch of stuff just in case the process decides to make use of it. It is the price we pay for having a lot of power available to us.
So for an example, I wrote up two test programs. I'm a Windows guy, so everything was done using Visual C++ 7.1. The first test was just an empty main(). Compiled and linked statically, it takes 24k on disk. That is basically just the CRT startup and shutdown code and the signal handlers (plus error message strings, etc.). It also links (dynamically) to kernel32.dll, ntdll.dll, and the OS itself. It allocates 568k of user memory/136k VM, 7k of kernel memory, and holds 14 kernel objects (thread handle, process han
Time flies like an arrow. Fruit flies like a banana.
Sure there is. Have a look at jawt.h header file that's included in your SDK installation. It allows you to access native window system primitives from JNI.
"The deluded are always filled with absolutes. The rest of us have to live with ambiguity." - Aristoi, Walter Jon Willia
That's just wrong. For one thing, "C" is a language, not an implementation; same for "Java." Languages have specs but they don't have any associated speed. Only specific implementations of languages have that. Thus, you can compare the speed of C code compiled with Microsoft Visual C++ 7.0 to the speed of code running under Sun's JDK 1.2.2, or you can compare "gcc -O2" vs "IBM JDK 1.3", but you cannot compare "C vs. Java" because those things are specs, and specs can't run code.
For another thing, you're mistakenly assuming that C# and Java are interpreted languages; they are not. (Neither is C a compiled language; there's nothing in the spec that keeps C from being interpreted.) Again, this can only refer to specific implementations, but even if you had done that, you would still not be right because all popular implementations of Java (notably Sun's and IBM's) have used either Just-In-Time compiling or HotSpot virtual machines (which also compile code.) Sun's Java 1.0 release, about eight years ago, was interpreted, but no version since then has been.
As far as the possibility of speed goes, languages that just variants of just-in-time compilation generally have a modest startup penalty. This was roughly 700 ms. the last time I measured it, but I understand it has gone down somewhat in more recent releases. (Scripting languages generally start up quite quickly, by way of comparison.) That makes Java unsuitable for things like "ls" that you run often, but it doesn't matter for many applications. As far as the possibility of optimization goes, virtual machine implementations have optimization options that aren't available to compiled languages. (The reverse is not true, to my knowledge.) For example, Sun's HotSpot VM optimizes at runtime and can dynamically take into account conditions at the time a program is run to make optimization decisions. Branch predictions that go one way with small files might go another way with large files, but (for example) a C++ compiler cannot possibly take this information into account, since all its optimization decisions are frozen when the code was compiled.
For my own part, I have done several performance comparisons of gcc 2.95 with Sun Java 1.3 and 1.4, and I have found them to be roughly at parity. Gcc may have had an edge in the 5% to 20% range, but I also found some applications where java was faster. (gcc needed to have -O2 to be able to compete with Java; without it, Java won almost always.)
There is an open source alternative IDE for .NET called SharpDevelop, which you get at http://www.icsharpcode.net.
It is not as good as VS2003, but quite near :)
Intelligence shared is intelligence squared.
Um...do you know how templates work? I'm not talking about typecasts when I say "lot of code". I'm talking about the almost identical copies each template function (usually, the only difference is a tiny comparison operation).
Now...I wouldn't consider the extra code to be a fault of template programming, since I can't think of a better solution that would be as fast (time-space, my friend). Templates don't even force you to have the extra code either, but libraries like the STL make use of the feature to speed things up.
There's a D?
D Programming Language Reference
Beware: In C++, your friends can see your privates!
If I understand the .NET framework correctly, there is no way to support either multiple inheritance or templates--in which case C++ cannot be accurately modeled in .NET. Nor will Java be .NETtable after 1.5, which will introduce pale imitations of templates (but imitation enough to give the CLR a hissyfit).
.Net (2.0) is supposed to introduce native template support to IL. Not sure about multiple inheritance, but I doubt it.
.NET CLR does not support multiple languages. It supports one language--C#. Its "multiple language support" comes from being able to compile down many functionally-identical languages with different syntaxes down to the same bytecodes.
.Net compilers compile to those set of instructions. This isn't very different from taking a C++ program and building an executable that consists of instructions for an x86 cpu. The machine (virtual or not) provides the facilities for performing the operations you want to do.
.NET supports are those which are subsets of C#. And once you realize that, .NET becomes much less interesting.
.Net brings to the table, and I personally think this isn't one of the big ones -- I think it's more of a "cool" factor than anything else -- but dismissing it outright because the design doesn't perfectly suite some obscure language that is generally used by AI researchers is kind of silly in my opinion.
The next version of
The
If you want to get technical, the CLR supports IL (implementation language), which is interpreted by the virtual machine. The virtual machine has a set of instructions it understands, and the various
If you can represent what you want to do in IL, you can write a compiler for it. There's some guy out there who wrote an 386 asm->IL compiler (why? because he could I guess...) for example. Not that I think it's a terribly great idea, but it is neat.
But truly different languages are not representable in the CLR. Show me how to do a Scheme continuation in the CLR, please, or export a C++ template, or a LISP macro.
IL doesn't have special instructions designed to support those things, but they can be done; they just won't be necessarily be done fast or efficently; for instance, you could do C++ templates the way your average C++ compiler does them --> your compiled code has a unique object for each templated type required. And I can pretty much guarantee you that you could write a Scheme or LISP compiler -- it'd just be a pain in the ass to do (which I'd imagine any proper LISP compiler would be), and it wouldn't be wicked fast.
The only languages
A more accurate statement would be that IL supports object oriented / functional languages very well, and other things not so well.
Most commonly used programming languages are OOP or functional in nature. I haven't used a non object oriented language since I got out of college. Perl, C, C++, Java, Basic, Fortran, Pascal, Python, Cobol, Smalltalk, various shell languages, etc. are all either functional or object oriented languages.
I'd argue that implementing optimal support in a form that most languages translate well to (as opposed to a form that rarely used languages translate well to) was a good design decision.
The power of this allows you to write code to get what you want done, instead of spending a lot of time writing code to get a round peg to fit in a square hole. There are many other peripheral benefits that
This is one of the specific things you can't really do with JNI and Java anymore. Java graphics is now really complicated. There's no way you'll be able to use low level OS rendering methods and have them integrate with Java2D and Swing.
Fortunately, the API is being steadily improved so the need for native methods is diminishing significantly with each version of Java. Have a look at these improvements in 1.4 over previous versions (it includes benchmarks you can run to see for yourself).
The key point here is that if you write your graphics code in pure Java, it will get faster with each new release, in many cases, without you having to lift a finger - and in 1.4, it can already take advantage of things like native hardware acceleration.
I don't know why the OP mentioned Lisp macros, because they certainly have nothing to do with the backend of a Lisp compiler. However, problems still do exist with compiling to IL, mostly focusing around calling-conventions and potential limitations instituted by the CLR.
For example, Common Lisp has advanced object-oriented features such as multiple-dispatch methods and method combination, and this would most have a large conceptual mismatch with the typical calling conventions used by languages in IL, hence the CL compiler would need to use its own calling conventions and would be incompatible with other languages (thus defeating the point of IL).
Same goes for memory layout, stack management, etc... all due to Common Lisp's advanced data types and capabilities such as multiple-inheritance, CHANGE-CLASS, resumable conditions...
As far as I know, all real Common Lisp compilers that support Windows have not yet made any serious steps towards adding an IL backend, since there is very little benefit to be gained until those issues can somehow be worked out. Franz, in particular, put out a list of roadblocks a few years ago, but I do not know what became of it.
Scheme, on the other hand, has call/cc which requires heap-allocated stacks. This has been a sticking point with Scheme on JVM; the Schemes there simply do not support the full call/cc as a result. JVM is very limited with what the call-stack can do, for "security" reasons. I imagine CLR has similar issues, unless someone clever found a way around it.
In general, the problem of an ideal "Universal Intermediate Representation" for all languages, so that only one backend is needed per platform, has been extensively studied for probably 30 years and I do believe the conclusion so far is: it's not possible.
I highly doubt that Microsoft has beat out academia in this regard.
As for your other statement regarding various languages and their supported paradigms, I would like to clarify something:
C, Basic, Pascal, Fortran, and Cobol are not regarded as functional nor object-oriented languages. I highly recommend you consult the definitions of said terms. In addition, I would not count the following as object-oriented languages, in an ideal world: C++ and Java, due to their mostly static (and pain-in-the-ass) nature.
(Hint: functional language means higher order functions and closures)
Those who do not know the past are doomed to reimplement it, poorly.
First of all -- what's the deal with this whole "WARMUPS" thing? This is just the most explicit way possible of training the JIT mechanisms without measuring its overhead. That might be fine if you believe that the overhead asymptotically costs nothing, however, I don't know what evidence there is of this. The test should use other mechanisms other than this explicit mechanism to allow the language itself to demonstrate that the overhead is of low cost.
The way this test is set up, the JIT people could spend hours or days optimizing the code without it showing up in the tests. This is the wrong approach and will do nothing other than to encourage the JIT developers to cheat in a way such as this just to try to win these benchmarks.
Ok as to the specific tests:
1. FloatInteger conversion on x86 are notoriously slow and CPU micro-architecturally dependent. It also depends on your rounding standard -- the C standard dictates a rounding mode that forces the x86s into their slowest mode. However using the new "Prescott New Instructions", Intel has found a way around this issue that should eventually show up in the Intel C/C++ compiler.
This does not demonstrate anything about a language other than to ask the question of whether or not the overhead outside of the fi rises to the level of not overshadowing the slowness of the conversion itself.
(That said, obviously Intel's compiler knows something here that the other guys don't -- notice how it *RAPES* the competition.)
2. Integer to string conversion is just a question of the quality of the library implementation. A naive implement will just use divides in the inner loop, instead of one of the numerous "constant divide" tricks. Also, string to integer will use multiplies and still just be a limited to the quality of implementation as its most major factor determining performance.
3. The Pi calculation via iteration has two integer->floating point conversions and a divide in the inner loop. Again, this will make it limited to CPU speed, not language speed.
4. The Calculation of Pi via recursion is still dominated by the integer divide calculation. It will be CPU limited not language limited.
5. The Sieve of Erastothenes (sp?) is a fair test. However, if SLOTS is initialized to millions, and the comparable C implementation uses true bits, instead of integers, then I think the C implementation should beat the pants off of C#, Java, or anything else.
6. The string concatenation test, of course, is going to severely ding C for its pathetic string library implemenation (strcat, has an implicit strlen calculation in it, thus making it dramatically slower than it needs to be.) Using something like bstrlib would negate the advantage of C#, Java, or any other language.
7. The string comparison with switch is a fair test, and gives each language the opportunity to use whatever high level "insight" that the compiler is capable of delivering on. It should be noted that a sufficiently powerful C compiler should be capable of killing its competition on this test, however, I don't believe any C compiler currently in existence is capable of demonstrating this for this case. I.e., this *could* be a legitimate case to demonstrate that C# or Java's high level abstractions give it an advantage over where the state of the art is in C compilers today.
8. Of course the tokenization is another serious ding on the rather pathetic implementation of the C library. None of strtok, strspn, etc are up to the task of doing serious high performance string tokenization. If you use an alternative library (such as bstrlib or even just PCRE) you would find that C would be impossible to beat.
-----
Ok, while the results here are interesting, I don't think there were enough tests here to truly test the language, especially in more real world (and less laboratory-like) conditions. Please refer to The Great Win32 Computer Language Shootout for a more serious set of tests.
Most commonly used programming languages are OOP or functional in nature. I haven't used a non object oriented language since I got out of college. Perl, C, C++, Java, Basic, Fortran, Pascal, Python, Cobol, Smalltalk, various shell languages, etc. are all either functional or object oriented languages
Imperative, they're imperative or OOP, not functional. Functional languages are languages exactly like LISP or Scheme. You construct a C program out of a bunch of statements, not a bunch of functions.
People keep saying that swing is only fast enough for simple gui's, but we've got a pretty good mapping system up with a fairly complex gui. The performance is slower than it would be in C++, but if you know swing, you can get pretty darn good behaviour from it.