代码之家  ›  专栏  ›  技术社区  ›  Eloff

在非托管结构上使用fixed语句的开销是多少?

  •  0
  • Eloff  · 技术社区  · 14 年前

    特别是,我在考虑这样一个场景:

        unsafe struct Foo
        {
            public int Bar;
    
            public Foo* GetMyAddr()
            {
                fixed (Foo* addr = &this)
                    return addr;
            }
        }
    

    假设一个foo存储在非托管内存中,我将尝试找出在getmyaddr中评估fixed语句所涉及的内容。作为程序员,我知道这个结构永远不在托管堆上,我只需要以最有效的方式在非托管内存中获取它的地址。我特别担心这里是否使用了任何锁定或原子操作,因为这将使它完全不适合。

    4 回复  |  直到 14 年前
        1
  •  7
  •   JaredReisinger    14 年前

    这不会像你想象的那样。“fixed”语句只固定托管对象(this) 在“固定”语句本身的持续时间内 一旦你“回来”就结束了。见 MSDN docs 有关详细信息。

    您已经说过您的“foo”在非托管内存中,这意味着托管GC不会在您身上移动它。在这种情况下,您不能直接返回“&this”吗?或者,您可以考虑将非托管对象放入托管对象中。在你所做的事情上多给点背景,我们都能给出更具体的建议。

        2
  •  2
  •   Hans Passant    14 年前

    当结构存在于非托管内存中时,表达式&this没有意义。没有办法在那里分配它。托管结构的一个关键属性是它们的内存布局是 可发现且 与该结构的非托管视图兼容。在对齐成员的同时,clr会根据需要重新排列字段,以获得最小的大小。事实上,如果后面的字段可以容纳在填充中,它将交换字段。

    无法通过Marshal.ptrtoStructure将非托管结构转换为其托管版本。marshal.sizeof仅对非托管布局准确。

        3
  •  0
  •   Eloff    14 年前

    我建立了一个微基准测试,并测量了在非托管内存中的结构上使用fixed时的开销,它非常低,返回fixed(this)的开销仅是简单返回fixed的10倍。这对于我的用例来说是可以接受的(使用结构的地址散列),我无法了解它是如何实现的,但在本例中它似乎足够快。

        4
  •  -1
  •   Johannes Rudolph    14 年前

    基本上没有开销。固定意味着“固定指针在内存中指向的位置,不要重新定位它。”如果垃圾收集器决定移动内存,其他所有托管指针都可以随意“弯曲”。固定将防止这一点,所以基本上它将“节省”这(可能的)开销。

    我不知道固定指针的实现,但在最简单的情况下,它只是黑名单内存块。与正常的托管指针相比,这不是很昂贵。

    另一方面,它阻止了GC可能决定在内存管理方面执行的各种优化,例如增加本地化、减少碎片等。