搜索

查看: 3217|回复: 11

[JavaScript] NodeJs超长字符串问题处理的详细分析

[复制链接]
发表于 2023-5-4 11:50:00 | 显示全部楼层 |阅读模式
Editor 2023-5-4 11:50:00 3217 11 看全部
目录
  • 问题背景
  • 代码细节
  • 更进一步
  • 总结问题:对于超大的 string V8不能支持

    问题背景
    在 Nodejs 计算服务中,对端上上报的内存信息二进制数据进行预处理+缓存时,遇到了一个奇怪的报错:RangeError: Invalid string length 。根据该报错信息,查找得知是字符串长度超过了 node.js 的限制,即 2^29-1 (约 5 亿+)个字符。整体流程如图所示。
    关于 node.js string 的长度上限,主要和 V8 引擎「压缩指针」技术有关。按个人理解,其通过压缩指向变量的地址(64 位)中固定的 32 位的方式,从而减少引擎的内存占用。

    202302201135051.png

    NodeJs超长字符串问题处理的详细分析1304 作者:Editor 帖子ID:2752 论坛知鸟论坛_zn60.com


    代码细节
    由于需要快速访问某地址,因此缓存的数据结构必须是个对象,即 INodeGraph。具体结构如下:
      type IAddr = string;
    // 内存图谱
      declare interface INodeGraph {
        [addr: IAddr]: IParsedNode;
      }
    // 内存节点信息
      declare interface IParsedNode {
        addr: IAddr;
        // size, nodeType 等辅助信息
        parentNodeAddr: IAddr[]; // addr
        childNodeAddr: string[]; // addr
        edgeMap: {
          [addr: IAddr]: {
            // 当前节点与父子节点之间的边(关系)的信息
          };
        };
      }
    我们目的很明确,就是实现这样一个 js 大对象的持久化存储,并且能够方便快速的转回 js object。为解决此问题,首先想到的能否利用 protobuf 替代 JSON 实现持久化。可惜的是 protobuf 并不适用于动态 key 的场景,它适用于处理数组中存储多个相似结构对象的数据结构。
    随后尝试了减少对象中不必要的信息,即缩短对象的固定 key,例如用「pNode」取代冗长的「parentNodeAddr」。对于一个百万个键值对的 object 而言,虽然牺牲了代码的可读性,但在实际的 case 中,能承载的键值对数量大约多了 20%。
    事实上回过头来看,更好的处理方式或许是用另外的 Map 存储对象的 key。例如 : 将nodeGraph.parentNodeAddr这个 key 最大程度缩短为nodeGraph.p
    声明 const GraphKey = { parentNodeAddr: 'p' } 保存一个 key 的映射,需要访问某属性时,使用nodeGraph[GraphKey.parentNodeAddr]

    更进一步
    上述手段只是治标不治本,对于 key 更多的大对象并不能彻底解决问题。因此在不改变项目整体架构的前提下(如使用图数据库/改用 go 开发等),提出以下两个最终方案:
    方案 1:借助 Node.js C++ Addons 的能力,绕开 js string 的限制,将相关序列化逻辑交给 C++ 处理,并直接将处理好的引用树 js object 进行后续处理。
  • 优势:如果能实现,性能会获得优先提升;扩展了 Node.js 的能力
  • 劣势:实现难度大;维护可能是个问题
    方案 2:生成引用树缓存时,拆分为多个较小的对象,分别进行序列化和存储,使用时再合并为一个大对象。
  • 优势:无需 C++ 侧开发,难度更小;维护方便
  • 劣势:合并对象需要额外的时间,这一步骤可能会让未命中缓存时的首次请求更慢

    202302201135052.png

    NodeJs超长字符串问题处理的详细分析5827 作者:Editor 帖子ID:2752 论坛知鸟论坛_zn60.com


    总结
    到此这篇关于NodeJs超长字符串问题处理的文章就介绍到这了,更多相关NodeJs字符串问题处理内容请搜索知鸟论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持知鸟论坛!
  • 发表于 2023-6-28 18:04:29 | 显示全部楼层
    ffycxyw2274436 2023-6-28 18:04:29 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    发表于 2023-6-28 22:17:49 | 显示全部楼层
    永远就三年疗 2023-6-28 22:17:49 看全部
    楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
    发表于 2023-6-29 18:11:48 | 显示全部楼层
    永远爱你冰塘 2023-6-29 18:11:48 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    发表于 2023-6-29 18:33:19 | 显示全部楼层
    术数古籍专卖疤 2023-6-29 18:33:19 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    发表于 2023-6-29 19:17:07 | 显示全部楼层
    贺老师 2023-6-29 19:17:07 看全部
    楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
    发表于 2023-6-30 08:54:58 | 显示全部楼层
    心随674 2023-6-30 08:54:58 看全部
    感谢楼主的无私分享!要想知鸟论坛好 就靠你我他
    发表于 2023-6-30 16:19:02 | 显示全部楼层
    胡37 2023-6-30 16:19:02 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    发表于 2023-7-3 12:10:21 | 显示全部楼层
    素色流年783 2023-7-3 12:10:21 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    发表于 2023-7-3 19:42:38 | 显示全部楼层
    无人岛屿颈 2023-7-3 19:42:38 看全部
    其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
    • 您可能感兴趣
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| 小黑屋| 知鸟论坛 |网站地图
    本站资源来自互联网用户收集发布,如有侵权请邮件联系处理。 联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表