c# - 提高速度的不安全 C# 技巧

标签 c# unsafe

我不习惯使用指针(例如 C++)或不安全的孤岛进行编码:仅使用“安全”C#。 现在我想在 C# 中为 .Net Micro Framework 实现一个函数,其中紧凑性和性能非常重要。 基本上,我会收集 4 条短裤,从而填充缓冲区(例如字节数组)。 假设每个样本都是这样的:

struct MyStruct
{
    public short An1;
    public short An2;
    public short An3;
    public short An4;
}

每个样本都是通过计时器事件收集的,因此我无法循环(有几个原因)。 我尝试了很多方法来有效地做到这一点,但表现最好的似乎是这个:

unsafe struct MyStruct2
{
    public fixed byte Buffer[Program.BufferSize];
}


unsafe class Program
{
    public const int BufferSize = 0x1000;
    public const int ArraySize = BufferSize / 8;

    static MyStruct2 _struct2 = new MyStruct2();
    static MyStruct* _structPtr;


    unsafe static void Main(string[] args)
    {
        int iter = 5000;  //just for simulate many cycles

        for (int i = 0; i < iter; i++)
        {
            //let's make a trick!
            fixed (byte* ptr = _struct2.Buffer)
                _structPtr = (MyStruct*)ptr;

            _structIndex = 0;
            do
            {
                Test5();
            } while (++_structIndex < ArraySize);
        }


        Console.ReadKey();
    }


    unsafe static void Test5()
    {
        _structPtr->An1 = (short)An1();
        _structPtr->An2 = (short)An2();
        _structPtr->An3 = (short)An3();
        _structPtr->An4 = (short)An4();
        _structPtr++;
    }


    //simulations of ADC reading
    static int An1()
    {
        return 0x1111;
    }

    static int An2()
    {
        return 0x2222;
    }

    static int An3()
    {
        return 0x3333;
    }

    static int An4()
    {
        return 0x4444;
    }
}

相对于以下这种更安全的方式的改进 - 例如 - 不是那么高(177 毫秒对 224 毫秒),但无论如何它都很重要。

    static MyStruct Test3()
    {
        var data = new MyStruct();
        data.An1 = (short)An1();
        data.An2 = (short)An2();
        data.An3 = (short)An3();
        data.An4 = (short)An4();
        return data;
    }

注意:我删减了一些代码,但我觉得已经够清楚了。

我的问题是:我通过将“固定”指针复制到另一个未固定指针而做出的“技巧”是否可靠?...但是您可以假设所有数据都是静态分配的,因此应该固定。 先感谢您。 干杯

最佳答案

我认为代码不安全。在固定范围内的 _structPtr = (MyStruct*)ptr 之后,假设 _struct2 不会移动,您可以继续将数据放入 _structPtr 中。虽然您认为它不会被 GC 是正确的,但这并不意味着 GC 不会在内存压缩期间移动它。 .NET Compact Framework 仍在进行垃圾收集,我认为它会压缩内存而不是让内存碎片化。

例如,如果在 _struct2 之前在堆上分配的临时(非静态)对象被 GC 删除,则该结构使用的内存可能会转移到该临时对象使用的可用空间中。此时 _structPtr 指向未使用的内存。

修改 Test3() 以获取 ref MyStruct 数据 会有帮助吗?

此外,检查 [StructLayout(LayoutKind.Explicit)][FieldOffset(...)] 这将允许您拥有一个具有多种方式的结构访问其中的相同数据。在您的情况下,可以是 4 个字节或 1 个 int 或(可能)1 个 4 字节数组。

关于c# - 提高速度的不安全 C# 技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5302153/

相关文章:

rust - std::ptr::write 是否传输它写入的字节的 "uninitialized-ness"?

rust - 在范围内拥有不正确(大于正确)生命周期的引用是否可以?

c# - 无法在对象中插入重复的键 - 如何在 Entity Framework Core 中创建复合键

c# - TFS 更改构建代理工作目录

c# - 在 C# 中的两个独立 Windows 应用程序之间共享数据

java - 将对象移出堆

arrays - 暂时将[u8]转换为[u16]

c# - Winforms 托管 Javascript 内容

c# - 为什么有时在计时器滴答事件中它会连续调用该方法两次?

java - 有没有办法获得引用地址?