【问题标题】:When is it necessary to declare volatile VALUEs in Ruby C extensions?什么时候需要在 Ruby C 扩展中声明 volatile VALUE?
【发布时间】:2013-10-03 21:38:38
【问题描述】:

我找不到太多文档说明何时适合在 Ruby 扩展中将 VALUE 声明为 volatile 以避免过早地对使用中的对象进行垃圾回收。

这是我到目前为止所学到的。有谁可以填空吗?

volatile不需要时需要使用:

  • 在 C++ 对象成员中(因为它们从不在堆栈上?
  • 在不调用 Ruby API 的 C/C++ 方法中(因为在调用 Ruby API 之前 GC 不会打开

volatile确实需要使用时

  • 在调用任何 Ruby ALLOCmalloc 宏/函数的 C/C++ 方法中(因为这些会在内存高度碎片化时触发 GC
  • 在调用任何 Ruby 函数的 C/C++ 方法中(例如,rb_funcallrb_ary_new 等)

其他避免GC的方法

  • 标记正在使用的VALUEs
  • 在对象创建期间禁用 GC,然后重新启用它
  • 不要使用 Ruby 的分配方式(有风险)

一切都正确吗?我缺少什么细节?除了标记,volatile是唯一的方法吗?

【问题讨论】:

    标签: c++ c ruby garbage-collection mark-and-sweep


    【解决方案1】:

    我会说经验法则是,如果您的变量值可以在运行时随时更改并且您不知道何时更改,请使用 volatile 关键字。这包括中断。例如,您有中断回调函数来计算用户在键盘上按下某物的次数。您的程序不知道用户何时按下键盘上的按钮,因此您的计数器变量必须使用 volatile 关键字声明。

    如前所述,它禁用了对变量的一些编译器优化。例如:

    int a = 5;
    while(a == 5){
      //do something
    }
    

    编译器将while(a == 5) 语句优化为while(true),因为它发现变量a 在运行时无法更改,并且在每个循环中检查a 的值是没有用的。所以你最终陷入了无限循环。但是如果你添加关键字volatile:

    volatile int a = 5;
    while(a == 5){
      //do something
    }
    

    您只需告诉编译器保持变量不变。不要对其进行任何优化,一些中断可能会改变它的值。在这方面它工作得很好。

    【讨论】:

      【解决方案2】:

      将变量标记为 volatile 会阻止 C/C++ 编译器应用某些优化,这是基于变量不能“自行”更改值的假设。 Wikipedia: Volatile variable

      我认为它应该在VALUE 与 C 扩展之外的 Ruby 代码共享或可由 Ruby 代码更改时使用,以使编译器了解这一事实。看看this example

      【讨论】:

      • 这是误导。 volatile 在 C 和 C++ 中做不同的事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-01
      • 1970-01-01
      • 2012-09-16
      • 2012-12-05
      • 2015-10-10
      相关资源
      最近更新 更多