DotNet problem.
Moderators: Lavish Software Team, Moderators
DotNet problem.
I've noticed some issues working with an a DotNet application in Vanguard. Every thing was working fine until a week or so ago. Now when I run the application, the game is unplayable. The screen starts to freeze up continuously.
After a little investigation, it appears that the DotNet interface is not retrieving information in a timely manner and running very slowly. One example is just locking the frame and getting a characters name can take less than a millisecond to over a second and a half. Way to long, especially with the frame locked.
Is this a problem with InnerSpace or the ISXVG extension? I've done some testing to get the same information directly in DotNet using the DataParse function and get the same result.
After a little investigation, it appears that the DotNet interface is not retrieving information in a timely manner and running very slowly. One example is just locking the frame and getting a characters name can take less than a millisecond to over a second and a half. Way to long, especially with the frame locked.
Is this a problem with InnerSpace or the ISXVG extension? I've done some testing to get the same information directly in DotNet using the DataParse function and get the same result.
I'm pretty sure I fixed the problem. I was running a loop that used the Thread.Sleep() function at the end of the loop to add a delay between cycles. (Yes, the frame was not locked when the thread was put to sleep, I checked.)
Anyways, removing the Sleep call and using a custom function to add the delay seems to have fixed the problem and it is running at full speed again. This method has worked fine, until recently. I'm don't know what changed.
Anyways, removing the Sleep call and using a custom function to add the delay seems to have fixed the problem and it is running at full speed again. This method has worked fine, until recently. I'm don't know what changed.
I don't really know what to tell you, people are using .NET with IS 24/7 now and individual calls are basically instant. Without seeing your code, I don't even know what help to offer you.
I don't know how the ISXVG .net API is set up either, but assuming it's using LavishScript objects and not bootstrapped API directly into ISXVG, then I can maybe offer some insight. Every call into LavishScript API will implicitly frame lock, and lock against all other LavishScript API calls (from .net). i.e. If you've got 2 threads making competing LavishScript calls, the first one of them taking 2 seconds to complete, then the other will not be executing for 2 seconds, and both calls are synchronized with the game's main thread.
Here's an old thread about seemingly poor .NET response times, that may help as well. http://www.isxwow.net/forums/viewtopic. ... 791&p=5247
I don't know how the ISXVG .net API is set up either, but assuming it's using LavishScript objects and not bootstrapped API directly into ISXVG, then I can maybe offer some insight. Every call into LavishScript API will implicitly frame lock, and lock against all other LavishScript API calls (from .net). i.e. If you've got 2 threads making competing LavishScript calls, the first one of them taking 2 seconds to complete, then the other will not be executing for 2 seconds, and both calls are synchronized with the game's main thread.
Here's an old thread about seemingly poor .NET response times, that may help as well. http://www.isxwow.net/forums/viewtopic. ... 791&p=5247
In the link you supplied, the person is doing these calls without locking the frame. In my case, I am locking the frame.
I don't have the code available to me at the moment, but I created simple test script that locked the frame, saved a few pieces of information about the character, unlocked the frame and then waited a second to repeat the process. The delay that I am seeing is when the frame is locked and that time is averaging between 200-500ms.
I don't have the code available to me at the moment, but I created simple test script that locked the frame, saved a few pieces of information about the character, unlocked the frame and then waited a second to repeat the process. The delay that I am seeing is when the frame is locked and that time is averaging between 200-500ms.
Ok, here is some more information.
The first time I run the .NET applictaion, everything works great. Re-run the same application using the same App Domain name, and the problem shows up. Re-run and and get the same problem.
Run the application using a new App Domain name and everything runs great, close and run using the same name and the problem shows up again.
Using the "DotNet -list" command the App Domain that was just used is not listed after the application is closed.
The first time I run the .NET applictaion, everything works great. Re-run the same application using the same App Domain name, and the problem shows up. Re-run and and get the same problem.
Run the application using a new App Domain name and everything runs great, close and run using the same name and the problem shows up again.
Using the "DotNet -list" command the App Domain that was just used is not listed after the application is closed.
If the delay is on the call to lock the frame, then the main thread is busy that long.
But from your description, it sounds like Inner Space thinks the AppDomain is shut down, but there's still threads running. Attach a .NET debugger after you close your app the first time, and make sure it's cleaned up like you think it is. You may need to gracefully end threads, or set Thread.IsBackground to true (which will terminate the thread).
But from your description, it sounds like Inner Space thinks the AppDomain is shut down, but there's still threads running. Attach a .NET debugger after you close your app the first time, and make sure it's cleaned up like you think it is. You may need to gracefully end threads, or set Thread.IsBackground to true (which will terminate the thread).
The Thread.IsBackground and ending the thread made no difference. Something is definitely messed up here. I'm not the only one that is seeing this problem. The .NET interface ends up running unusably slow for some reason and I'm completely at a loss as to what is going on.
See http://www.isxgames.com/forums/showthre ... 35&page=13 for a few others reporting the same issue.
These are .NET applications that have worked perfectly fine, until recently. With no change to the application in this time.
See http://www.isxgames.com/forums/showthre ... 35&page=13 for a few others reporting the same issue.
These are .NET applications that have worked perfectly fine, until recently. With no change to the application in this time.
The issue reported on that thread does not appear to be a bug. I got the bot code from Karye2 tonight and made suggestions on minor (but non-trivial) changes.See http://www.isxgames.com/forums/showthre ... 35&page=13 for a few others reporting the same issue.
But without seeing sample code for what you're claiming if it's any different, I can't really help you either.
http://www.isxgames.com/forums/showthre ... 811&page=2
is a link to the thread in question, seems the author feels something may be screwy with the framelock on vista.
is a link to the thread in question, seems the author feels something may be screwy with the framelock on vista.
An update on the issue. I went through and removed any reference to the Sleep() function as you recommended to Kayre. Everything appears to function correctly, sometimes. By sometimes, I mean that there still appears to be a bug in the API that causes the program to execute at a very slow rate making its use impossible. Similar to what Blazer said he was experiencing in the link above.
What I have done is implemented a loop at the beginning that displays a line of text to the console, polls a variable, and then displays another line of text to the console. If the read and output is done quickly (< ~500ms) I let the program run and it works great.
If the process takes longer to compete (>500ms and sometimes in the area of close to a minute) I'll abort the script and try again. If the script is allowed to run, it is unusable (Frame rate drops to about nil, response times are garbage, its just unusable).
Anything I mentioned about changing the Application Domain name helping can be ignored, as it does not with this issue. It may have helped with the problem associated with using the Sleep() function, but this slowdown occurs no matter what I have tried.
I have 3 different machines that this program is run on:
1.6GHz C2D Vista 32Bit: The slowdown is the most common on this computer and the most crippling. At times the script will have to be executed up to 10 times before it executes properly. When the slowdown is present, the script is unusable.
3.0GHz P4 Vista 32Bit: The slowdown is less frequent on this computer but the effects are just as crippling as on the computer as above.
2.4GHz C2D Vista 64bit: The problem does not appear to show any less than on the other computers, but the slowdown does not have the devastating effect that it does on the other systems. The script sometimes able to execute at a reduced effectiveness with the slowdown present.
Note: This bug also appears to have an effect on the auto-patcher program used by the ISXVG extension. On first two systems, the extension will have to be reloaded several times before the patcher will complete successfully (not crash) and load the extension properly.
What I have done is implemented a loop at the beginning that displays a line of text to the console, polls a variable, and then displays another line of text to the console. If the read and output is done quickly (< ~500ms) I let the program run and it works great.
If the process takes longer to compete (>500ms and sometimes in the area of close to a minute) I'll abort the script and try again. If the script is allowed to run, it is unusable (Frame rate drops to about nil, response times are garbage, its just unusable).
Anything I mentioned about changing the Application Domain name helping can be ignored, as it does not with this issue. It may have helped with the problem associated with using the Sleep() function, but this slowdown occurs no matter what I have tried.
I have 3 different machines that this program is run on:
1.6GHz C2D Vista 32Bit: The slowdown is the most common on this computer and the most crippling. At times the script will have to be executed up to 10 times before it executes properly. When the slowdown is present, the script is unusable.
3.0GHz P4 Vista 32Bit: The slowdown is less frequent on this computer but the effects are just as crippling as on the computer as above.
2.4GHz C2D Vista 64bit: The problem does not appear to show any less than on the other computers, but the slowdown does not have the devastating effect that it does on the other systems. The script sometimes able to execute at a reduced effectiveness with the slowdown present.
Note: This bug also appears to have an effect on the auto-patcher program used by the ISXVG extension. On first two systems, the extension will have to be reloaded several times before the patcher will complete successfully (not crash) and load the extension properly.
Have you done any profiling to determine what is actually going slow? I understand and appreciate that *something* is slow, but I have no idea what has been done by any of you to determine what the problem is, other than observing that your application seems to be running slow.
If it's a problem with the IS .NET API, it would be very specific; there's a good amount of very very good programmers using this system, and none of them are reporting problems like this. Unfortunately they also don't play Vanguard, so I can't be sure if it's actually an ISXVG problem (which I guarantee there's performance problems with, though maybe not to the extent of the problems you're reporting), or for example if it's something to do with garbage collection because ISXVG doesn't support persistent objects and therefore you guys might be using thousands of newly allocated .NET objects every frame, or if you're simply using API that they are not, and so on.
Now.. let me explain something that may or may not be relevant, and you may or may not have already known, and I'm going to also throw in some repeating myself for good measure, which you may have already known but for the completeness of this conversation I'm going to explain it anyway, so don't feel bad. Your program is running on real operating system threads, at a normal priority level. Other than synchronizing with the game's main thread when you call into nearly all Inner Space API, Inner Space is not interfering with your application or slowing it in any way. If you create a Winforms window with a rich text box in it, and have a thread adding text to it every 1 millisecond, it should run just as fast through IS than if you ran it outside of IS entirely. However, if you want to call any IS API, it will always implicitly sync with the game's main thread if you have not explicitly done so (see the Frame Locking wiki page at http://www.lavishsoft.com/wiki/index.ph ... me_Locking -- it was recently updated because what the page used to say implied something completely different about its purpose, which is no longer "to stop it from crashing" as of many months ago). For example, using InnerSpaceAPI.InnerSpace.Echo("hello") is going to wait for the main thread to be in the state reserved by the IS .NET API, which happens exactly once per frame, when the game is attempting to render. If you have active frame locks, the main thread remains in that state for as long as you have active locks, and will leave that state the moment you no longer have active locks. So, if you've got 2 InnerSpace.Echo calls back to back, and you have not explicitly locked the frame, then the total execution time is on average going to be somewhere between 1 and 2 frames in length. If you're getting 10fps, that means it could take up to 200ms just for those two echoes. And that's not a bug, mind you, that's just how it has to work. So one thing to change if you've not done so is to maximize your FPS in the game. If you are getting 60fps, your application will perform significantly better, because any frame locking could be expected to complete in 1/60th of a second (16.777 milliseconds), as compared to 1/10th of a second (100 milliseconds).
So, to reiterate or rephrase... Frame locking should ALWAYS be expected to take whatever amount of time it takes to iterate 1 frame of the game (based on your FPS). If the frame is already locked, it is instant. There is no other waiting around involved in the API, other than frame locking. Every call you do into the Inner Space API is going to implicitly frame lock. Because frame locking is expensive (again, if it's not already locked, you are expecting to wait up to 16.777 milliseconds at 60fps), you should be explicitly frame locking around entire segments of code that are not already frame locked. Certain LavishScript events are implicitly under frame lock -- for example, the OnFrame event that Inner Space fires is frame locked, because it's already running on the game's main thread (and therefore is synchronized with... you guessed it, the game's main thread). Therefore, anything inside the OnFrame event does not need explicit frame locks, and any frame locks inside OnFrame will be instant. If you put any number of InnerSpaceAPI.InnerSpace.Echo inside OnFrame, it will happen basically instantly. I recommend using a .NET-facing console though instead of echoing everything to the IS console. It's going to be much faster to not have to frame lock, much faster not to have to marshal into unmanaged code in the first place, and much faster for IS not to have to process the text. A rich edit text box or any other window can do a better job for your .NET applications than echoing to a LavishGUI console.
Now.. about your loop. I went nuts on the isxgames forum on the thread linked in the post by wired203 about needing source code to do anything about these bug reports. I can't make any assumptions about your loop, or why it should take 500ms to execute. You seem to be measuring the effects of something else entirely, if it works fine sometimes and not others. I don't know what to say about that. I gave suggestions to Blazer based on his source code, but it looks like I might have to start actually playing Vanguard just to debug .net apps for you folks.
If it's a problem with the IS .NET API, it would be very specific; there's a good amount of very very good programmers using this system, and none of them are reporting problems like this. Unfortunately they also don't play Vanguard, so I can't be sure if it's actually an ISXVG problem (which I guarantee there's performance problems with, though maybe not to the extent of the problems you're reporting), or for example if it's something to do with garbage collection because ISXVG doesn't support persistent objects and therefore you guys might be using thousands of newly allocated .NET objects every frame, or if you're simply using API that they are not, and so on.
Now.. let me explain something that may or may not be relevant, and you may or may not have already known, and I'm going to also throw in some repeating myself for good measure, which you may have already known but for the completeness of this conversation I'm going to explain it anyway, so don't feel bad. Your program is running on real operating system threads, at a normal priority level. Other than synchronizing with the game's main thread when you call into nearly all Inner Space API, Inner Space is not interfering with your application or slowing it in any way. If you create a Winforms window with a rich text box in it, and have a thread adding text to it every 1 millisecond, it should run just as fast through IS than if you ran it outside of IS entirely. However, if you want to call any IS API, it will always implicitly sync with the game's main thread if you have not explicitly done so (see the Frame Locking wiki page at http://www.lavishsoft.com/wiki/index.ph ... me_Locking -- it was recently updated because what the page used to say implied something completely different about its purpose, which is no longer "to stop it from crashing" as of many months ago). For example, using InnerSpaceAPI.InnerSpace.Echo("hello") is going to wait for the main thread to be in the state reserved by the IS .NET API, which happens exactly once per frame, when the game is attempting to render. If you have active frame locks, the main thread remains in that state for as long as you have active locks, and will leave that state the moment you no longer have active locks. So, if you've got 2 InnerSpace.Echo calls back to back, and you have not explicitly locked the frame, then the total execution time is on average going to be somewhere between 1 and 2 frames in length. If you're getting 10fps, that means it could take up to 200ms just for those two echoes. And that's not a bug, mind you, that's just how it has to work. So one thing to change if you've not done so is to maximize your FPS in the game. If you are getting 60fps, your application will perform significantly better, because any frame locking could be expected to complete in 1/60th of a second (16.777 milliseconds), as compared to 1/10th of a second (100 milliseconds).
So, to reiterate or rephrase... Frame locking should ALWAYS be expected to take whatever amount of time it takes to iterate 1 frame of the game (based on your FPS). If the frame is already locked, it is instant. There is no other waiting around involved in the API, other than frame locking. Every call you do into the Inner Space API is going to implicitly frame lock. Because frame locking is expensive (again, if it's not already locked, you are expecting to wait up to 16.777 milliseconds at 60fps), you should be explicitly frame locking around entire segments of code that are not already frame locked. Certain LavishScript events are implicitly under frame lock -- for example, the OnFrame event that Inner Space fires is frame locked, because it's already running on the game's main thread (and therefore is synchronized with... you guessed it, the game's main thread). Therefore, anything inside the OnFrame event does not need explicit frame locks, and any frame locks inside OnFrame will be instant. If you put any number of InnerSpaceAPI.InnerSpace.Echo inside OnFrame, it will happen basically instantly. I recommend using a .NET-facing console though instead of echoing everything to the IS console. It's going to be much faster to not have to frame lock, much faster not to have to marshal into unmanaged code in the first place, and much faster for IS not to have to process the text. A rich edit text box or any other window can do a better job for your .NET applications than echoing to a LavishGUI console.
Now.. about your loop. I went nuts on the isxgames forum on the thread linked in the post by wired203 about needing source code to do anything about these bug reports. I can't make any assumptions about your loop, or why it should take 500ms to execute. You seem to be measuring the effects of something else entirely, if it works fine sometimes and not others. I don't know what to say about that. I gave suggestions to Blazer based on his source code, but it looks like I might have to start actually playing Vanguard just to debug .net apps for you folks.