【问题标题】:Node.js JSON.parse on object creation vs. with getter propertyNode.js JSON.parse 对象创建与 getter 属性
【发布时间】:2015-12-28 03:06:36
【问题描述】:

这主要是一个'我做得对吗/我怎样才能做得更好'之类的话题,最后还有一些具体的问题。如果您对下面的文字有其他建议/评论,即使我没有特别提出这些问题,也请随时发表评论。


我有一个 MySQL 表供我的应用程序的用户使用,除了一组固定列外,还有一个包含 JSON 配置对象的文本列。这是为了存储无法存储在单独列中的可变配置数据,因为每个用户具有不同的属性。不需要对配置数据进行任何查找/排序/任何操作,因此我们认为这是最好的方法。

当从我的 Node.JS 应用程序(在 Node 0.12.4 上运行)查询数据库时,我将 JSON 文本分配给一个对象,然后使用 Object.defineProperty 创建一个 getter 属性,该属性在 JSON 字符串数据被解析时解析它需要并将其添加到对象中。

代码如下所示:

user = 
    uid: results[0].uid
    _c: results[0].user_config # JSON config data as string

Object.defineProperty user, 'config',
    get: ->
        @c = JSON.parse @_c if not @c?
        return @c

编辑:上面的代码是Coffeescript,对于那些不使用Coffeescript的人来说,这是(近似的)Javascript等价物:

var user = {
    uid: results[0].uid,
    _c: results[0].user_config // JSON config data as string
};

Object.defineProperty(user, 'config', {
    get: function() {
        if(this.c === undefined){
            this.c = JSON.parse(this._c);
        }
        return this.c;
    }
});

我以这种方式实现它是因为解析 JSON 会阻塞 Node 事件循环,并且 config 属性只需要大约一半的时间(这是在快速服务器的中间件函数中)所以这种方式 JSON 只会在以下情况下被解析它实际上是需要的。配置数据本身的范围可以从 5 到大约 50 个不同的属性组织在几个嵌套对象中,不是大量的数据,但仍然不仅仅是几行 JSON。

此外,这些 JSON 对象有 3 个(我只展示了一个,因为它们基本相同,只是其中的数据不同)。每个场景在不同的场景中都需要,但所有场景都依赖于变量(其中一些来自外部来源),所以在这个函数的点上,不可能知道哪些是必要的。

所以我有几个关于这种方法的问题,希望你们能回答。

  • 使用Object.defineProperty 是否会对性能产生负面影响,如果有,是否会抵消不立即解析 JSON 数据带来的好处?

  • 我是否正确假设不立即解析 JSON 实际上会提高性能?我们正在处理大量的请求,我们需要快速有效地处理这些请求。

  • 现在这三个 JSON 数据集来自在 SQL 查询中连接的两个不同的表。这是每个请求只需要进行一次查询,而不是最多四次。请记住,有些场景不需要任何 JSON 数据,但也有需要所有三个数据集的场景(当然还有介于两者之间的场景),仅从其表中获取所需的 JSON 数据是否是一种改进,在实际需要其中一个数据集的时候?我避免了这种情况,因为我觉得等待执行四个单独的 SELECT 查询比等待一个包含两个 JOINed 表的查询要花费更长的时间。

  • 是否有其他方法可以进一步提高总体性能? (我知道,这是一个有点主观的问题,但欢迎对我应该检查的事情提出想法/建议)。不过,我不打算将 JSON 数据解析到单独的线程中,因为我们的服务在虚拟化单核服务器集群上运行,创建子进程只会增加总体 CPU 使用率,而在高负载下会增加对性能的负面影响更大。

注意:当我说性能时,主要是指快速高效的吞吐率。我们更喜欢更大的内存占用而不是更重的 CPU 使用率。

【问题讨论】:

    标签: javascript mysql json node.js coffeescript


    【解决方案1】:

    我们应该忘记小的效率,比如大约 97% 的时间: 过早优化是万恶之源
    - 唐纳德·高德纳

    我从那篇文章中得到了什么?太多时间花在优化可疑结果上,而不是专注于设计和清晰度。

    JSON.parse 确实会阻塞事件循环,但每个同步调用都会阻塞 - 这只是代码执行,并不是一件坏事。

    根本问题不是阻塞,而是阻塞多长时间。我记得一位 Strongloop 讲师说 10 毫秒是一个很好的经验法则,可以让云规模的应用程序中的呼叫的最大执行时间。 >10ms 是开始优化的时间 - 对于大规模应用程序。每个应用程序都必须定义该阈值。

    那么,你的惰性初始化会节省多少执行时间? This article 表示解析一个 15MB 的 json 字符串需要 1.5 秒 - 大约 10,000 B/ms。 3 个配置,每个 50 个属性,30 字节/k-v 对 = 4500 字节 - 大约半毫秒。

    到了优化的时候,我会考虑让你的惰性 init 执行 MySQL 调用。配置只需要 50% 的时间,它不会阻塞事件循环,并且对 db 的外部调用绝对让 JSON.parse() 相形见绌。

    所有这些都是为了说明:您所做的不一定是坏事或错误,但如果整个应用程序都充斥着这些类型的可疑优化,那么这对功能添加和维护有何影响?我看到的最大问题是上市时间,而不是速度。代码复杂性会增加上市时间。

    Q1使用 Object.defineProperty 时是否会对性能产生负面影响...

    查看this site 以获得提示。

    Q2:*...不立即解析 JSON 实际上会提高性能...

    恕我直言:无关紧要

    Q3目前这三个 JSON 数据集来自两个不同的表...

    大多数数据库查询成本通常是进程外调用和网络数据传输(除非您的架构或配置非常糟糕)。一次通话中的所有数据都是正确的举措。

    Q4是否有其他方法可以提高整体性能

    无法判断。首先是观察到的行为,然后是分析工具来识别罪魁祸首,然后是代码优化。

    【讨论】:

    • 根据我以前开发的应用程序的经验,在处理大量流量时,JSON 解析通常是一个相对显着的性能瓶颈,比数据库查询更严重,因为查询是异步处理的,而 JSON数据不是。在惰性初始化中执行 MySQL 查询不是一种选择,因为我确实需要立即使用用户数据,它只是并不总是需要的配置属性,因此无论哪种方式都必须在那时进行数据库调用。无论如何,谢谢你的回复,它给了我一些答案和一些值得思考的事情。
    猜你喜欢
    • 2016-11-29
    • 2016-05-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 2015-10-15
    相关资源
    最近更新 更多