【问题标题】:Background job taking twice the time that the same operation within rails后台作业花费的时间是 Rails 中相同操作的两倍
【发布时间】:2014-08-23 15:19:58
【问题描述】:

在我的 Rails 应用程序中,我有一个需要大量数据库访问的长计算。

简而言之,我的计算花了 25 秒。

在后台作业(大型单个工作人员)中执行相同的计算时,相同的计算需要两倍的时间(即 50 秒)。我已经尝试了几种技术将工作置于后台进程中,但没有一个会对我的表现产生影响 => 使用 DelayJob / Sidekiq / 在我的 Rails 中执行该过程,但在为工作创建的线程中,但都具有相同的影响我的表演*2。

这种性能差异仅存在于 rails 的“生产”环境中。看起来我的后台工作中没有由 rails 完成的优化。

我的技术环境如下=>

  • 我正在使用 ruby​​ 2.0 / rails 4
  • 我正在使用独角兽(但没有它我也会遇到同样的问题)。
  • 作业使用 Rails.cache 存储部分计算。
  • 我正在使用 postgresql

有人知道这种影响可能来自哪里吗?

【问题讨论】:

  • 您能否制作尽可能小的样本来重现该问题?
  • 后台工作者是否与独角兽在同一台机器上运行(即具有相同的资源)?它是否访问与 Rails 应用程序相同的缓存(即,当使用内存缓存存储时,缓存将是进程本地的,而不是在独角兽和后台工作人员之间共享)?
  • 如果经过的时间精确地乘以因子 2,那么您确定您的计算没有运行 两次?以防万一:)
  • 您使用的是哪种 Rails 缓存?它是否托管在像 memcache 这样的单独机器上?如果是这样,后台工作者和缓存机器之间是否存在应用程序和缓存之间不存在的任何延迟?

标签: ruby-on-rails delayed-job


【解决方案1】:

我假设您正在将后台作业速度与在 Web 请求期间运行操作的速度进行比较?如果是这样,您可能会受益于 Rails 的QueryCache,它在 Web 请求期间缓存数据库查询。尝试按照此处所述禁用它:

Disabling Rails SQL query caching globally

如果这导致作业的 Web 请求版本花费的时间与后台作业一样长,那么您就找到了罪魁祸首。然后,您可以在后台作业中启用查询缓存以加快速度(如果它对您的应用程序有意义)。

【讨论】:

  • 这是个好主意,但不幸的是它对我的表现影响很小。其他缓存不是 Rails 受益的吗?
【解决方案2】:

后台工作不是需要用于加速的东西。它的主要含义是“触发并忘记”并删除25秒的同步计算并添加更多的异步计算。因此,您可以让用户响应她的请求正在处理并稍后返回计算。

您可以通过将大任务拆分为一些小任务并同时运行它们来提高后台作业的速度。在你的情况下,我认为这是不可能使用的,因为你的计算依赖于操作。

因此,如果您想加快计算速度,则需要研究数据结构的非规范化,在此计算的源数据更新时存储一些计算值以供您的大计算使用。因此,您将根据用户对结果的请求计算更少,而对数据存储进行更多计算。它是使用后台工作的好地方。这样你就完成了数据更新,为更新缓存创建后台任务。如果用户在此任务完成之前请求计算,您仍然需要等待缓存填充。

更新:我想我仍然需要回答你的主要问题。所以基本上,后台任务处理的额外时间来自实施。由于“即发即弃”的方法,没有人需要后台任务调度程序会消耗大量处理器时间来监视新作业。我不完全确定,但认为如果您的计算将复杂两倍,时间增益将相同 25 秒。

【讨论】:

    【解决方案3】:

    我的猜测是,额外的时间来自于后台工作人员加载 Rails 和所有应用程序的需要。我的线索是您说 Rails 在生产模式下的差异最大。在生产模式下,对应用的后续调用会使用应用和类缓存。

    如何检查这个假设:

    更改您的后台作业以执行以下操作:

    1. 在启动工作程序之前打印一条日志消息
    2. 启动工作器
    3. 运行您的计算。作为计算启动的一部分,打印一条日志消息
    4. 打印另一条日志消息
    5. 再次运行计算
    6. 打印另一条日志消息

    然后比较两次运行计算。

    当然,您还会从数据库缓存中获得一些额外的时间优势,代码可能会保留在内存中,等等。但是如果第二次运行要快得多,那么第二次运行并没有重新启动 Rails 的事实更重要。

    此外,第 1 步和第 3 步的日志消息之间的时间间隔也将帮助您了解启动时间。

    修复

    为什么要等? 最重要的是:为什么您需要更快的结果?例如,告诉您的用户计算结果后将通过电子邮件发送给他们。或者让您的用户看到计算正在后台进行,然后再向他们显示结果。

    任何长时间运行的计算的关键是在后台进行并鼓励用户不要等待结果。在得到结果之前,他们应该能够做其他事情。

    自动开始计算一旦用户登录,或在他们做了一些有趣的事情后,开始计算。这样,当(如果)用户要求计算时,答案要么已经完成,要么很快就会完成。

    缓存结果并根据需要破坏缓存 与上述类似,定期自动开始计算。如果用户更改了一些数据,则通过破坏缓存重新开始计算。如果数据在计算期间发生更改,还有一些方法可以停止任何正在进行的计算。

    预计算部分计算 为什么要花 25 秒或更长时间进行 dbms 计算?可能是你应该改变计算。研究添加索引、汇总表、反规范化、将计算拆分为可以预先计算的较小步骤等。

    【讨论】:

      猜你喜欢
      • 2013-03-11
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 2012-01-23
      • 2016-04-22
      • 2021-10-26
      • 2016-05-31
      相关资源
      最近更新 更多