gpt4 book ai didi

ruby-on-rails - 为什么 ActiveSupport::JSON.encode 这么慢?

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

JRuby 9.2、Rails 4.2

我一直致力于读取/转储大型 JSON 对象、100+MB 的文件,这些文件通常会挂起几分钟,然后在写出时耗尽内存。

我注意到它特别发生在使用 to_json 时。下面是一个 4MB 的文件,所以它实际上是完整的:

pry(main)> f = File.open('nvdcve-1.0-recent.json'){|f| JSON.load(f) }
pry(main)> puts Benchmark.measure{ JSON.dump(f) }
0.230000 0.010000 0.240000 ( 0.081894)
=> nil
pry(main)> puts Benchmark.measure{ f.to_json }
1.020000 0.020000 1.040000 ( 0.820851)
=> nil

问题的根源是 ActiveSupport 在一堆事情上覆盖了 to_json:

pry(main)> f.method(:to_json)
=> #<Method: Hash#to_json(to_json_with_active_support_encoder)>
pry(main)> puts Benchmark.measure{ f.to_json_without_active_support_encoder }
0.040000 0.000000 0.040000 ( 0.035408)
pry(main)> puts Benchmark.measure{ f.to_json_with_active_support_encoder }
1.170000 0.010000 1.180000 ( 0.812674)

参见此处:https://apidock.com/rails/Object/to_json_with_active_support_encoder

那么 ActiveSupport::JSON.encode 与 JSON gem 的 to_json 到底有什么不同,导致它慢得多,即使是在一个不起眼的 JSON 文件上也是如此是从 JSON 文件加载的吗?

如果我覆盖 to_json 不使用 ActiveSupport 变体,我会破坏任何 Rails 功能吗?

最佳答案

根据to the source ActiveSupport::JSON 几乎只是 JSON gem 之上的附加层——它实际上完成了大部分繁重的工作。它主要做的是:

转义一些在某些浏览器中可能会出现问题的额外字符。

ESCAPED_CHARS = {
"\u2028" => '\u2028',
"\u2029" => '\u2029',
">" => '\u003e',
"<" => '\u003c',
"&" => '\u0026',
}

评论没有说明有问题的浏览器是哪些,这对于现代浏览器来说可能完全不是问题。

将对象转换为合适的 JSON 表示形式:

      # Convert an object into a "JSON-ready" representation composed of
# primitives like Hash, Array, String, Numeric,
# and +true+/+false+/+nil+.
# Recursively calls #as_json to the object to recursively build a
# fully JSON-ready object.
#
# This allows developers to implement #as_json without having to
# worry about what base types of objects they are allowed to return
# or having to remember to call #as_json recursively.
#
# Note: the +options+ hash passed to +object.to_json+ is only passed
# to +object.as_json+, not any of this method's recursive +#as_json+
# calls.
def jsonify(value)
case value
when String
EscapedString.new(value)
when Numeric, NilClass, TrueClass, FalseClass
value.as_json
when Hash
Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
when Array
value.map { |v| jsonify(v) }
else
jsonify value.as_json
end
end

这可能是最重要的部分,因为 #as_json 是模型如何将自身呈现为 JSON 的关键。它还处理转换日期和时间戳以及其他非基元(ActiveSupport 为这些提供了 #as_json 方法)。删除它很可能会破坏很多东西。

根据您的用例,您也许可以从您的模型对象手动创建 ruby​​ 对象(数组、哈希等)并使用 JSON.generate(data) - 我不确定它会表现得更好虽然。

关于ruby-on-rails - 为什么 ActiveSupport::JSON.encode 这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57334126/

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