1

我的问题是:

我有一个使用大量内存的 perl 脚本(由于缓存的预期行为)。但是,我注意到我做的缓存越多,它变得越慢,并且该过程大部分时间都处于睡眠模式。

我认为为进程预先分配内存可能会提高性能。

有人在这里有什么想法吗?

更新

我想我在这里不是很清楚。我将更清楚地提出问题:

我不是在寻找在 perl 脚本中进行预分配的方法。我认为这对我没有多大帮助。我感兴趣的是一种告诉操作系统为我的 perl 脚本分配 X 内存量的方法,这样它就不必与以后进入的其他进程竞争。

假设我无法摆脱内存使用。虽然,我也在探索减少这种情况的方法,但不要指望那里有太大的改善。仅供参考,我正在使用 solaris 10 机器。

4

10 回答 10

4

我从您的帖子和评论中收集到的是:

  • 当内存使用量增加时,您的程序会变慢
  • 你的程序越来越多地花时间睡觉,而不是计算。

最可能的解释:睡眠意味着等待资源可用。在这种情况下,资源最有可能是内存。使用 vmstat 1 命令进行验证。看看 sr 列。如果它持续超过约 150,系统将不顾一切地释放页面以满足需求。这伴随着 pi、po 和 fr 列的高活性。

如果确实如此,您的最佳选择是:

  • 升级系统内存以满足需求
  • 将内存使用量减少到适合当前系统的水平。

预分配内存无济于事。在任何一种情况下,内存需求都会在某个时候超过可用的主内存。然后内核必须决定哪些页面现在需要在内存中,哪些页面可以被清除并重新用于更迫切需要的页面。如果所有经常需要的页面(工作集)都超过了主内存的大小,则系统会不断地将页面从二级存储(交换)移动到二级存储(交换)。然后,系统被认为是颠簸,并没有花太多时间做有用的工作。除了增加内存或减少使用内存之外,您对此无能为力。

于 2008-09-27T00:25:00.020 回答
2

来自评论:

内存限制不是很严重,但内存占用很容易增长到 GB,当我们有竞争内存的进程时,它会变得非常慢。我想从操作系统中保留一些内存,这样即使有太多其他进程来了,抖动也很小。贾格马尔

那我们换个思路吧。问题并不在于您的 Perl 脚本。相反,机器上的所有进程都消耗太多内存,机器无法按照配置进行处理。

您可以“保留”内存,但这并不能防止颠簸。事实上,它可能会使问题变得更糟,因为操作系统不会知道您是在使用内存还是只是将其保存以备后用。

我怀疑你正在遭受公地悲剧。我对很多其他用户在有问题的机器上是对的吗?如果是这样,这更像是一个社会问题而不是技术问题。您需要有人(可能是系统管理员)介入并协调机器上的所有进程。他们应该找到最奢侈的内存消耗者,并与他们的程序员一起减少系统资源的成本。此外,他们应该安排要调度的进程,以便资源分配是有效的。最后,他们可能需要获得更多或改进的硬件来处理预期的系统负载。

于 2008-09-26T19:17:43.083 回答
0

你可能会问自己一些问题:

  • 我的数据结构对手头的任务真的有用吗?
  • 我真的需要缓存那么多吗?
  • 我可以在一段时间后丢弃缓存的数据吗?
于 2008-09-24T15:16:21.583 回答
0

看看http://metacpan.org/pod/Devel::Size

您也可以内联 ac 函数来执行上述操作。

据我所知,您不能直接从 Perl 分配内存。您可以通过编写 XS 模块或使用我提到的内联 C 函数来解决此问题。

于 2008-09-24T15:32:54.663 回答
0
my @array;
$#array = 1_000_000; # pre-extend array to one million elements,
                     # http://perldoc.perl.org/perldata.html#Scalar-values

my %hash;
keys(%hash) = 8192; # pre-allocate hash buckets 
                    # (same documentation section)

不熟悉您的代码,我会在这里冒险一些疯狂的猜测 [笑] 这些技术不会为您的脚本提供新的高效率,但预分配可能会有所帮助。

祝你好运!

——道格拉斯·亨特

于 2008-09-24T15:46:34.037 回答
0

我最近重新发现了一篇很棒的Randal L. Schwartz 文章,其中包括预分配数组。假设这是您的问题,您可以使用该代码的变体来测试预分配。但一定要测试结果。

脚本因更多缓存而变慢的原因可能是thrashing。大概缓存的原因首先是为了提高性能。所以一个快速的答案是:减少缓存。

现在可能有一些方法可以修改您的缓存方案,以便它使用更少的主内存并避免抖动。例如,您可能会发现缓存到文件或数据库而不是内存可以提高性能。我发现文件系统和数据库缓存比应用程序缓存更有效,并且可以在多个实例之间共享。

另一个想法可能是更改您的算法以减少其他区域的内存使用量。例如,不是将整个文件拉入内存,Perl 程序往往会更好地逐行读取。

最后,你探索过 Memoize 模块吗?它可能不会立即适用,但它可能是想法的来源。

于 2008-09-24T16:22:30.847 回答
0

我还没有找到一种方法来做到这一点。

但是,我发现(有关详细信息,请参阅

分配给词法(即 my() 变量)的内存即使超出范围也无法回收或重用。它被保留以防变量返回范围。分配给全局变量的内存可以通过使用 undef()ing 和/或 delete() 重用(在您的程序中)。

所以,我相信这里的一种可能性是检查我是否可以在给定的时间点减少词汇变量的总内存打印。

于 2008-09-25T12:38:32.953 回答
0

听起来您正在寻找limitulimit。但我怀疑这会导致超出限制的脚本失败,这可能不是你想要的。

更好的想法可能是在进程之间共享缓存数据。根据我的经验,将数据放入数据库或文件中效果很好。

我不想这么说,但是如果您的内存限制如此严重,那么 Perl 可能不是该应用程序的正确语言。我认为C将是一个更好的选择。

于 2008-09-25T15:27:40.643 回答
0

您可以做的一件事是使用 solaris 区域(容器)。
您可以将您的进程放在一个区域中并为其分配 RAM 和 CPU 等资源。
以下是一些教程的两个链接:

  1. Solaris 容器如何指导
  2. Solaris 10 08/07 操作系统中的区域资源控制
于 2008-10-01T06:49:20.283 回答
0

虽然它没有按照您的要求进行预分配,但您可能还想查看大页面大小选项,以便当 perl 必须向操作系统要求为您的程序提供更多内存时,它会以更大的块获取它。

请参阅Solaris Internals:Multiple Page Size Support以获取有关其产生的差异以及如何做到这一点的更多信息。

于 2009-01-12T00:29:34.050 回答