Reputation: 1453
I have an application where I'm using a high number of CSharpScript
instances to control the application. The problem I'm facing is that the memory usage depends heavily on what type of global object I'm using. If the global type is defined in my application assembly (huge assembly) the memory usage rises by about ~100MB for every compiled script. If I instead put the global type in a separate assembly I find the memory usage to rise by ~10MB for each script which is still a lot for the amount of scripts I'm using.
Is there any way to limit this memory usage when using the CSharpScript API?
Upvotes: 0
Views: 1613
Reputation: 1122
I don't know what is your specific implementation but it might be possible for you to do this:
Instead of giving the data to your scripts using big heavy global object, you can let the script give your application only their logic:
instead of this csx file, with HeavyObject as global:
// script.csx:
HeavyObject.DoSomeWork();
you can write this csx, with no global param needed:
// betterscript.csx:
public class ScriptWork : IHaveWork
{
Work(HeavyType obj)
{
obj.DoSomeWork();
}
}
return new ScriptWork();
you need this interface in your app:
public interface IHaveWork
{
void Work(HeavyType obj);
}
and the script should run with references to your application. You would receive from your script an instance of IHaveWork, and then you should call Work within your application.
Upvotes: 1
Reputation: 16991
What I believe is happening here is that your script directly references an object defined in the main application. Since the script is compiled in to a separate AppDomain
, this causes that AppDomain
to pull in its own local copy of things from the AppDomain
of the main application. Since you have 100s of scripts, each in their own AppDomain
your main assembly gets loaded 100s of times.
One way to avoid this is to have any interfaces between the scripts and the application pass through a "shim" object, which is a small class, defined in its own assembly, that can "serialize" data across that AppDomain
boundary. That Shim class should inherit from MarshalByReferenceObject
. This can be tricky and complex, because the shim can't pass any of the classes defined in the application, or it will "suck in" the main assembly just like before. Everything must be passed as classes defined in .NET.
The MarshalByReferenceObject
as a base class allows the shim to cross the domain boundary without bringing in an entire copy of the assembly. More information can be found at
https://msdn.microsoft.com/en-us/library/system.marshalbyrefobject(v=vs.110).aspx#Remarks
Upvotes: 2