【问题标题】:Is there a more lightweight alternative to array?有没有比数组更轻量级的替代品?
【发布时间】:2015-09-22 04:58:39
【问题描述】:

我需要创建一个包含 30 亿个布尔变量的数组。我的内存只有 4GB,因此我需要这个数组非常紧凑(每个变量最多一个字节)。理论上这应该是可能的。但我发现 Ruby 为数组中的一个布尔变量使用了太多空间。

ObjectSpace.memsize_of(Array.new(100, false))   #=> 840

每个变量超过 8 个字节。我想知道 Ruby 中是否有更轻量级的 C 数组实现。

除了一个小的配置文件,我还需要这个数组的每个布尔值都可以快速访问,因为我需要根据需要尽可能快地翻转它们。

【问题讨论】:

  • 使用位图。有一个字符串,只需翻转它的单个位。没有数组开销,每个字节 8 个值。酷吧? :)
  • 你为什么不把你的位存储在整数中?
  • @cremno: NArray.byte 似乎不支持长度超过 2^31 的数组。
  • @trVoldemort,你为什么问小尺寸? Ruby 不像普通的 C 那样又快又小。Ruby 为糖果函数和 oop 付出了速度和大小。只是......如果你想要优化,请转到 C

标签: arrays ruby


【解决方案1】:

Ruby 不是一种性能良好的语言,尤其是在内存使用方面。正如其他人所说,你应该把你的布尔值放在数字中。由于 ruby​​ 的“物化”,你会失去很多记忆。如果这对您来说是一个糟糕的场景,您可以将其存储为大长度的字符串并将字符串存储在一个数组中,从而减少内存损失。

http://calleerlandsson.com/2014/02/06/rubys-bitwise-operators/

您还可以在 C++ 中实现自己的 gem,它可以自然地使用位和双精度,从而减少内存损失。双精度数组意味着每个位置有 64 个布尔值,对于您的应用程序来说绰绰有余。

非常大的对象总是一个问题,并且需要您实现很多才能更轻松地处理大型对象集合。当然,您至少必须实现某种方法来访问存储多个布尔值的对象数组中的某个位置,并翻转它们。

【讨论】:

    【解决方案2】:

    以下课程可能不是您正在寻找的。它将使用位和移位将 1 或 0 存储到数组中。条目默认为 0。如果您需要为每个条目提供三种状态,0、1 或 nil,那么您需要将其更改为每个条目使用两位,而不是一位。

    class BitArray < Array
      BITS_PER_WORD = 0.size * 8
      MASK = eval("0x#{'FF' * (BITS_PER_WORD/8)}") - 1
    
      def []=(n, value_0_or_1)
        word = word_at(n / BITS_PER_WORD) || 0
        word &= MASK << n % BITS_PER_WORD
        super(n / BITS_PER_WORD, value_0_or_1 << (n % BITS_PER_WORD) | word)
      end
      def [](n)
        return 0 if word_at(n / BITS_PER_WORD).nil?
        (super(n / BITS_PER_WORD) >> (n % BITS_PER_WORD)) & 1
      end
    
      def word_at(n)
        Array.instance_method('[]').bind(self).call(n)
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      • 2014-04-23
      • 2011-01-31
      • 1970-01-01
      • 2011-07-18
      • 2013-08-01
      相关资源
      最近更新 更多