-
Hello, I have used Jint to implement some data import and data query work in OrchardCore. But in the process of processing data, I found that the memory occupied by the script has not been released after each execution. In OrchardCore it is used as follows public IScriptingScope CreateScope(IEnumerable<GlobalMethod> methods, IServiceProvider serviceProvider, IFileProvider fileProvider, string basePath)
{
var engine = new Engine();
foreach (var method in methods)
{
engine.SetValue(method.Name, method.Method(serviceProvider));
}
return new JavaScriptScope(engine, serviceProvider);
}
public object Evaluate(IScriptingScope scope, string script)
{
static void ThrowInvalidScopeTypeException()
{
throw new ArgumentException($"Expected a scope of type {nameof(JavaScriptScope)}", nameof(scope));
}
if (scope is not JavaScriptScope jsScope)
{
ThrowInvalidScopeTypeException();
}
var parsedAst = _memoryCache.GetOrCreate(script, static entry => Engine.PrepareScript((string) entry.Key));
var result = jsScope.Engine.Evaluate(parsedAst).ToObject();
return result;
} It's called like this in my code var script = $@"var parameters={JsonConvert.SerializeObject(parameters)};
{extDbQuery.Scripts}";
var engine = _scriptingManager.GetScriptingEngine("js");
var scope = (JavaScriptScope)engine.CreateScope(_scriptingManager.GlobalMethodProviders.SelectMany(x => x.GetMethods()), _serviceProvider, null, null);
try
{
dynamic jsValue =scope.Engine.Evaluate(script);
//dynamic jsValue = _scriptingManager.Evaluate("js:"+script,null,null,null);
I've seen some issues about it and there doesn't seem to be any mention of how to completely free an instance of an engine that is no longer in use In my case, it seems possible to work around memory limitations by limiting the number of data rows, such as limiting users to importing only 10,000 data at a time. Every time I create a new engine instance, but I don't know how to fully release them. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 15 replies
-
When I execute the following code,that the memory is immediately reclaimed var arr = Array(10_000_000).fill(new Array(10_000_000));
return arr.length but in the other script, no collection is performed this is my testing code : var insertList = [];
var total = 0, start = 0;
while (start < 1_000_000) {
insertList.push({
"CnTy": "edfgwegweg",
"CreationTime": "234123t'rtr",
"CreatorUserId": 1,
"IsDeleted": 0,
"Soldto": "2342341",
"MarkFor": null,
"SalesOrg": "123",
"Material": "123124",
"Remark": "234234",
"ValidFrom": "124123123",
"ValidTo": "223423412300Z",
"ListPriceType": null,
"Currency": "CNY",
"ScaleQty": 1,
"PriceFrom": 2,
"CustomerGroup": null,
"SOA": "123124",
"UoM": "234234123",
"Unit": 23,
"Amount": 123123.124
})
start++
}
var output = {
total: insertList.length
}
insertList = null
return output |
Beta Was this translation helpful? Give feedback.
-
The "Diagnostic Tools" "Process Memory" graph shows the Private Bytes of the entire process, if you hover your mouse on "Private Bytes" it will display a tooltip:
I tested a modified version of your script in "a"+"b"+3+new Array(1).fill(1).map(a=>a+1).push({a:1}) // warmup
System.GC.Collect()
// take snapshot
var insertList = []; var total = 0, start = 0; while (start < 10000) { insertList.push({ "CnTy": "edfgwegweg", "CreationTime": "234123t'rtr", "CreatorUserId": 1, "IsDeleted": 0, "Soldto": "2342341", "MarkFor": null, "SalesOrg": "123", "Material": "123124", "Remark": "234234", "ValidFrom": "124123123", "ValidTo": "223423412300Z", "ListPriceType": null, "Currency": "CNY", "ScaleQty": 1, "PriceFrom": 2, "CustomerGroup": null, "SOA": "123124", "UoM": "234234123", "Unit": 23, "Amount": 123123.124 }); start++; }; var output = { total: insertList.length }; return output
// take snapshot
System.GC.Collect()
// take snapshot
insertList = null;
// take snapshot
System.GC.Collect()
// take snapshot From the snapshots we can see As for why "Private bytes" didn't get released back to the OS, I don't know enough about memory management on Windows/.NET to comment. |
Beta Was this translation helpful? Give feedback.
-
I have faced the same problem. And If I understand it correctly, there is no memory leak but bizarre behavior of GC.
Result of
Result of
gcroot showed that there are no objects that hold Engine. I called GC manually, and it cleaned everything after some time.
It looks like a problem with GC and some data structures |
Beta Was this translation helpful? Give feedback.
-
You should also try to disable object identity tracking under interop: Line 248 in 4839fd1 |
Beta Was this translation helpful? Give feedback.
-
There's now a new release 3.0.0-beta-2046 which contains manual clearing of object identity tracking in Engine's |
Beta Was this translation helpful? Give feedback.
-
In latest release the identity tracking has been disabled by default. |
Beta Was this translation helpful? Give feedback.
You should also try to disable object identity tracking under interop:
jint/Jint/Options.cs
Line 248 in 4839fd1