This message was discovered on microsoft.public.dotnet.vsa.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
| Trent |
| GOOD ANSWER |
I have been working on loading and unload the VSA Engine into AppDomain to reduce the amount of memory usage in my application. I have built a test environment that will create and unload a VSA Engine into a AppDomain. While this reduces the amount of memory used compared to simple creating and destroying the VAS Engine in the one domain, I still have an increase in memory.
Have I set up the configuration for the domain incorrectly or is this the wrong way.
I have attached the project and the code it anybody would like to test it. You will notice an increase in memory if the engine is complied.
Test (With a for loop of 100) Without Compile Memory Usage = 15,000 k With compile Memory usage = 30,000 K
While these memory values are low, it cause problems in the production environment when the number of engines and complexity of the script increase.
Thanks
using System; using System.Reflection; using System.Windows.Forms; using System.Collections; namespace AppDomainTesting { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { for(int i=0; i<100; i++) { AppDomain appDomain = null; AppDomainSetup setup = new AppDomainSetup(); AppDomainSetup appDomainSetUp = new AppDomainSetup();
Console.WriteLine("Insatance = "+i.ToString()); try {
appDomain = AppDomain.CreateDomain(System.Guid.NewGuid().ToString(),null,appDomainSetUp) ;
string assemblyName = Assembly.GetAssembly( typeof(AppDomainTesting.ScriptEngine) ).FullName;
AppDomainTesting.TestEngine test = (AppDomainTesting.TestEngine)appDomain.CreateInstanceAndUnwrap(assemblyName, "AppDomainTesting.TestEngine"); //comment out the next line and memory usage will be lower test.Compile(); test.Run();
} catch(System.Exception err) { string error = err.ToString(); System.Windows.Forms.MessageBox.Show(error); } finally { if(appDomain != null) AppDomain.Unload(appDomain); }
}
Console.WriteLine("Total Memory =" + GC.GetTotalMemory(true).ToString()); Console.WriteLine("Press Enter To End"); if(Console.Read()>0) return; } } public class TestEngine : System.ComponentModel.Component { private ScriptEngine engine; public TestEngine() { engine = new ScriptEngine(); } public void Compile() { engine.Compile(); } public void Run() {
if(engine.IsCompiled) { engine.Run();
string strNamespace = engine.RootNamespace; string FullName = strNamespace +".script";
// Get the method from the type Type ModType = engine.Assembly.GetType(FullName,true,true); System.Reflection.MethodInfo method = ModType.GetMethod("main"); if (method != null) method.Invoke(null,null); } } } public class ScriptEngine : Microsoft.VisualBasic.Vsa.VsaEngine { public ScriptEngine() { this.RootMoniker = "MemoryTesting://script"; this.Site = new VsaBaseSite(); this.InitNew(); this.RootNamespace = "scriptcode"; this.Name = "scriptcode"; Microsoft.Vsa.IVsaReferenceItem systemRef= (Microsoft.Vsa.IVsaReferenceItem)this.Items.CreateItem("system.dll",Microsof t.Vsa.VsaItemType.Reference, Microsoft.Vsa.VsaItemFlag.None); systemRef.AssemblyName = "System.dll"; Microsoft.Vsa.IVsaCodeItem code= (Microsoft.Vsa.IVsaCodeItem)this.Items.CreateItem("main",Microsoft.Vsa.VsaIt emType.Code, Microsoft.Vsa.VsaItemFlag.Module); code.SourceText= this.script;
} private string script = "Option Strict Off\n"+ "Option Explicit Off\n"+ "Imports System\n"+ "Imports System.Windows.Forms\n"+ "Public Module script\n"+ "Sub main\n"+ //"MessageBox.Show(\"Testing\")\n"+ "Console.WriteLine(\"Testing \" & DateTime.Now.ToLongTimeString())\n"+ //"MessageBox.Show(\"Testing\")\n"+ "End Sub\n"+ "End Module\n"; } public class VsaBaseSite :Microsoft.Vsa.IVsaSite {
#region Implementation of IVsaSite public object GetEventSourceInstance(string itemName, string eventSourceName) { return null; } public object GetGlobalInstance(string name) { return null; } public void Notify(string notify, object info) {
} public bool OnCompilerError(Microsoft.Vsa.IVsaError error) { Console.WriteLine(error.ToString()); return true; } public void GetCompiledState(out byte[] pe, out byte[] debugInfo) { pe = null; debugInfo = null;
}
#endregion } }
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
Trent,
I haven't tested it but I suspect your problem is related to maintaining isolation between your AppDomains. The way you have written your code, the AppDomainTesting.TestEngine object is still being attached to your primary AppDomain because of the CreateInstanceAndUnwrap call (and cast) which is returning a (proxy) TestEngine object. Although it is a proxy, the primary AppDomain still attaches to the assembly as metadata is required.
To solve this, an indirection solution (yuck) where the primary AppDomain has NO knowledge of the assembly is required (class factory and invoke by interface?).
Eric Gunnerson has recently written an article on dynamic assemblies on MSDN which may help (sorry can't find the reference).
For this reason, I can't see how the AppDomain recycling scheme supplied by MS in the thread of 15 July 2002 could work. Has anyone actually managed to implement it successfully - how?
Regards, Baddabing
"Trent" <Click here to reveal e-mail address> wrote in message news:u3e06BoWCHA.436@tkmsftngp10... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Trent |
| GOOD ANSWER |
Hello Baddabing
Thanks for the ideas. I have not been successfully able to implement them yet, but I'm still trying. The link to the article you mention; (watch for word wrap)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/htm l/csharp05162002.asp
another usefully article can be found at Codeproject
http://www.codeproject.com/csharp/livecodedotnet.asp
If anybody has been successful in implementing AppDomain recycling scheme using the VSA engine please let me know
Thanks
Trent
"Baddabing" <Click here to reveal e-mail address> wrote in message news:#H9Ppw6XCHA.2652@tkmsftngp10... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Trent |
| GOOD ANSWER |
I have attached a working copy of the of AppDomain recycling scheme that I put together from the articles. hopefully this is the right way???
Trent
"Trent" <Click here to reveal e-mail address> wrote in message news:OIYfvcAYCHA.2452@tkmsftngp09... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
Trent,
Exactly - that's the idea. One point though, is that typically the interface and class factory would be created in their own DLL.
The really bad news is that you will find that memory continues to be consumed when instantiating (thats all it takes) the VB engine in a second AppDomain, even after that second AppDomain is unloaded. This is not the case for the JScript engine.
( MS - I would really like to know the cause of this VB engine unload memory issue - is it related to there being no mechanism to fully unload a domain-neutral assembly?)
This flaw I think prevents the use of the VB engine in this scenario. Microsoft, I believe, have stated that it was never intended the use of a second AppDomain solution to solve the assembly unload dilemma. The whole point of their solution is access to live objects and events which is negated by having to use a second AppDomain.
The necessity to use a second AppDomain in a compile many times scenario, and then pay the price in regards to live objects and events, means that Script for the Dotnet framework remains suitable only for a compile once/run many times scenario IMHO.
Regards, Baddabing
"Trent" <Click here to reveal e-mail address> wrote in message news:#WVWVFDYCHA.444@tkmsftngp12... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
I'm testing this application with the allocation profiler ( http://www.gotdotnet.com/userarea/filedetails.aspx?FileName=AllocationProfil er.zip ) and seems to work ok, think that GC.GetTotalMemory gives you just an estimation of the allocated heap. "Baddabing" <Click here to reveal e-mail address> escribió en el mensaje news:eaUfvkJYCHA.1732@tkmsftngp10... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
Hi JM,
This isn't a managed memory issue.
Simply instantiating the VB Engine in a second AppDomain, and then successfully unloading that AppDomain, leaves allocated system memory. As mentioned this is not visibly the case for the JScript engine or for an arbitrary assembly generated through the Reflection.Emit namespace into a non-primary domain.
On my system, creating an instance of the VB engine into a second AppDomain and unloading the AppDomain grows system memory usage by (very) approx. 4.5mb every 100 instantiations.
All I can think of, is that this is a domain-neutral assembly issue and the VSA VB code (domain-neutral assemblies statics and CLR data structures are freed on an AppDomain unload but not code) is huge or something. Seems unlikely to me, but it could be tested by implementing ones own CLR host with CorBindToRuntimeEx specifying no domain-neutral assemblies (other than mscorlib.dll).
As per my previous message I think that having to use a second AppDomain (for a compile many/run few scenario) negates the real advantages of Script for the .Net Framework (live objects and events). Furthermore, I'd hazard a guess that the script team have let out a few expletives about the CLR's inability to unload an assembly. If one could - scripting would be soooo schweeet.
But would be useful to know if anyone has implemented a VB engine AppDomain recycling scheme where system memory doesn't grow as I describe? Anyone have any other thoughts or a solution?
Regards, Baddabing
"JM Servera" <Click here to reveal e-mail address> wrote in message news:#tIchwLYCHA.3736@tkmsftngp08... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
Hi Baddabing! Thanks for your explanation. I was in the belief that the Garbage Collector will someday free the memory. As you, I'm very disappointed with having to use a second AppDomain to allow my app unloading the script. I'm developing a service that will run scheduled scripts and I need to unload them every time that they have run, so, if the service has this memory leaks then I can't put it in production... and this will not make my boss very happy. So, I'm also very interested in finding anyone who found the way to "correctly" unload the VB engine. (Actually, not only interested, I do need it). Thanks again, JM
"Baddabing" <Click here to reveal e-mail address> escribió en el mensaje news:O8JB6#PYCHA.2452@tkmsftngp11... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
JM,
I've actually been going nuts over this AppDomain issue and am about to give up. However, I believe I was wrong in stating that this is only an issue with the VB VSA engine.
My experiments lead me to now believe that continually instantiating (different each time) assemblies into a secondary AppDomain which is then unloaded, leads to a substantial increase in system memory use - recoverable only at end of process. This is the case even if interaction between the default and secondary AppDomain is limited to invoking of methods through an interface returned through a factory created instance of the assembly in the second AppDomain - i.e. the default AppDomain knows nothing about the remote assembly other than through that interface.
This doesn't really impact on generating a small number of dynamic assemblies for things like plugins, but sure does for scripting where one might want to generate and load hundreds of assemblies.
Would be really grateful if someone could show me I'm wrong?
Your project sounds interesting - is it web based?
Best regards, Baddabing
"JM Servera" <Click here to reveal e-mail address> wrote in message news:#YyPAjtYCHA.2260@tkmsftngp09... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
Hi Baddabing! My service it's planned to be a multithreaded windows service that reads scripts from a database and runs them depending on its scheduling information. As I was very upset with the memory leaks past week, I've created a simple windows service that opened up to 6 threads at a time and each one opened a database connection, with a random lifetime for every opened thread between 200 and 600 milliseconds. I've found that my service was slowly eating my system memory at about 2MB a day, even closing every thread's db connection and calling GC.Collect(). So, I've decided to let it run for some days to see if the runtime core will eat memory forever or, as it is supposed to do, it will free the unused memory when it decided that it was the time to do it. Finally, after 8 days of running, the service freed the memory and started its cycle again. It seems that the managed heap remains allocated by the system until it decides to free it. The managed allocations and GC collections are made into this heap, and we do not have any control over this one, we can free blocks of memory into it, but not the heap itself. It's something like we have to trust on the core for allocating and freeing memory depending on the system needs. The main problem is that this is not clearly explained in the documentation. I will be very interested if someone (any ms guy) can explain this behavior in a more technical fashion and tell me if I'm too optimistic. Note: I still didn't try it with a vsa vb.net engine, it was just a multithreading service test.
Greetings from Mallorca, JM
"Baddabing" <Click here to reveal e-mail address> escribió en el mensaje news:OskTnUvYCHA.952@tkmsftngp12... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Miljan Mitrovic |
| GOOD ANSWER |
I too noticed this behavior in similar surbconstances. I even made an app to "eat" the memory and service responded by freeing it's memory to accomodate outer requests. I did not try to force mem release with a 3rd party memory recoverers. Anyone?
"JM Servera" <Click here to reveal e-mail address> wrote in message news:uWcuxU6YCHA.1152@tkmsftngp10... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
Finally I've isolated the code that is leaking memory: IVSAEngine.Compile for both VB and JS engines is consuming virtual memory. My service fulfills all the requirements for AppDomain unloading (MarshalByRef, creating instances from interfaces etc...) and after three weeks of tests and profiling I'm pretty sure that the call that is eating memory is the Compile method. Every GC collection frees physical memory, but not virtual memory (under the task admin choose view->select columns and check the virtual memory option), so after about two hours of continously compiling and running scripts my virtual memory is totally full. The scripts are so simple as a Console.WriteLine, and I don't have published objects. Just commenting this standard code stops the bug: if(engine.Compile()) { try { engine.Run(); Assembly assem = engine.Assembly; Type type = assem.GetType("MyNetScript."+script.Name); MethodInfo method = type.GetMethod("Main"); try { method.Invoke(null, null); // I've tried also with (this,null) } catch(Exception ex) { Debug.WriteLine("Invoke " + ex.Message); if (ex.InnerException!=null) Debug.WriteLine("\t"+ex.InnerException.Message); throw ex; } } catch(Exception ex) { Debug.WriteLine("Engine: " + ex.Message); if(ex.InnerException!=null) Debug.WriteLine("Engine Run: " + ex.InnerException.Message); throw ex; } }
I've also tried to comment the inner code of the "if" without any luck, so, I'm sure that the method that is leaking is the "Compile" one. In any other case I've tested AppDomain loading/unloading works fine, it just begins leaking I really do need a solution or workaround for this leak.
"Miljan Mitrovic" <miljan@pexim(.dot.)co(.dot.)yu> escribió en el mensaje news:ulp0o77YCHA.2580@tkmsftngp12... > I too noticed this behavior in similar surbconstances. I even made an app to > "eat" the memory and service responded by freeing it's memory to accomodate [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
JM,
Are you sure that this is really the issue? Commenting out the compile means that the SAME assembly is continually getting loaded into a recycled appdomain. Definately no memory problems with that.
The real issue is whenever a DIFFERENT assembly is loaded (each time) into a recycled appdomain. I think you will see this behaviour with ANY dynamically generated assembly, whether through codedom or vsa.
This is the (current) .NET VSA scripting paradox - you can use scripting if you don't have to compile many scripts (or you can stop and restart the process). But then why use scripting?
What do you think - can you try it?
Baddabing
"JM Servera" <Click here to reveal e-mail address> wrote in message news:#FzY8k5aCHA.2612@tkmsftngp12... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
Ok, I'll try it. "Baddabing" <Click here to reveal e-mail address> escribió en el mensaje news:uKVOMm6aCHA.1692@tkmsftngp09... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
JM,
With your permission, I'll email you private to discuss some of these issues. Am interested to hear your thoughts.
Baddabing
"JM Servera" <Click here to reveal e-mail address> wrote in message news:#iiLQt6aCHA.1652@tkmsftngp11... [Original message clipped]
|
|
|
| |
|
|
| |
|
| |
| JM Servera |
| GOOD ANSWER |
I've tried to load different assemblies and yes, it seems to keep some memory every time. I've tried it with sdk 1.0 and 1.1 with the same result. Started wit 3.912 mem 2.808 virtual and finished with, 8568 mem and 4372 virtual for about 254 assemblies. This was my C# code... maybe buggy...
using System;
namespace Test { class Class1 { static int count=0; public static void loadModule() { try { string assemblyName=(string) AppDomain.CurrentDomain.GetData("AssemblyName"); object c=(object) System.Reflection.Assembly.LoadFrom(assemblyName); Console.WriteLine("{0} loaded in {1}",assemblyName,AppDomain.CurrentDomain.FriendlyName); } catch{} }
static void SearchDlls(string path) { foreach(string s in System.IO.Directory.GetDirectories(path)) { foreach(string file in System.IO.Directory.GetFiles(s,"*.dll")) { AppDomain p=null; p= AppDomain.CreateDomain("test"); p.SetData("AssemblyName", file); p.DoCallBack(new CrossAppDomainDelegate(loadModule)); count++; AppDomain.Unload(p); } SearchDlls(s); } } [STAThread] static void Main(string[] args) { string s=System.Environment.GetEnvironmentVariable("ProgramFiles"); System.Reflection.Assembly[] assemblies= AppDomain.CurrentDomain.GetAssemblies(); for (int i=0; i<assemblies.Length; i++) { Console.WriteLine(assemblies[i].FullName); } Console.WriteLine("Press <return> to start"); Console.ReadLine(); SearchDlls(String.Format("{0}\\Microsoft.Net\\SDK",s)); Console.WriteLine("Loaded {0} assemblies",count); assemblies= AppDomain.CurrentDomain.GetAssemblies(); for (int i=0; i<assemblies.Length; i++) { Console.WriteLine(assemblies[i].FullName); } assemblies= null; s= null; GC.Collect(); GC.Collect(); GC.Collect(); GC.WaitForPendingFinalizers(); Console.ReadLine(); }
} }
"JM Servera" <Click here to reveal e-mail address> escribió en el mensaje news:#iiLQt6aCHA.1652@tkmsftngp11... [Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
|
|
| |
| Thong Nguyen |
| GOOD ANSWER |
Wah. It's driving me nuts too. There's no way to add dynamic scripting to an application without the ability to unload a dynamically created assembly. Loading the assembly into another appdomain causes severe speed issues (and great difficulting wrt marshalling).
I hope Microsoft addresses this soon :(.
BTW, check out the DynamicJava project (http://koala.ilog.fr/djava/#overview). It supports dynamic interpretation of Java. C# needs something like this :|.
::Tum
"Baddabing" <Click here to reveal e-mail address> wrote in message news:OskTnUvYCHA.952@tkmsftngp12... [Original message clipped]
|
|
|
| |
|
|
| |
|
| |
| Peter Torr \(MS\) (VIP) |
| GOOD ANSWER |
"Baddabing" <Click here to reveal e-mail address> wrote in message news:OskTnUvYCHA.952@tkmsftngp12... [Original message clipped]
Hi,
Unless your class derives from MarshalByRefObject, the second assembly will always be loaded into your main AppDomain, which uses memory. You MUST derive from MBRO if you want to be able to unload the domain and reclaim memory. At the end of the post are 4 files you should compile:
iface.js
* defines an interface * compile with jsc /t:library iface.js
host.js
* defines a simple host app * compile with jsc host.js
byval.js
* defines an implementation deriving from Object * compile with jsc /t:library byval.js
byref.js
* defines an implementation deriving from MarshalByRefObject * compile with jsc /t:library byref.js
As you will see by running host.exe, byval prints "host.exe" as its AppDomain, whereas byref prints "bar".
Peter
-- Peter Torr -- Click here to reveal e-mail address This must be the disclaimer I waited years to read: http://www.microsoft.com/info/cpyright.htm
// ---------- iface.js ---------- package IFace { interface Test { function Test() : void } }
// ---------- host.js ---------- import IFace import System
var ad1 = AppDomain.CreateDomain("foo") var ad2 = AppDomain.CreateDomain("bar")
var ob1 : Test = ad1.CreateInstanceAndUnwrap("byval", "Ob") var ob2 : Test = ad2.CreateInstanceAndUnwrap("byref", "Ob")
ob1.Test() ob2.Test()
// ---------- byval.js ---------- import IFace import System
class Ob implements Test { function Test() { print("My AppDomain is " + AppDomain.CurrentDomain.FriendlyName) } }
// ---------- byref.js ---------- import IFace import System
class Ob extends MarshalByRefObject implements Test { function Test() { print("My AppDomain is " + AppDomain.CurrentDomain.FriendlyName) } }
|
|
|
| |
|
|
| |
| |
| Baddabing |
| GOOD ANSWER |
Peter,
The requirements you state were already met. Try modifying your application to:-
1. load an assembly into a second AppDomain 2. unload that AppDomain
Repeat the above 2 steps, a large (>100) number of times, with a DIFFERENT assembly each time. What happens to system memory on your system?
Baddabing
"Peter Torr (MS)" <Click here to reveal e-mail address> wrote in message news:eTojbQ0ZCHA.1976@tkmsftngp11... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Peter Torr \(MS\) (VIP) |
| GOOD ANSWER |
"Baddabing" <Click here to reveal e-mail address> wrote in message news:#U44np7ZCHA.2336@tkmsftngp08... [Original message clipped]
Hi,
Loading, executing, and unloading a simple assembly 500 times gave rise to a modest increase in memory. I compiled the script below into 500 assemblies, then ran them with the host code.
Initial footprint was 7,288 k Mem, and 4,460 k Virtual Mem. After looping 500 times, it was 9,396 k and 5,400 respectively. I'll pass this on to the runtime people.
How many assemblies to do you expect to be loading in real situations? How often? How big are they?
Peter
-- Peter Torr -- Click here to reveal e-mail address This must be the disclaimer I waited years to read: http://www.microsoft.com/info/cpyright.htm
// ---------- byref.js ---------- import IFace import System
class Ob extends MarshalByRefObject implements Test { function Test() { print("My AppDomain is " + AppDomain.CurrentDomain.FriendlyName) } }
// ---------- iface.js ---------- package IFace { interface Test { function Test() : void } }
// ---------- host.js ---------- import IFace import System import System.Reflection
print("Starting... press a key") System.Console.ReadLine()
for (var i : int = 1; i <= 500; i++) { var ad : AppDomain = AppDomain.CreateDomain("MyDomain" + i) var ob : Test = ad.CreateInstanceAndUnwrap("byref" + i, "Ob") ob.Test() ob = null AppDomain.Unload(ad) ad = null }
var ass : Assembly[] = AppDomain.CurrentDomain.GetAssemblies() for (var j : int in ass) print(ass[j])
GC.Collect() GC.Collect() GC.Collect()
print("Done... press a key") System.Console.ReadLine()
|
|
|
| |
|
|
| |
| |
| Peter Torr \(MS\) (VIP) |
| GOOD ANSWER |
"Peter Torr (MS)" <Click here to reveal e-mail address> wrote in message news:uI$c2uAbCHA.1712@tkmsftngp11... > I'll pass this on to the runtime people.
I'm still trying to get an answer to this one...
Peter
|
|
|
| |
|
|
| |
| |
| Rick Bullotta |
| GOOD ANSWER |
Any answer yet? Any info on mods to the VSA subsystem in .NET Framework 1.1?
Thx.
- Rick
"Peter Torr (MS)" <Click here to reveal e-mail address> wrote in message news:ulM2qLJcCHA.2112@tkmsftngp09... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Berkflow |
| GOOD ANSWER |
I have been also trying to figure out how to deal with mounting memory usage in my scripting application and wanted to at least try the AppDomain approach. However, when I create the app domain for my assembly it fails on the AppDomain.CreateInstanceAndUnwrap() call because it expects everything in it to be serializable. I made all of my classes serializable, but I need to create the VsaEngine in there (via Microsoft.Vsa.VsaLoader) and that class is not serializable, so I am not sure how other developers have managed to do this. Any ideas would be most appreciated.
- Steve
"Rick Bullotta" <Click here to reveal e-mail address> wrote in message news:eCTdJ5$sCHA.2124@TK2MSFTNGP12... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| JM Servera |
| GOOD ANSWER |
Are there any news about this Issue? There's a lot of time that nobody talks about that and we need a scripting platform for .NET. We had to use the ooooold VB ScriptControl in our .NET applications and that's not very smart... Thanks. "Berkflow" <Click here to reveal e-mail address> escribió en el mensaje news:Click here to reveal e-mail address... > I have been also trying to figure out how to deal with mounting memory usage [Original message clipped]
|
|
|
| |
|
|
| |
|
| |
| Viatcheslav V. Vassiliev |
| GOOD ANSWER |
Create a serializable wrapper class that holds VsaEngine (or other object you need) inside. Try to have minimum cross-domain calls (implement most activity in your wrapper).
Regards, Viatcheslav V. Vassiliev
"Berkflow" <Click here to reveal e-mail address> ÓÏÏÂÝÉÌ/ÓÏÏÂÝÉÌÁ × ÎÏ×ÏÓÔÑÈ ÓÌÅÄÕÀÝÅÅ: news:Click here to reveal e-mail address... > I have been also trying to figure out how to deal with mounting memory usage [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Jim Bob |
| GOOD ANSWER |
Here is some code that shows the basics - it is a C# console application hosting a VB script engine.
Also check the following article.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/htm l/csharp05162002.asp
http://www.west-wind.com/presentations/DynamicCode/DynamicCode.htm
Sorry for any word wrap.
using System; using Microsoft.VisualBasic.Vsa; using Microsoft.Vsa; using System.Reflection;
namespace Recycle { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { AppDomain engineDomain = null; System.IO.StreamWriter writer = null; try { int max = 100; if(args.Length > 0 ) max = Convert.ToInt32(args[0])+1;
string assemblyName = Assembly.GetAssembly(typeof(Recycle.ScriptEngine)).FullName; for(int i = 1; i < max; i++) { Console.WriteLine("Instance = "+i.ToString()); engineDomain = AppDomain.CreateDomain("EngineDomain",null,null); ScriptEngine engine = (ScriptEngine) engineDomain.CreateInstanceAndUnwrap(assemblyName,"Recycle.ScriptEngine"); engine.Compile(); engine.Close(); AppDomain.Unload(engineDomain); engineDomain = null; }
} catch(System.Exception error) { Console.Write(error.ToString()); } finally { if(writer != null) writer.Close(); writer = null; } Console.WriteLine("Press any key to end."); Console.Read(); } }
public class ScriptEngine :System.MarshalByRefObject { Microsoft.VisualBasic.Vsa.VsaEngine engine; private string _script; public ScriptEngine() { this._script = "Imports System\n"+ "Public Module script\n"+ "\tSub main\n"+ "\tSystem.Console.WriteLine(\"VSA Engine \")\n"+ "\tEnd Sub\n"+ "End Module"; this.engine = new VsaEngine();
engine.RootMoniker = "Recycle://script"; this.engine.Site = new VsaSiteImpl(); engine.InitNew(); engine.RootNamespace = "Test"; engine.Name = "Test"; engine.GenerateDebugInfo = false;
Microsoft.Vsa.IVsaReferenceItem systemRef= (Microsoft.Vsa.IVsaReferenceItem)engine.Items.CreateItem("system.dll",Micros oft.Vsa.VsaItemType.Reference, Microsoft.Vsa.VsaItemFlag.None); systemRef.AssemblyName = "system.dll"; Microsoft.Vsa.IVsaCodeItem scriptCode= (Microsoft.Vsa.IVsaCodeItem)engine.Items.CreateItem("main",Microsoft.Vsa.Vsa ItemType.Code,VsaItemFlag.Module); scriptCode.SourceText=this._script;
} public void Close() { this.engine.Close(); } public void Compile() { this.engine.Compile(); } public void Run() { if(this.engine.IsCompiled) { this.engine.Run(); string strNamespace = engine.RootNamespace; string FullName = strNamespace +".script"; // Get the method from the type Type ModType = engine.Assembly.GetType(FullName,true,true); string main = "main"; System.Reflection.MethodInfo method = ModType.GetMethod(main); method.Invoke(null,null);
} } } } public class VsaSiteImpl : Microsoft.Vsa.IVsaSite {
#region Implementation of IVsaSite public object GetEventSourceInstance(string itemName, string eventSourceName) { return null; } public object GetGlobalInstance(string name) { return null; } public void Notify(string notify, object info) {
} public bool OnCompilerError(Microsoft.Vsa.IVsaError error) { Console.Write(error.ToString()); return false; } public void GetCompiledState(out byte[] pe, out byte[] debugInfo) { pe = null; debugInfo = null;
}
#endregion} }
"Viatcheslav V. Vassiliev" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Berkflow |
| GOOD ANSWER |
Thanks. Got it working! Code samples are always great. Of course, this brought me to where this thread started which is that memory still leaks using AppDomains. So I started working on another way of calling the VSA engine by wrapping it in an executable. Having its own process space should guarantee the memory goes away when the app terminates. There's more overhead in this method of course, but I figure in my case, I can keep the app running on a per object basis as it runs through several scripts (this is a script based workflow app). Now the only problem I have is this - I am trying to call a method in my ..NET app by starting the app, then creating an object inside that app that I can then manipulate to load and execute scripts using .NET remoting. However, in my client code I can't figure out how to create the object since it seems you need the type of the object and I can't get the type by adding a reference since you can't reference an exe only dlls. Anyone know how to do this? Here's some sample code of how I am trying to do this. It fails when trying to get the type "MyVsaServer.WorkItem". (return value for t is null). sysProc = new System.Diagnostics.Process();
sysProc.StartInfo.FileName = "MyVsaServer.exe";
sysProc.Start();
Type t = Type.GetType("MyVsaServer.WorkItem");
System.Runtime.Remoting.ObjRef or = sysProc.CreateObjRef(t);
IWorkItem wi = (IWorkItem)or.GetRealObject(new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.S treamingContextStates.All));
---------------------------------------------------------------------------- ---------------
"Jim Bob" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
|
| |
| Stacey Blaschke |
| GOOD ANSWER |
I was wondering if this issue has been looked at and if their is a fix for the appdomain unloading memory leak. I too am working on a script engine for our app am hoping for a fix to this memory leak in the near future.
Thanks, Stacey Blaschke eEye Digital Security
"Peter Torr (MS)" <Click here to reveal e-mail address> wrote in message news:ulM2qLJcCHA.2112@tkmsftngp09... [Original message clipped]
|
|
|
| |
|
|
| |
|
|
| |
| JM Servera |
| GOOD ANSWER |
Hi Peter, I'm developing a windows service that checks for scheduled scripts every 5 seconds and runs them in a different thread each one; the number of scripts depend on the customer needs. I'm currently doing stress testing and I run many different scripts with different time periods (10, 15, 25 seconds and one once a day). After about 2 hours my memory is full. The scripts I compile and run for my tests are so simple as a Console.WriteLine, just for knowing that my script really ran.
Thanks, JM
"Peter Torr (MS)" <Click here to reveal e-mail address> escribió en el mensaje news:uI$c2uAbCHA.1712@tkmsftngp11... [Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
| |
| clintmiller@gmail.com |
| GOOD ANSWER |
I'm experiencing this same thing as well. Any ideas?
Baddabing wrote: [Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
| |
| Baddabing |
| GOOD ANSWER |
JM,
BTW thanks for the allocation profiler link - didn't know about it and it looks excellent.
Thanks, Baddabing
"JM Servera" <Click here to reveal e-mail address> wrote in message news:#tIchwLYCHA.3736@tkmsftngp08... [Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
|
|
|
|
|
|