一个类在Ruby中可以拥有的实例数量是否有限制?

时间:2014-11-13 11:31:43

标签: ruby

在Ruby中,我正在解析CSV文件并将值存储到类中(csv中的每个“列”对应于我的类的属性,Expense)。我的CSV有15.000行。但是在我浏览完所有行之后,我只有260个Expense类对象,而不是15.000,这是行数。如果我解析一个包含100行的CSV,它可以正常工作,它会创建100个Expense类对象。但是从150行开始创建问题 - 150行返回36个类Expense的实例,15.000返回260.我没有看到逻辑,就像在某些时候它重置了我的类的实例数并重新开始计数。

一个类在Ruby中可以拥有的实例数量是否有限制?

这不是一个程序,我是一个真正的打手。我只是通过CSV,对数据进行一些验证,然后返回到CSV。所以我一直在寻找一种方法,我不需要将值存储在临时文件中。

由于

代码:

class Expense
    attr_accessor :var1, :var2, :var3
    def initialize(var1,var2,var3)
        @var1 = var1
        @var2 = var2
        @var3 = var3
    end
    def self.count
        ObjectSpace.each_object(self).to_a.count
    end
end

old_file = File.read("C:/Folder/OldFile.csv")
new_file = File.new("C:/Folder/NewFile.csv", "w")
puts "Number of rows in input file: #{old_file.count("\n")}"
puts "Number of Expense objects stored before procedure: #{Expense.count}"

#loop through the rows and store each column as an attribute of the class
old_file.each_line do |line|
    #save each column of the row as an element of the array
    attr_ay = []
    line.chomp.each_line(';') do |att| 
        attr_ay.push(att.chomp(";"))
    end
    #loops through each attribute and assigns the corresponding value of the array
    i=0
    expense = Expense.new("","","")
    expense.instance_variables.each do |att|
        expense.instance_variable_set(att,attr_ay[i])
        new_file.print(expense.instance_variable_get(att)+";")
        i = i + 1
    end
    #jump to the next line in new file 
    new_file.print "\n"
end
new_file.close

#compare number of rows
new_file = File.read("C:/Folder/NewFile.csv")
puts "Number of rows in output file: #{new_file.count("\n")}"
puts "Number of Expense objects stored after procedure: #{Expense.count}"

#Result:
#Number of rows in input file: 15031
#Number of Expense objects stored before procedure: 0
#Number of rows in output file: 15031
#Number of Expense objects stored after procedure: 57

1 个答案:

答案 0 :(得分:2)

这个答案基于我和Max的评论似乎解决了这个问题。

  1. 问题中的代码不受对象数量限制的影响。 Ruby语言没有固有的限制,大多数实现允许大量的对象,超过数TB的内存。脚本通常在用完对象指针之前耗尽内存或CPU时间。

  2. 使用ObjectSpace访问对象是导致问题的原因:

    1. ObjectSpace是一个有用的调试工具或元编程工具,您可以使用它找到当前对象,但它不维护任何活动引用。
    2. Ruby将清除未引用的对象,这称为垃圾收集。它通过检查所有活动绑定并跟随它们的对象引用(以及它们的所有子引用等)来完成此操作。任何未标记为"在使用中的东西"在该标记阶段可以在稍后的扫描阶段中移除。
    3. 垃圾收集与您的代码同时运行,并且只有在脚本消耗了至少一些内存后才会启动。这解释了当您尝试不同测试时数字的令人费解的变化。
  3. 修复方法是使用容器来保存对象。只需push - 将它们打开到Array即可创建必要的引用,并阻止垃圾回收对您来说是一个问题。您应该使用该变量来查找和计算对象,而不是ObjectSpace