Slashdot Mirror


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?"

17 of 677 comments (clear)

  1. Alternative to Visual Studio by Vaevictis666 · · Score: 5, Informative
    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?

    1. Re:Alternative to Visual Studio by Glock27 · · Score: 3, Informative
      Eclipse do not seem to support c# natively (I confess to not having tried the c# plugin).

      AFAIK, all language support in Eclipse is by plugin. You're basically saying you've never tried it, but you advise us to try something else.

      Huh?

      (I've used Eclipse a bit for Java, and it is excellent. I'm pretty sure it'll be a fine environment for many languages by the time it's all said and done.)

      --
      Galileo: "The Earth revolves around the Sun!"
      Score: -1 100% Flamebait
    2. Re:Alternative to Visual Studio by PianoComp81 · · Score: 3, Informative

      Eclipse can be good for other languages. My problem with it is that it's just too slow many times. I did have a problem in Windows getting C/C++ to compile, but I think it was looking for cygwin + gcc, and not the MSVC++ I had installed at the time. I too have used it extensively for Java, and probably wouldn't use anything else on a decent-sized project.

  2. Re:In Java's case ... by JasonB · · Score: 5, Informative

    Java SDK v1.5 (not yet released) contains support for 'generics', which are very much like C++ templates for Java:

    http://java.sun.com/features/2003/05/bloch_qa.html

  3. Conclusions by SimuAndy · · Score: 3, Informative
    After a quick registration, I'm enlightened by the conclusions I drew from his article:
    • 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. -andy
  4. Re:jump off the bandwagon by Cnik70 · · Score: 5, Informative

    You apparently haven't taken the time to work with any of the newer releases of java (1.3 and 1.4). Java is a very mature and worthy language, especially when it comes to developing non platform dependent applications. I prefer java since I CAN program it on a Linux box, transfer it to a windows, mac or even a mainframe and the program will still run exactly the same without changing a single line. lets see c, c++, .Net or c# do that... Also don't forget about a little thing called J2ME which is slowly but surely making it's way onto cell phones and other small devices. You may want to take another look at todays Java before declaring that it sucks.

    --
    -Cnik
  5. Re:jump off the bandwagon by MikeApp · · Score: 4, Informative

    You claim to have worked on numerous Java projects, then complain only about GUI apps? The large majority of Java projects are server-side, which is where it really rocks. Write once and deploy on your choice of platform (Linux, Solaris, or Windows if need be).

  6. Re:jump off the bandwagon by Dr.+Bent · · Score: 4, Informative

    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.

    I would be willing to bet the reason they failed is because you do not understand how to use Java correctly. As long as we're playing the personal experience game, it has been my experience that hardcore C/C++ programmers tend to make horrible Java programmers because they think Java should behave like C/C++. It doesn't (obviously), and when you try to shove that round peg into a square hole what you get is a huge mess.

    At my company, we have a bunch of old school C/C++ progammers and a few Java programmers. As our Java products started to take off (now our #1 selling product line), we wanted to move some of those developers over to Java to help out.

    It was a disaster. They made object pools in order to try to manage thier own memory. They were calling System.gc() and yield() instead of using a Java profiler to find bottlenecks. The never used lazy loading. They never used failfast ("exceptions are too slow!", they said). The result was all the projects they worked on were extremely brittle, used twice as much memory, and ran much slower than our original Java stuff because they were constantly fighting against the system instead of working with it.

    Try reading Effective Java by Josh Bloch and Thinking in Java by Bruce Eckel. Do what these guys suggest and your Java apps will run just as well than as anything written in C or C++.

  7. Re:I've been coding most of... by MobyDisk · · Score: 5, Informative

    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.

  8. SharpDevelop - #develop - GPL .NET IDE by Sean+Clifford · · Score: 4, Informative
    Well, there's always vi a la vim win32 port. :)

    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.

  9. Re:jump off the bandwagon by EMN13 · · Score: 4, Informative

    Server side tasks are just great for java; your arguments don't add up.

    Any platform I've heard of for server stuff will run java. C/C++ may have a wider distribution; but not amongst relevant platforms. Irrelevant to the discussion are portable/client side/ small / light platforms, and the computation heavy things. Servers are about "service" - the naming is not a coincidence.

    Most server processes run forever, or as close as possibly; not very short lived at all. Starting a new process (aka application) for every client is generally not best practice - those are threads, and don't require constant re-JIT-ing or other JVM/CLR overhead.

    Rather, the larger the system, and the more data, generally the less code in relation to that data, and even less JVM in relation to data. So for the quintessential server with tons of data gunk, the c/c++ advantage is much smaller than in the GUI.

    Furthermore, it is a mistake to compare the portability of java to that of c++ in the manner you do. c++ implementations aren't generally compatible. Take a look at the mozilla coding guidlines for portable c++: http://mozilla.org/hacking/portable-cpp.html

    c++ isn't portable, normally. C++-- might be though. Then again, it might not be. The java language is very standardized; and in case you shouldn't have a compiler on that platform, the bytecode is too!

    In conclusion, if you're using c++ for a server-side task you should consider using java instead. As a matter of fact, most scripting languages are probably better suited than c++, I can hardly image a worse fit.

  10. Re:But, the compiler/os should... by The+boojum · · Score: 3, Informative

    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.

  11. Re:I've been coding most of... by cookd · · Score: 4, Informative

    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.
  12. Re:What's with all of the bellyaching about speed? by GrayArea · · Score: 4, Informative
    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.

    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
  13. Re:Bad Kool-Aid. by Keeper · · Score: 3, Informative

    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).

    The next version of .Net (2.0) is supposed to introduce native template support to IL. Not sure about multiple inheritance, but I doubt it.

    The .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.

    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 .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.

    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 .NET supports are those which are subsets of C#. And once you realize that, .NET becomes much less interesting.

    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 .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.

  14. Re:jump off the bandwagon by cartman · · Score: 3, Informative

    I disagree.

    Garbage collection in Java is not guranteed... It'll clean up when it god damn well feels like it.

    This is false. Garbage collection in Java is guaranteed. The VM times the garbage collection to occur when the CPU was otherwise idle, or when additional memory is needed by the VM or by other programs. This is the most reasonable behavior.

    In the meantime, the system slows to a crawl.

    This is false. Garbage collection is deferred to improve performance. Deferring gc does not make anything "slow to a crawl," since unused objects consume no cache and take no processor cycles.

    Graphics in Java are abysmally slow.

    This is an exaggeration. It is noticeably less responsive however.

    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.

    Java requires far fewer debug cycles than C or C++, since an entire class of bugs (tricky "pointer bugs") is eliminated. Thus, "over and over and over" is not accurate.

    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.

    It's possible the difficulty was with you or your team, not Java. Perhaps you're unfamiliar with the tools or the language. Other organizations have produced enormous projects, successfully, in Java.

    Stick with C and C++ for most development, there's a reason they are the standard: they work.

    For backend development and enterprise applications, Java is the standard, not C or C++. It's been that way for some time. There's a reason for it.

  15. Am I the only person who read the article? by Ninja+Programmer · · Score: 3, Informative

    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.