v00d00
v00d00

Reputation: 3265

C# Memory optimization for large arrays

Here are two code parts in c++ and c# doing absolutely the same thing:

C++
http://ideone.com/UfL5R

#include <stdio.h>
int main(int argc, char *argv[]) {
  char p[1000000];
  unsigned int i,j;
  unsigned long long s=0;
  for(i=2;i<1000000;i++) p[i]=1;
  for(i=2;i<500000;) {
    for(j=2*i;j<1000000;j+=i) p[j]=0;
    for(i++;!p[i];i++);
  }
  for(i=3,s=2;i<1000000;i+=2) if(p[i]) s+=i;
  printf ("%lld\n",s);
  return 0;
}

time: 0.01s memmory: 2576 kB

C#
http://ideone.com/baXYm

using System;

namespace ConsoleApplication4
{
    internal class Program
    {
        private  static void Main(string[] args)
        {
            var p = new byte[1000000];
            ulong i, j;
            double s = 0;
            for(i=2;i<1000000;i++) 
                p[i]=1;

            for(i=2;i<500000;) 
            {
                for(j=2*i;j<1000000;j+=i) 
                    p[j]=0;
                for(i++;p[i]==0;i++);
            }

            for(i=3,s=2;i<1000000;i+=2) 
                if(p[i]!=0) s+=i;

            Console.WriteLine(s);
        }
    }
}

time: 0.05s mem: 38288 kB

How can I improve the C# code to prove that C# can be as fast as C++ to my colleague?

As you can see the C# execution time is 5 time larger, and the memory consumption is 15 times larger.

Upvotes: 5

Views: 4466

Answers (5)

Haymo Kutschbach
Haymo Kutschbach

Reputation: 3362

Just a note to your timing. Its not shown, how did you measure the execution times. One can expect a reasonable overhead for .NET applications on startup. So if you are about the execution time of the loops only, you should run the inner loops several (many) times, skip the 1..2 first iterations, measure the other iterations and compute the average.

I would expect the results be more similar than. However, as always when targeting 'peak performance' - precautions regarding the memory management are important. Here, it probably would be sufficient to prevent from 'new' inside the measurement functions. Reuse the p[] in each iteration.

Upvotes: 3

Timothy Khouri
Timothy Khouri

Reputation: 31845

How to GREATLY Increase the Performance of your C# Code

Go "unsafe" (unmanaged) for that... every time you're doing someSortOfArray[i], the .NET framework is doing all kinds of neat-o things (such as out of bounds checking) which take up time.

That's really the whole point of going unmanaged (and then using pointers and doing myPointer++).

Just to clarify, if you go unmanaged and then still do a for-loop and do someArray[i], you've saved nothing.

Another S.O. question that may help you: True Unsafe Code Performance

Disclaimer

By the way, I'm not saying to do this all the time, but rather as an answer for THIS specific question only.

Upvotes: 6

Stack Overflow is garbage
Stack Overflow is garbage

Reputation: 247979

How can I improve the C# code to prove that C# can be as fast as C++ to my colleague?

You can't. There are legitimate areas where C++ is fundamentally faster than C#. But there are also areas where C# code will perform better than the equivalent C++ code. They're different languages with different strengths and weaknesses.

But as a programmer, you really ought to base your decisions in logic.

Logic dictates that you should gather information first, and then decide based on that.

You, on the contrary, made the decision first, and then looked for information to support it. That may work if you're a politician, but it's not a good way to write software.

Don't go hunting for proof that C# is faster than C++. Instead, examine which option is faster in your case.

In any case, if you want to prove that X can be as fast as Y, you have to do it the usual way: make X as fast as Y. And as always, when doing performance tuning, a profiler is your best friend. Find out exactly where the additional time is being spent, and then figure out how to eliminate it.

Memory usage is a lost cause though. .NET simply uses more memory, for several reasons:

  • it has a bigger runtime library which must be present in the process' address space
  • .NET objects have additional members not present in C++ classes, so they use more memory
  • the garbage collector means that you'll generally have some amount of "no-longer-used-but-not-yet-reclaimed" memory lying around. In C++, memory is typically released immediately. In .NET it isn't. .NET is based on the assumption that memory is cheap (which is typically true)

Upvotes: 6

Brendan Long
Brendan Long

Reputation: 54242

The memory usage may be related to garbage collection. In Java, memory usage is intentionally high -- garbage collection only happens when you need more memory. This is for speed reasons, so it would make sense that C# does the same thing. You shouldn't do this in release code, but to show much memory you're actually using, you can call GC.Collect() before measuring memory usage. Do you really care how much memory it's using though? It seems like speed in more important. And if you have memory limits, you can probably set the amount of memory that your program will use before garbage collecting.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038820

Compile and run in Release mode. I get exactly 0.01s from the C# version when built and run in Release mode. As far as memory consumption is concerned you are comparing apples to oranges. A managed environment will consume more memory as it is hosting the CLR and the Garbage Collector which don't come without cost.

Upvotes: 10

Related Questions