【问题标题】:out of memory when repeatedly initializing Clearscript V8 engine (GC issue?)重复初始化 Clearscript V8 引擎时内存不足(GC 问题?)
【发布时间】:2016-09-20 02:52:39
【问题描述】:

我创建了一个基本的默认 ASP.NET 5 项目。我有一个控制器可以创建

var engine = new V8ScriptEngine();

并返回一些模拟 json。当我刷新页面一定次数时,我会得到

堆设置中的致命错误

分配失败 - 进程内存不足

并遵循堆栈跟踪

Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at V8Isolate.Create(StdString* , V8IsolateConstraints* , Boolean , Int32 )
   at Microsoft.ClearScript.V8.V8IsolateProxyImpl..ctor(String gcName, V8RuntimeConstraints gcConstraints, Boolean enableDebugging, Int32 debugPort)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Microsoft.ClearScript.V8.V8Proxy.CreateImpl[T](Object[] args)
   at Microsoft.ClearScript.V8.V8IsolateProxy.Create(String name, V8RuntimeConstraints constraints, Boolean enableDebugging, Int32 debugPort)
   at Microsoft.ClearScript.V8.V8Runtime..ctor(String name, V8RuntimeConstraints constraints, V8RuntimeFlags flags, Int32 debugPort)
   at Microsoft.ClearScript.V8.V8ScriptEngine..ctor(V8Runtime runtime, String name, V8RuntimeConstraints constraints, V8ScriptEngineFlags flags, Int32 debugPort)
   at Microsoft.ClearScript.V8.V8ScriptEngine..ctor()

我尝试用dotMemory查看内存。每次我刷新页面时,都会创建一个引擎,并将 2MB 的内存添加到非托管内存中。当它达到某个限制时,它会崩溃,如上所述。只要我在达到限制之前单击强制 GC,内存就会下降,我可以再次使用该页面。

我的问题是:为什么 GC 不首先处理这个问题?在每次请求之后,对象可以被释放,如果我强制 GC 就可以了。我假设如果我几乎没有内存但我可以用 GC 回收它,它会这样做。

我该如何解决这个问题?也许添加更多内存会有所帮助,但我也不知道该怎么做。如果 GC 永远不会清理这些对象,它无论如何都会破坏。

当我运行 Kestrel (dnx web) 和 IIS 时也会发生同样的情况。 我将框架设置为“dnx46”

这是我的 dnx 版本

$ dnx --version
Microsoft .NET Execution environment
 Version:      1.0.0-rc1-16231
 Type:         Clr
 Architecture: x86
 OS Name:      Windows
 OS Version:   10.0
 Runtime Id:   win10-x86

ClearScript 版本为"ClearScript.V8": "5.4.3"

【问题讨论】:

  • 你是在使用后取消所有对它的引用,还是等待它决定生命的结束?
  • 我没有把它清空,但它超出了范围:[HttpGet] public JsonResult Get() { var engine = new V8ScriptEngine(); return new JsonResult("asd"); }
  • 我遇到了一些问题,让事情滑入超出范围是不够的 - 我已经用 excel 做到了这一点,即使你说退出,它也会让它保持打开状态。我已经有了很多事情,将它们归零总是可以解决问题

标签: c# asp.net memory-leaks garbage-collection v8


【解决方案1】:

简短版本:完成后,您需要dispose 每个脚本引擎。一种方便的方法是使用using 语句:

using (var engine = new V8ScriptEngine()) {
    // do stuff
}

加长版:每个 V8 实例都保留一大块地址空间。这些不会显示为已用内存,但在 32 位进程中,只有几十个实例就可以用完地址空间。托管 GC 最终会将其全部清理干净,但由于它无法跟踪 V8 的地址空间预留,因此并不急于这样做,因为它没有检测到任何内存压力。最终,您的内存使用率仍然很低,但 V8 无法再保留足够大的地址空间块,因此它失败了。

【讨论】:

  • 所以如果我有一个在内部创建引擎的类,我应该在其中实现IDisposable 并委托给引擎的Dispose 方法,并在我完成或使用@987654327 时显式调用它@ 构造,对吧?
  • 是的;为了获得最佳结果,如果您的班级在内部使用 V8ScriptEngine,则应实现 IDisposable 并委托实施。
猜你喜欢
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 2015-04-10
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多