如何使用C#直接访问数组中的对象(不使用不安全)?

时间:2017-04-18 20:31:11

标签: c# pointers

我一直在做一些翻找,试图决定是否使用Java或C#作为网络。

我从大约一年前跑过这个帖子: Java vs .NET performance

基本上可以从中收集的是java运行得更快,因为它直接访问内存中的值,而C#使用get和set作为指针。

话虽如此,我可以直接使用C#访问这些值,以获得这些性能优势而不会运行不安全吗?

3 个答案:

答案 0 :(得分:4)

基准显示的所有内容都是multi-dimensional arrays are slow in .NET;使用Java版本中的锯齿状数组(即在C#和Java中执行相同的操作)使C#程序达到相同的性能水平。

这与“直接访问内存”与“使用get和set是指针”无关,无论这是什么意思(我真的不知道)。

答案 1 :(得分:0)

在C#中使用unsafe数组可以直接指向元素(如果它们是内在类型)。这应该提供性能优势,因为没有对每个访问进行范围检查。我知道你说没有不安全的代码,但如果你想要性能,你必须考虑这个选项。

考虑以下示例:

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);
    }
}

通过我的测试,我发现使用指针(pointer[i])进行数学运算的速度提高了20%,而不是数组访问(value[i])。

PS。此声明来自Microsoft。在他们的parallel toolkit examples中有一个名为Strassens的项目,它对矩阵乘法进行基准测试,并使用上述方案进行快速数学运算。

答案 2 :(得分:0)

请完成您的语言研究。目前,如果您知道如何,C / C ++被认为是可以生成最有效和最快的代码的语言。而C / C ++在很大程度上依赖于指针,这就是这些语言获得大部分速度和效率的方式。

请尝试了解.NET / C#中的索引器和指针之间的区别。 C / C ++意义上的指针只是内存中的一些地址,指针的数据类型表示当递增/递减时,它在内存中项目大小的大小。不能更快。

C#中的索引器是更复杂的野兽。

你所链接的问题也很难衡量实际速度。 它从程序的开始测量,而不是在程序启动后等待灰尘沉淀。好吧,JIT在这段时间内仍然可以处于活动状态,这个过程的线程刚刚构建完毕等等。它更像是运行时环境的测量,它能够快速启动一些进程。

C#数组中的

可以非常快速的方式固定和访问,暂时不受垃圾收集的影响。

请不要尝试根据这些不良信息来源选择语言。目前,C#和Java相差甚远......

在一个好的设计中,您可以设法将数据存储在一维数组中......