【问题标题】:Creating big amount of Sitecore Items causes memory leak创建大量 Sitecore 项目会导致内存泄漏
【发布时间】:2013-05-12 04:59:26
【问题描述】:

我有一个 Sitecore 应用程序,我需要从另一个系统循环创建大量 Sitecore 项目。以下是我的测试目的循环;

using (new Sitecore.SecurityModel.SecurityDisabler())
{
    for (int i = 0; i < 20000; i++)
    {
        Item newItem = MyTemplateItem.CreateItemFrom(DateTime.Now.Ticks.ToString(), myParentItem);

        newItem.Editing.BeginEdit();
        newItem.Fields["Title"].Value = Guid.NewGuid().ToString();
        newItem.Editing.EndEdit();
    }
}

当这个循环运行并且在任务管理器中查看时,进程内存使用量随着时间的推移而增加。

Sitecore Item 类没有实现IDisposable 接口,所以无法调用创建项的Finalizer。

如何避免这种内存泄漏?

PS:我正在使用 Windows 应用程序来执行此操作以绕过 IIS 进程内存泄漏,Sitecore 将在此过程结束时进行缓存更新和索引构建。

【问题讨论】:

  • 你确定这真的是泄漏吗?您正在执行一个必须分配内存并循环执行的函数。仅仅因为进程内存上升并不意味着它是泄漏。内存永远不会下降吗?
  • 我认为我的术语是正确的,内存不断增长,如果 RAM 已满,PC 将重新启动。它是内存泄漏。我已经监视了大约一个小时的循环。

标签: .net memory-management memory-leaks garbage-collection sitecore


【解决方案1】:

您可以在项目创建期间暂时禁用数据库缓存:

using (new Sitecore.Data.DatabaseCacheDisabler())

您可以在创建过程中禁用索引:

Sitecore.Configuration.Settings.Indexing.Enabled = false;

尝试添加这两件事,看看是否有帮助。

更新: 也许这会奏效。 在 EndEdit() 之后将其添加到循环中:

newItem = null;

if (i % 100 == 0)
{
  GC.Collect();
  GC.WaitForPendingFinalizers();
}

每次添加 100 个项目时,它会强制垃圾收集器尝试回收未使用的内存。

如果这可行,那么您实际上不必自己调用 GC,它会在某个时候自动发生,只是您不知道何时。

【讨论】:

  • 感谢您的回复。我尝试了你的建议,但内存增长没有任何变化。
  • 在我的回答中添加了另一个建议
  • 一般来说,您应该避免调用 GC.Collect,因为它是一个非常占用 CPU 的进程,会在执行其操作时阻塞整个 AppPool。
【解决方案2】:

Ruud 的回答似乎比以前更有效。由于数据库缓存的建立,内存的增长很快。通过禁用显着减慢内存增长,但增长仍然非常缓慢。

我使用了以下语句来实现它;

using (new Sitecore.Data.DatabaseCacheDisabler())

newItem = null; // did not worked

// replaced above line with the below
Marshal.Release(Marshal.GetIUnknownForObject(newItem));

if (i % 100 == 0)
{
   GC.Collect();
   GC.WaitForPendingFinalizers();
}

感谢所有支持者!

【讨论】:

    【解决方案3】:

    如果您将缓存限制设置为较高的值(即过高)并执行您正在执行的操作,那么获取您报告的症状似乎是合理的。在脚本运行时查看页面 /sitecore/admin/cache.aspx 将显示是否是这种情况。我会想象条目 master[items]master[data] 将继续攀升......

    如果是这种情况,只需设置较低的缓存限制将意味着根据需要清空缓存,这似乎是一种更健康的控制方式。

    另外,如果您想显着加快程序化项目的创建速度,不妨尝试使用

    using (new BulkUpdateContext()) { code.. }

    BulkUpdateContext() 也可能跳过将项目添加到缓存中 - 我没有检查是否是这种情况,但如果是这样,它也可能会“修复”您遇到的内存问题。

    (另见this SO answer)。请注意,它会禁用多个管道。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      相关资源
      最近更新 更多