-5

I've been doing some rummaging, trying to decide whether or not to use Java or C# for a network.

I ran across this thread from about a year ago: Java vs .NET performance

Basically what can be gathered from this is that java is running much faster because it's directly accessing the values from memory and C# is using get and set which are pointers.

That being said, can I directly access these values with C# is to gain those performance benefits without running unsafe?

Community
  • 1
  • 1
En'gai
  • 1
  • 5
  • 8
    what ur asking makes no sense – Christo S. Christov Apr 18 '17 at 20:36
  • @Hristo What doesn't make sense about it? Accessing code directly is considered 'unsafe', but is faster. I'm was curious if it were other possible to obtain these gains. – En'gai Apr 18 '17 at 20:45
  • Your suggestions are simply wrong. There are no pointers in C#. Getters and Setters about Encapsulating, not about performance (and absolutely are not unsafe) – Ole Albers Apr 19 '17 at 07:03
  • BTW. Java has its benefit, but you do not find a lot of Memes about Java being so FAST... http://s2.quickmeme.com/img/58/58da71aa70835d82f576f40acdb3d692931364748ab47f405dfc0c9782795d90.jpg – Ole Albers Apr 19 '17 at 07:07

3 Answers3

4

All that the benchmark shows is that multi-dimensional arrays are slow in .NET; using jagged arrays as in the Java version (i.e. doing the same thing in C# and Java) brought the C# program to the same level of performance.

This has nothing to do with "directly accesing memory" vs "using get and set which are pointers", whatever that is supposed to mean (I honestly have no idea).

Asik
  • 21,506
  • 6
  • 72
  • 131
  • 1
    I might add that packing a 2D array into a 1D array might be faster/easier for some operations. It depends on the application if jagged arrays or packed arrays are best, Definitely _do not use_ multidimensional arrays. – John Alexiou Apr 18 '17 at 20:43
  • You need to do proper benchmarking to get meaningful results, but the test isn't fair anyway. In the java version you're doing array[i][j] *= a.getArray()[i][j]; which only accesses the array once if I understand compound assignment correctly. In the C# version you're using indexers, so you're not accessing the array directly but via the get and set methods. – Paul Boddington Apr 29 '15 at 4:15 – En'gai Apr 18 '17 at 20:52
  • Honestly, I think I might trust Paul on this one. :) – En'gai Apr 18 '17 at 20:53
  • Indexers in C# are method calls, but in the case of arrays they compile down to a pointer arithmetic + dereference exactly as in Java or C (+ optionally a bounds-check, as in Java). You could just use the debugger and check the assembly code in a release build and see for yourself. I don't know where the comment you quote comes from, but it seems to be from someone who doesn't understand either Java or C# very well. – Asik Apr 19 '17 at 15:28
1

Using an unsafe array in C# allows you to get direct pointers to the elements (if they are of intrinsic types). This should provide a performance benefit because there are no range checks to be done of each access. I know you said no unsafe code, but if you want performance you have to consider this option.

Consider the example below:

public unsafe class PinnedArray : IDisposable
{
    byte[] values;
    byte* pointer;
    GCHandle handle;

    public PinnedArray(int size)
    {
        values=new byte[size];
        handle=GCHandle.Alloc(values, GCHandleType.Pinned);
        pointer=(byte*)handle.AddrOfPinnedObject().ToPointer();
    }
    ~PinnedArray()
    {
        Dispose();
    }

    public void Dispose()
    {
        if(values!=null)
        {
            handle.Free();
            values=null;
        }
    }
    // This is fast because it uses pointers
    public void AddFrom(PinnedArray other)
    {
        if(values.Length!=other.values.Length)
        {
            throw new ArgumentException("other");
        }
        for(int i = 0; i<values.Length; i++)
        {
            pointer[i]+=other.pointer[i];
        }
    }        

    public void FillRandom()
    {
        Random rand = new Random();
        for(int i = 0; i<values.Length; i++)
        {
            values[i]=(byte)(rand.Next()%256);
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        var A = new PinnedArray(100);
        var B = new PinnedArray(100);

        B.FillRandom();
        A.AddFrom(B);
    }
}

With my testing I see a 20% speedup in doing math using pointers (pointer[i]) as opposed to array access (value[i]).

PS. This declaration comes from Microsoft. In their parallel toolkit examples there is a project named Strassens which benchmarks matrix multiplication and uses the above scheme for quick math.

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
  • That's brilliant my friend. Thank you sire. First time today I got an answer worth the asking. ;) – En'gai Apr 18 '17 at 21:11
  • So essentially the answer is no, it's not possible to gain that performance without using unsafe methods, yes? – En'gai Apr 18 '17 at 21:14
  • Can you parallelize the code with `Parallel.For()` construct? You can see 6× speedups with parallel processing. Another trick is loop unrolling which give you about a 10% bump. – John Alexiou Apr 18 '17 at 21:15
  • array[x] *is* just a pointer dereference whether you do it in unsafe or safe code. The difference as you mention is you may avoid bounds check (which the CLR does elide in safe code in some cases), but it has nothing to do with the question's premise, which is nonsense. As such the answer is misleading (as it suggests the question makes sense and the answer is "use unsafe code"). – Asik Apr 19 '17 at 15:36
  • @Asik. I agree. I answered as if the question was "How do I write fast array math in C#?" The _OP_ seems to like my answer. – John Alexiou Apr 19 '17 at 15:44
  • @ja72 he also seems confused by it, as his comments show. You comfort him in his theory that C# arrays are slower because they "use get and set which are pointers", whatever that means, and that by using unsafe code you're getting rid of that cost. That is not the case. The perf difference in the linked benchmark was entirely down to multi-dimentional arrays vs single-dimensional arrays, not Java vs C# or safe code vs unsafe code. – Asik Apr 19 '17 at 15:47
  • @Asik No one said C# arrays were slower, and I would certainly not be comforted by it. The one time I had to use java I wanted to cry ;) – En'gai Apr 22 '17 at 19:45
  • @ja72 I really do appreciate you taking the time to answer this. Most people saw Java vs. C# and went berserk it seems. I don't need comforting, I need knowledge. <3 – En'gai Apr 22 '17 at 19:47
0

Please work on your language research. Currently, the C/C++ is considered the language that can produce the most efficient and fastest code, if you know how. And C/C++ is heavily dependent on pointers, that is how these languages gain most of the speed and efficiency.

Please try to understand difference between indexers in .NET/C# and pointers. Pointers in C/C++ sense is just some address in memory and data type of the pointer says how big steps it does when incremented/decremented, the size of the item in the memory. Can not be anything faster.

Indexers are much more complex beasts in C#.

Also the question you have linked made a poor attempt at measuring the real speed. It measured from the start of the program without waiting for the dust to settle after the program starts up. Well, JIT can be still active during that time, thread for the process was just barely constructed etc. It was more like measurement of the runtime environment, its ability to fire up fast some process.

in C# array can be pinned and accessed in the very fast way, not subject of the garbage collection for a moment.

Please do not try to choose a language based on such poor source of the informations. Currently, C# and Java are less or more comparable...

In a good design, you can manage to store data in one-dimensional array...

ipavlu
  • 1,617
  • 14
  • 24
  • If you want the fastest possible performance, then your choice is `Fortran`. In comparing with `C` type languages the speedup starts from 4× with small arrays and goes up to 50× or 100× compared to naive code for large arrays. Worst case scenario `Fortran` is 4× of `C`. – John Alexiou Apr 18 '17 at 21:12