如何按内存限制拆分数组?

问题描述 投票:0回答:1

我想将对象数组拆分为内存限制,每个内存块不应大于4MB,有什么办法吗?通过下面的代码,我得到了输入数组的大小。

var sizeof = require('object-sizeof')

var arr = [{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"g1ob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"}];

console.log(sizeof(arr))
javascript arrays node.js algorithm memory-management
1个回答
0
投票

如果要限制数据,则必须定义分块算法才能在quota中使用。这些步骤实际上非常简单:

  1. 创建一个新块。
  2. 向其中添加项目,直到配额用完为止-不要超过它。
  3. 如果达到配额,则从1开始。
  4. 如果到达数组的末尾-完成。
  5. 这里是实现的外观。

NOTE

:我相信object-sizeof库可以正确计算对象的大小。我不确定是否确实需要考虑对象引用。因此,假设实现是正确的。

NOTE 2

:我找不到该库的CDN副本,因此出于示例目的,我实现了一个非常笨拙的替换算法。每个键的大小为1,每个值的值为1。对象值是递归计算的。

/*
 * dumb implementation of `sizeof` for example purposes.
 * The "size" is 1 for each key and 1 for each simple value.
 *  {a: "b"} has size = 2
 *  {a: {b: "c"}} has size = 3, etc.
 */
var sizeof = obj => Object.entries(obj)
  .reduce((sum, [key, value]) => 
    sum + 1 + (typeof value !== "object" ? 1 : sizeof(value)),
    0
  )

var arr = [{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"g1ob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"},{test:"gob", gg:"2"}];

function chunkToLimit(arr, limit) {
  var result = [];
  
  //variables needed for the loop. Initialised properly later
  var chunk;
  var remainingQuota = -Infinity;
  
  for (var i = 0; i < arr.length; i++) {
    var item = arr[i];
    var size = sizeof(item);

    if (size > remainingQuota) {
      //the current chunk that will be filled
      chunk = [];
      //account for the size of the empty chunk itself
      remainingQuota = limit - sizeof(chunk);
      
      //add to result
      result.push(chunk);
    }
    
    remainingQuota -= size
    chunk.push(item);
  }
  
  return result;
}

console.log(chunkToLimit(arr, 10))

这将导致内存限制

,但是如果您需要通过Internet发送此消息,那么您将使用JSON序列化,因此有效负载的大小可能与普通对象的大小完全不同,因为每个项目都将被编码为字符串,而且{a: "b", c:"d"}甚至不会是"a" +"b"+"c"+ "d"的大小,但还会包含{}表示对象, ,分隔属性以及每个键和值周围的"。因此,大小看起来将不同于对象的大小。

幸运的是,JSON的大小更容易计算。它是一个字符串,因此您只需要知道它的大小即可。为此,您可以在Node.js中使用BufferBuffer可用于直接计算序列化为JSON时对象的字节大小。

Buffer.byteLength

在这种情况下,您将需要与之前不同的步骤:

  1. 如果添加新项目,检查块是否会超过限制。
  2. 如果是这样,则完成当前块并开始一个新块。
  3. 将当前项目添加到块中。
  4. 重复直到阵列用尽。
  5. 这里是一个实现:

NOTE

:我正在使用Buffer.byteLength,因为它在浏览器中可用。操作应相同,仅更改var sizeof = obj => Buffer.byteLength(JSON.stringify(obj), 'utf8') 功能。

© www.soinside.com 2019 - 2024. All rights reserved.