2

我的 rails 项目中有一个后台工作人员,它在 ruby​​ 中执行大量复杂的内存中数据聚合。我看到一个奇怪的行为。当我启动一个执行作业(数千个)的进程时,我发现随着时间的推移性能出现奇怪的下降。一开始,一个作业完成大约需要 300 毫秒,但在处理了大约 10.000 个作业后,执行时间将逐渐减少到 2000 毫秒左右。这对我来说是一个大问题,我对这怎么可能发生感到困惑。我没有看到内存泄漏(RAM 使用非常稳定),也没有看到任何错误。什么可能导致这种情况偏低,我应该从哪里开始寻找?

背景事实:

  • 在这项工作所做的事情中,它对很多字符串进行了大量的正则表达式比较。除了对 redis 实例的读/写操作之外,没有进行外部数据库调用。
  • 我试图在不同的服务器/计算机上执行相同的操作,并且症状都是一样的。
  • 如果我在开始表现太差时重新启动该过程,则性能会立即再次变好。
    • 我正在为作业处理器运行 ruby​​ 1.9.3p194 和 rails 3.2 和 sidekiq 2.9.0
4

1 回答 1

1

从您的服务的有限描述中很难判断,但该行为与查找性能较差或您非常依赖且正在增长的小型(即未泄漏)数据缓存一致只是一个适度的速度。一个人为的示例可能是“该工作人员迄今为止完成的工作”的列表,该列表在代码中的几个点按需排序。

一个这样的缓存是你无法直接控制的:Ruby 的符号表。查找符号类似于系统中符号数量的 O(log(n)),这很好。但是,如果您处理大量符号,这仍然会影响您,并且您的工作人员的每次迭代都可以生成新符号(例如,如果输入哈希中的键可以是任意数据,并且您使用symbolize_keys方法或调用to_sym大量不同的字符串)。符号在 Ruby 进程中被永久缓存。理论上,几百万不会显示为内存泄漏。但是,如果您的代码总共可以从 10,000 个符号增加到 1,000,000 个,则所有符号生成和检查代码都会减慢一小部分固定速度。如果你经常这样做,它可能会解释几百毫秒。

如果搜索可疑代码让您无处可去,那么找到问题的最佳选择是使用分析器。您应该收集表现良好和表现不佳的代码的配置文件,并将两者进行比较。

于 2013-07-12T11:42:55.000 回答