Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
API响应数据集上的Ruby分页导致内存峰值_Ruby_Out Of Memory - Fatal编程技术网

API响应数据集上的Ruby分页导致内存峰值

API响应数据集上的Ruby分页导致内存峰值,ruby,out-of-memory,Ruby,Out Of Memory,当我通过API返回的数据集进行分页时,我遇到了一个大内存峰值问题。API返回了约150k条记录,我一次请求10k条记录,并对15页数据进行分页。数据是一个哈希数组,每个哈希包含25个键和大约50个字符串值。这个过程杀死了我的512mb Heroku dyno 我有一个用于分页API响应数据集的方法 def all_pages value_key = 'values', &block response = {} values = [] current_page = 1 to

当我通过API返回的数据集进行分页时,我遇到了一个大内存峰值问题。API返回了约150k条记录,我一次请求10k条记录,并对15页数据进行分页。数据是一个哈希数组,每个哈希包含25个键和大约50个字符串值。这个过程杀死了我的512mb Heroku dyno

我有一个用于分页API响应数据集的方法

def all_pages value_key = 'values', &block
  response = {}
  values = []
  current_page = 1
  total_pages = 1
  offset = 0

  begin
    response = yield offset

    #The following seems to be the culprit
    values += response[value_key] if response.key? value_key

    offset = response['offset']
    total_pages = (response['totalResults'].to_f / response['limit'].to_f).ceil if response.key? 'totalResults'
  end while (current_page += 1) <= total_pages

  values
end
我知道是阵列的串联导致了问题,因为删除该行允许进程在没有内存问题的情况下运行。我做错了什么?整个数据集可能不超过20mb—这是如何消耗所有dyno内存的?我能做些什么来提高这里的效率

更新

响应如下所示:
{“totalResults”:208904,“offset”:0,“count”:1,“hasMore”:true,limit:“10000”,“items”:[…])

更新2

使用
报告运行
显示以下内容:

[HTTParty] [2014-08-13 13:11:22 -0700] 200 "GET 29259/data" -
Memory 171072KB
[HTTParty] [2014-08-13 13:11:26 -0700] 200 "GET 29259/data" -
Memory 211960KB
  ... removed for brevity ...
[HTTParty] [2014-08-13 13:12:28 -0700] 200 "GET 29259/data" -
Memory 875760KB
[HTTParty] [2014-08-13 13:12:33 -0700] 200 "GET 29259/data" -
Errno::ENOMEM: Cannot allocate memory - ps ax -o pid,rss | grep -E "^[[:space:]]*23137"
更新3

我可以用下面的基本脚本重新创建问题。该脚本是硬编码的,只能提取100k条记录,并且在我的本地VM上已经消耗了超过512MB的内存

#! /usr/bin/ruby
require 'uri'
require 'net/http'
require 'json'

uri = URI.parse("https://someapi.com/data")
offset = 0
values = []

begin
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.set_debug_output($stdout)

  request = Net::HTTP::Get.new(uri.request_uri + "?limit=10000&offset=#{offset}")
  request.add_field("Content-Type", "application/json")
  request.add_field("Accept", "application/json")

  response = http.request(request)
  json_response = JSON.parse(response.body)

  values << json_response['items']
  offset += 10000

end while offset < 100_000

values
#/usr/bin/ruby
需要“uri”
需要“net/http”
需要“json”
uri=uri.parse(“https://someapi.com/data")
偏移量=0
值=[]
开始
http=Net::http.new(uri.host,uri.port)
http.use_ssl=true
http.set\u debug\u输出($stdout)
request=Net::HTTP::Get.new(uri.request_uri+“?limit=10000&offset={offset}”)
添加字段(“内容类型”、“应用程序/json”)
添加字段(“接受”、“应用程序/json”)
response=http.request(请求)
json_response=json.parse(response.body)

值您已经确定了将
+=
用于阵列的问题。因此,可能的解决方案是添加数据,而每次都不创建新数组

values.push响应[value\u key]如果是response.key?值\u键


或者在没有任何运气的情况下使用我尝试过的
推送
concat。我将尝试
否-使用
检查
当前页面
与可能未定义的
总页面
仍然可以看到相同的内容。您介意在这里发布
回复吗?它是否包含
limit
键?Response没有limit键,如果不将新的响应值添加到
values
中,我认为这与问题消失无关。如果Response没有
limit
键,那么
Response['limit']
是关于什么的?这个问题看起来像是被诱导出来的(例如,你的迭代次数比你预期的要多。)啊哈,在看了你发布的
回复之后:你介意计算
总页数吗?这样它就不会转到
INF
?我建议您也将limit传递给block,并在(当前页面+=limit)
时循环
。不幸的是,我不能在附加基准之外说什么。您是否介意定义
def报告;将'Memory'+`ps ax-o pid,rss|grep-E“^[:space:][]*.{$$}”`.strip.split.map(&:to_i)[1]放到_s+'KB';结束
并将
报告
放在对
数组+=…
的调用之后?可能需要尝试使用和不使用
ObjectSpace.garbage\u collect
。我去年遇到了[可能是相同的]问题:另一方面,看起来您的数据不应该增加内部ruby堆。请在您自己的机器上打印内存报告(我很好奇ruby是否会释放内存),并尝试将
ObjectSpace.garbage\u collect
放在
JSON.parse
之后。
#! /usr/bin/ruby
require 'uri'
require 'net/http'
require 'json'

uri = URI.parse("https://someapi.com/data")
offset = 0
values = []

begin
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.set_debug_output($stdout)

  request = Net::HTTP::Get.new(uri.request_uri + "?limit=10000&offset=#{offset}")
  request.add_field("Content-Type", "application/json")
  request.add_field("Accept", "application/json")

  response = http.request(request)
  json_response = JSON.parse(response.body)

  values << json_response['items']
  offset += 10000

end while offset < 100_000

values