|
Java/C# are entering the HPC picture as well. But if you are tight on memory, stick with C++. Garbage collectors can be faster than manual memory management, but they use a lot more memory as any paper on the topic will tell you.
|
|
|
|
|
Hello,
Where should i start?
At first, i like articles which deals with such complex topics but i think the actual version need some improvements.
I think it isn't possible to find a general answer because it depends from the point of view.
You write: The reason why C# compiled applications could be faster is that, during the second compilation, the compiler knows the actual run-time environment and processor type and could generate instructions that targets a specific processor.
It will also not be able to take advantages of the Core 2 duo or Core 2 Quad's "true multi-threaded" instruction set as the compiler generated native code does not even know about these instruction sets.
Never heard about it. The most common way to control or optimize threading is the WIN32 API (f.e. control affinity mask to specifiy cpu). The API hides such details and generalize the usage via HAL. Then you already have a "true multithreaded" application. If your application is well designed it dosen't matters which cpu environment is present.
You write: In the earlier days, not much changes were introduced to the instruction set with every processor release. The advancement in the processor was only in the speed and very few additional instruction sets with every release. Intel or AMD normally expects game developers to use these additional instruction sets. But with the advent of PIV and then on, with every release, PIV, PIV HT, Core, Core 2, Core 2 Quad, Extreme, and the latest Penryn, there are additional instruction sets that could be utilized if your application needs performance. There are C++ compilers that generate code that targets specific processors. But the disadvantage is the application has to be tagged as "This application's minimum system requirements are atleast a Core 2 Quad processor" which means a lot of customers will start to run away.
I must diagree. Well, special instructions sets exists like SSE but there are serveral ways to dynamically use them.
You write: How many of us can manage memory efficiently in a C++ application that's so huge say a million lines of code? It's extremely difficult to "well-design" a C++ program especially when the program grows larger. The problem with "not-freeing" the memory at the right time is that the working set of the application increases which increases the number of "page faults". Everyone knows that page fault is one of the most time-consuming operation as it requires a hard disk access. One page fault and you are dead. Any optimization that you did spending your hours of time is wasted in this page fault because you did not "free" memory that you no longer needed.
I must also disagree, in C++ there are serveal ways to manage the memory very effective (more effective as C#).
Of course Page Faults are a critical situation but Page Faults will be raised if a requested memory page isn't present in the RAM (stored in swap file).
That's all. I hope it's a constructive feedback .
Ciao...
|
|
|
|
|
Quick article and the information about the two time compilation is good.
I am new to C#/.Net world. But I think the second time compilation at when we run
the application will make the starting of the application slower
But IMHO, We can use C++ smart pointers to manage memory without problem
And we don't need to ship a big runtime with our application.
|
|
|
|
|
For improving application load time, installer programs can be set to "NGen" the code.
NGen is a native code generator that compiles a C# application to native exe. This process is usually
done by the installer. Secondly, the .NET framework is present in all machines after Windows XP SP2.
this means, you don't have to ship the framework seperately for atleast 90% of the machines.
Regards,
Mugunth
Thanks & Regards,
M.Mugunth Kumar
M +65 82448625
W http://mugunth.kumar.googlepages.com
B http://tech-mugunthkumar.blogspot.com (Technology Blog) *NEW
Nanyang Technological University,
Wee Kim Wee School of Communication and Information,
31 Nanyang Link, Singapore - 637718.
|
|
|
|
|
90% simply isn't good enough
Unless the app you are writing is going to be ran ONLY on PCs that you have control over, then you MUST include the .NET framework in your install (or at least have your installer dynamicly install it).
Would you seriously ever do business with a company that guaranteed 90% uptime?
|
|
|
|
|
A couple things to note about this comment.
The JIT (Just In Time) compilation doesn't happen entirely at start time. It literally happens "just in time". In addition, this can be done at installation time instead. Finally, on this point, the IL is specifically designed to be fast to compile.
Yes, you can use smart pointers to manage memory in C++. However, by itself, a smart pointer doesn't do much to improve performance. Specialized allocators would be required to really optimize performance there. And there's an issue with memory management that is very difficult to address in C++, that's automatically handled in .NET. Memory allocations in C++ generally can lead to fragmentation and excessive page faults. The GC in .NET, on the other hand, is a "compacting garbage collector", which eliminates fragmentation and can reduce page faults.
There's a very interesting series of articles on this topic by some of the top Microsoft developers, both experts at optimizing code. http://blogs.msdn.com/ricom/archive/2005/05/10/performance-quiz-6-chinese-english-dictionary-reader.aspx[^].
William E. Kempf
|
|
|
|
|
FYI, I am new to .Net world.
William E. Kempf wrote: The JIT (Just In Time) compilation doesn't happen entirely at start time. It literally happens "just in time".
Compiling at "Just in time" makes the user feel like using a slower application.
William E. Kempf wrote: In addition, this can be done at installation time instead.
This seems to be a good option. But still the executable runs under the runtime where the slowness problem comes in.
William E. Kempf wrote: Finally, on this point, the IL is specifically designed to be fast to compile.
IL is designed to be fast to compile but the JIT Compiler is not compiled for the specific processor so JIT compiler gives us faster executable for the specific processor but the JIT compiler itself is slower because of the generic code in it.
William E. Kempf wrote: Yes, you can use smart pointers to manage memory in C++. However, by itself, a smart pointer doesn't do much to improve performance.
Smart pointers are to manage memory not to increase the performance.
And in C++ most of the time we don't need to use "new" to allocate heap memory.
We can avoid it as much as possible and use smart pointers whenever we need it.
But .Net allocates objects in heap memory and wait for GC to collect.
Thanks and correct me if i am wrong
|
|
|
|
|
.NET Framework during installation, installs not the IL code, but a NGen'd version of the IL code. Similarly, using our installer, we can "second compile" the application during installation using "NGen.exe". This is one way to improve the performance by preventing the second compilation that happens during startup.
Thanks & Regards,
M.Mugunth Kumar
M +65 82448625
W http://mugunth.kumar.googlepages.com
B http://tech-mugunthkumar.blogspot.com (Technology Blog) *NEW
Nanyang Technological University,
Wee Kim Wee School of Communication and Information,
31 Nanyang Link, Singapore - 637718.
|
|
|
|
|
Thanks Mugunth, I understand the NGen and the performance benefits.
|
|
|
|
|
codeprojecter_ wrote: Compiling at "Just in time" makes the user feel like using a slower application.
Maybe, maybe not. Since small amounts are being compiled, and they're compiling fast, in many circumstances the user can't even perceive the compilation overhead. There's too many variables to consider here to make a blanket claim one way or the other.
codeprojecter_ wrote: This seems to be a good option. But still the executable runs under the runtime where the slowness problem comes in.
I don't understand this comment. The "runtime" in this case is just an API, no different than running under the Win32 "runtime". With the way you said this, it seems like you think it's still somehow running in an interpreted mode. It's not. It's running as native code. The only overhead to the .NET runtime would be the overhead of the security features, and that's not overly significant and is likely worth the cost for most applications.
codeprojecter_ wrote: IL is designed to be fast to compile but the JIT Compiler is not compiled for the specific processor so JIT compiler gives us faster executable for the specific processor but the JIT compiler itself is slower because of the generic code in it.
You're making assumptions there. I'm not going to make any claims to know how the JIT is performed, as I've never had a reason to care enough to research it. But there's no reason not to assume the code that performs the JIT wasn't NGened and thus running optimally for the platform.
codeprojecter_ wrote: And in C++ most of the time we don't need to use "new" to allocate heap memory.
We can avoid it as much as possible and use smart pointers whenever we need it.
But .Net allocates objects in heap memory and wait for GC to collect.
Actually, you do have to use new to allocate heap memory most of the time. The other options are malloc and cousins and custom allocators, but for custom classes these options have to use at least placement new to construct the object. Maybe you didn't mean to say "heap" memory, and meant that you could instead rely on stack allocations, but I'd contend that most applications will rely on at least as much heap, if not significantly more, as it will stack.
And again, in case the point wasn't understood, smart pointers don't do anything for performance, or for dealing with allocations. They only address issues with deallocation. The GC addresses so much more than that, and produces significant performance benefits. Yes, there's drawbacks, such as the non-deterministic nature of collecting, and the fact that it addresses only memory and not other types of resource acquisitions, so I'm not trying to oversell the GC. But strictly discussing performance, which is the point of this article, the GC is a better general purpose solution.
BTW, the CLR uses both stack and heap allocations. It's just not as easy to determine where allocations occur.[^]
William E. Kempf
|
|
|
|
|
William E. Kempf wrote: Maybe, maybe not. Since small amounts are being compiled, and they're compiling fast, in many circumstances the user can't even perceive the compilation overhead. There's too many variables to consider here to make a blanket claim one way or the other.
May be True.
William E. Kempf wrote: I don't understand this comment.
Sorry if i am confusing. English is not my native language.
William E. Kempf wrote: it seems like you think it's still somehow running in an interpreted mode. It's not. It's running as native code.
Yes i am trying to say about the interpreted nature of IL. I understand the NGen's native code.
William E. Kempf wrote: The only overhead to the .NET runtime would be the overhead of the security features, and that's not overly significant and is likely worth the cost for most applications.
The "only" overhead ?
William E. Kempf wrote: You're making assumptions there. I'm not going to make any claims to know how the JIT is performed, as I've never had a reason to care enough to research it. But there's no reason not to assume the code that performs the JIT wasn't NGened and thus running optimally for the platform.
I just assumed nothing more nothing less
William E. Kempf wrote: Maybe you didn't mean to say "heap" memory, and meant that you could instead rely on stack allocations, but I'd contend that most applications will rely on at least as much heap, if not significantly more, as it will stack.
I try to mean the stack memory. Yes C++ application depends on heap. But i hope not for all objects which .Net objects does.
William E. Kempf wrote: But strictly discussing performance, which is the point of this article, the GC is a better general purpose solution.
In the scope of this article GC is a better "general purpose" solution
William E. Kempf wrote: BTW, the CLR uses both stack and heap allocations. It's just not as easy to determine where allocations occur.
Link seem to be not working
|
|
|
|
|
codeprojecter_ wrote: Yes i am trying to say about the interpreted nature of IL. I understand the NGen's native code.
JITed code is native as well. Nothing is ever "interpreted" in .NET. It's always executed in the platforms native language. What's in question is when the code is transformed into this native language. It can actually happen at three different times: during compilation (hardly ever done), during installation (NGen) or during runtime (JIT). Once compiled, there's no overhead to the runtime beyond security.
codeprojecter_ wrote: The "only" overhead ?
Depending on how literally you mean that, yes. Obviously every API call has overhead associated with it, but between managed and unmanaged APIs, this is a level playing field.
codeprojecter_ wrote: In the scope of this article GC is a better "general purpose" solution
Not just in the scope of this article. It's well established that garbage collection provides a more efficient "general purpose" solution to memory management. A garbage collector can perform significant optimizations to both allocation as well as deallocation of memory. Don't take my word for it, search for the numerous scientific papers written on this subject.
codeprojecter_ wrote: Link seem to be not working
Seemed to work for me. http://www.yoda.arachsys.com/csharp/memory.html[^]
William E. Kempf
|
|
|
|
|
William E. Kempf wrote: It's well established that garbage collection provides a more efficient "general purpose" solution to memory management. A garbage collector can perform significant optimizations to both allocation as well as deallocation of memory. Don't take my word for it, search for the numerous scientific papers written on this subject.
Unfortunatelly, in practice it is simply not the case. I believe there was an article on "Lambda the Ultimate" explaining that you need a VM manager that cooperates with the GC in order to get better performance compared to native allocations.
|
|
|
|
|
I'd have to see a link to the article before I could comment.
William E. Kempf
|
|
|
|
|
|
I think this quote, found in the comments, by the author of the research paper himself, sums it up:
I think the paper highlights that, unless memory is an issue, GC is a reasonable choice for performance (and a clear win once software engineering is included).
In other words, manual memory management always has the potential to be the most efficient, but often requires significant engineering to do so. There are other trade offs, though, including memory consumption and determinism.
BTW, the paper also didn't evaluate the .NET collector or any collector using similar collection algorithms. I won't venture to guess if the concurrent collection improves or degrades the performance, though.
William E. Kempf
|
|
|
|
|
And I find your quote to sum it up even better:
William E. Kempf wrote: In other words, manual memory management always has the potential to be the most efficient
The simple truth is that a generic GC cannot know the internal logic of my software and cannot know the best strategy to manage memory (I am not going to even mention other resources, such as locks, files, handles...).
But theory aside, give me an example of a performant GC application. I have never tried one, and some that are "poster-boys" for GC performance such as Eclipse or Paint.NET are simply crawling compared to similar native applications.
|
|
|
|
|
Nemanja Trifunovic wrote: But theory aside, give me an example of a performant GC application. I have never tried one, and some that are "poster-boys" for GC performance such as Eclipse or Paint.NET are simply crawling compared to similar native applications.
Eclipse is certainly not performant. But then, I think Java in general doesn't do well in this arena. To be fair though, it doesn't perform significantly worse than VisualStudio, depending on which plug-ins you have active (emphasis on significantly, because there is a noticeable difference).
Paint.NET, OTOH, is a very nice example. I'm very curious what makes you claim it's "simply crawling compared to similar native applications"? I'm more than willing to bet the average user would be unable to differentiate this from a native application. In my experience, it loads images faster than similar applications that come with digital cameras. It applies filters faster than those applications. Really, if you make the claim that this application performs worse than comparable native applications, you'll either have to provide proof or I'm going to have to assume your perception is skewed by your expectations.
Other .NET applications I've used that perform well: RSSBandit, PowerShell and Expression Blend to name a few.
William E. Kempf
|
|
|
|
|
William E. Kempf wrote: But then, I think Java in general doesn't do well in this arena. To be fair though, it doesn't perform significantly worse than VisualStudio,
And VS is one of the rare MS desktop applications that use managed code
William E. Kempf wrote: Paint.NET, OTOH, is a very nice example.
Wow, you are the first person aside from the authors of Paint.NET that likes its performance. Although I hate to cite Slashdot in any seroius discussion, most people seem to have the same impression as I do[^].
modified on Monday, March 3, 2008 3:15 PM
|
|
|
|
|
Nemanja Trifunovic wrote: And VS is one of the rare MS desktop applications that use managed code
Very little.
Nemanja Trifunovic wrote: Wow, you are the first person aside from the authors of Paint.NET that like its performance.
And you're the first I've heard that didn't like the performance. Interestingly, in the Slashdot article you posted, I count more people saying the "fat brush" test is "silky smooth" than those claiming it performs badly. In my own testing, a brush width of 200 draws smoothly and doesn't touch the CPU, contrary to the few bad reports. Of course, this Slashdot post was from 2004, and there have been numerous updates to Paint.NET since then. When was the last time you looked at this application?
William E. Kempf
|
|
|
|
|
In my opinion, Paint.NET's page faults are far less when compared to other similar applications (same memory foot prints ).
In my machine, the number of PageFaults for PaintDotNet and Firefox, after running it for similar amount of time was very different. I tested it after running both applications for about 5 min. In firefox, I opened gmail, and many javascript intensive applications, and in paintdotnet I did a couple of renders (Pencil sketching a 8MP photo).
PaintDotNet's number of page faults was around 70,000 where as Firefox, it was 100,000 when it started ( I do have a lot of plugins) and after opening gmail and other such websites, it went up by a factor of 10! Though the memory occupied by Firefox and PaintDotNet were 80MB to 100 MB...
The point is, for the allocated 80 MB heap in PaintDotNet, due to GC, memory is freed resulting in lower page faults than firefox which also uses the same amount of memory.
Mugunth
Thanks & Regards,
M.Mugunth Kumar
M +65 82448625
W http://mugunth.kumar.googlepages.com
B http://tech-mugunthkumar.blogspot.com (Technology Blog) *NEW
Nanyang Technological University,
Wee Kim Wee School of Communication and Information,
31 Nanyang Link, Singapore - 637718.
|
|
|
|
|
Hello,
you comparing two absoluty different worlds which aren't comparable.
As you should know the virtual memory managment depends from many factors.
One point is the internal memory managment and an other the local available heap area (RAM).
All this points presents that this result isn't deterministic.
Ciao...
what*s up...
|
|
|
|
|
That paper is quite impressive, I already found links to it and have to read it. However, studies with opposite conclusions were done in the past - they did not benchmark applications without enough VM (and well, if you're swapping it's obvious that you're gonna be slow - reporting benchmark results is almost redundant on that, or might be useful to give more scary numbers ).
|
|
|
|
|
Thanks William for the answers and the link
|
|
|
|
|
Hey, nice to see you back at Code Project, Bill, although not sure why you are commenting this article which is very substandard and may be removed soon.
William E. Kempf wrote: The JIT (Just In Time) compilation doesn't happen entirely at start time. It literally happens "just in time". In addition, this can be done at installation time instead.
JIT happens whenever it decides it is a best time to happen, but in any case it is easy to observe and impacts performance. I have yet to try a .NET application that starts quickly - even a "hello world" takes a while.
William E. Kempf wrote: Finally, on this point, the IL is specifically designed to be fast to compile.
Which as you know is negatively impacting the optimization of the resulting code. In order to fully optimize the code, a compiler needs time, and JIT does not have time.
|
|
|
|
|