gpt4 book ai didi

ruby-on-rails - 在 Ruby 中深度复制对象的最有效方法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 06:45:34 26 4
gpt4 key购买 nike

我知道序列化对象是(据我所知)有效深度复制对象的唯一方法(只要它不像 IO 之类的那样是有状态的),但它是一个比其他方式特别有效?

例如,由于我使用的是 Rails,所以我总是可以使用 ActiveSupport::JSONto_xml - 据我所知,编码对象是其中之一最被接受的方法来做到这一点。我希望编码可能是其中最有效的,因为它是 Ruby 内部的,但我是否遗漏了什么?

编辑:请注意,它的实现是我已经涵盖的内容 - 我不想替换现有的浅拷贝方法(如 dupclone),所以我最终可能会添加 Object::deep_copy,其结果是上述方法中的任何一个(或您的任何建议 :) 开销最少。

最佳答案

我也在想同样的事情,所以我将几种不同的技术相互进行了基准测试。我主要关注数组和散列——我没有测试任何复杂的对象。也许不足为奇,自定义深度克隆实现被证明是最快的。如果您正在寻找快速简便的实现方式,Marshal 似乎是您的不二之选。

我还使用 Rails 3.0.7 对 XML 解决方案进行了基准测试,下面未显示。它慢得多,只有 1000 次迭代大约 10 秒(下面的解决方案都运行了 10,000 次基准测试)。

关于我的 JSON 解决方案的两个注释。首先,我使用了 C 变体,版本 1.4.3。其次,它实际上并不是 100% 有效,因为符号将被转换为字符串。

这一切都是用 ruby​​ 1.9.2p180 运行的。

#!/usr/bin/env ruby
require 'benchmark'
require 'yaml'
require 'json/ext'
require 'msgpack'

def dc1(value)
Marshal.load(Marshal.dump(value))
end

def dc2(value)
YAML.load(YAML.dump(value))
end

def dc3(value)
JSON.load(JSON.dump(value))
end

def dc4(value)
if value.is_a?(Hash)
result = value.clone
value.each{|k, v| result[k] = dc4(v)}
result
elsif value.is_a?(Array)
result = value.clone
result.clear
value.each{|v| result << dc4(v)}
result
else
value
end
end

def dc5(value)
MessagePack.unpack(value.to_msgpack)
end

value = {'a' => {:x => [1, [nil, 'b'], {'a' => 1}]}, 'b' => ['z']}

Benchmark.bm do |x|
iterations = 10000
x.report {iterations.times {dc1(value)}}
x.report {iterations.times {dc2(value)}}
x.report {iterations.times {dc3(value)}}
x.report {iterations.times {dc4(value)}}
x.report {iterations.times {dc5(value)}}
end

结果:

user       system     total       real
0.230000 0.000000 0.230000 ( 0.239257) (Marshal)
3.240000 0.030000 3.270000 ( 3.262255) (YAML)
0.590000 0.010000 0.600000 ( 0.601693) (JSON)
0.060000 0.000000 0.060000 ( 0.067661) (Custom)
0.090000 0.010000 0.100000 ( 0.097705) (MessagePack)

关于ruby-on-rails - 在 Ruby 中深度复制对象的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5643432/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com