Thank you cag, this is quite an interesting post!
Quote:
Good idea for a topic
Thank you
Quote:
but it will need to a) be made sticky
Done. Thank you another_commander
Quote:
and b) moderated (ie. edit/modify/delete posts). This has been tried before but after a few pages of off topic discussion, I usually give up on it.
Ok, I'll edit the first post to include all incoming information, up until the time this post is too big. Then (or sooner) I'll move it to the wiki.
I won't moderate the posts of others, because:
a) I'm no moderator,
b) shame would kill me
Quote:
You've got some good ideas but we need across the board adoption to really impact frame rate. I believe much of our frame rate deficit can be restored if we all can avoid these pitfalls.
Interesting. I thought about improving the most costly oxps, but you're right, the way to go is to promote the existence of an ideal framerate goal.
This means we need to profile, in terms of framerate.
Done.
Quote:
Remember who your audience is, mostly, self-taught neophytes and expand a bit on some of your points:
- what's a singleton?
- compile a regexp? cool, but how?
- native obj-c oolite objects? in english, please, with maybe an example
- is there really a OnFrameCallback function? where's it documented?
You get the idea. The last thing we want to do is send a newbie on a wild goose chase; (s)he may not come back.
Right. I'll edit these points.
- Singleton: ToBeDefined =>
Done
- compiling a regexp: ToBeDefined
- native obj-c oolite objects: ToBeDefined =>
Done
- onFrameCallback function: ToBeDefined =>
Done
Quote:
We also need a small collection of model scripts for authors to emulate. Documentation is boring (and in oolite's case, quite terse), so often people look at other scripts to see how something is done. So these problems are copied in the belief they are correct (the oxp is popular, the author has published many oxp's, etc)
As a first one, I propose my Diplomacy OXP.
Done.
It's already optimized for performance, and is written by a pro dev (ok, not a pro javascript dev, you'll have to be happy with a java dev).
If it is found imperfect in some ways (about which I have no doubt, it is perfect), I'll be happy to improve it.
Quote:
Finally, we're going to have to deal with the orphaned oxp's, whose authors are no longer around. Compile a list, recruit people to re-code, proof and test. See what you started!
I've got no shame, and I've got you

!
Quote:
- never use 'delete' - it's not doing what you'd expect. In shipWillDockWithStation, I see a lot of
Code:
if( isValidFrameCallback( this.x) ) {
removeFrameCallback( this.x);
delete this.x;
}
where the last line just needs to be
Code:
this.x= null;
If that's the only reference, garbage collection will do the rest. The delete command removes the property 'x' from the script's object, is an expensive op and not necessary. (esp. if you do 'x= addFrameCallback(...)' in shipWillLaunchFromStation)
ToBeInserted
Quote:
I have a problem with your use of the term 'closure'. I've just realized serious frame rate gains by using closures, but of course, we're talking about 2 different things. As I understand the term, a closure is a persistent local environment that JavaScript creates
only when you return an inner function. Consider the following:
Code:
this.$uservar = 5;
this._func = function() {
if( this.$uservar < 0 )
this._do_this();
else
this.$uservar = this._do_that();
}
This is costly because of fetching this.$uservar at least once/call. Many oxp's have user setting like this, which only change when the script is editted. By using a closure, you only need fetch this.$uservar once/game, like this:
Code:
this.$uservar = 5;
this.startUp = function() {
this._func = this._setup();
...
}
this._setup = function() {
var dothis = this._do_this;
var dothat = this._do_that;
var user_var = this.$uservar;
func = function() {
if( user_var < 0 )
dothis();
else
user_var = dothat();
}
return func;
}
So, the propertyGet for this.$uservar is only done once, in startUp, and stored locally in user_var for the rest of the game. As you can see, this also works with functions
as well as any data that passed by reference, like arrays. BUT great care is warranted, lest screwy bugs appear, when dealing with global data! Avoid global data until you have a good understanding of this. However, debugging is more difficult as user_var is not available via the debug console, so I'd advise leaving this step until after you've got the code well developed.
I've also been able to combine this with your 'deference' advice by grouping functions that use the same properties into a single closure.
I may not have used the closure word in exactly the correct way.
ToBeChecked
Having grokked for this (
https://stackoverflow.com/questions/180 ... javascript ), I'll now use it as meaning (a function + an external environment).
Closures are necessary, and better than some other alternatives. I only say they must be avoided when possible.
I don't use the debug console, so...
Quote:
Functions calls aren't as costly as some of those other things but your advise valuable for a different reason, what I like to call (read scream) the GDERM bug (feature?).
It roughly stands for 'Gosh Darn Event(handler) Return Maybe' bug. Unlike interrupt handlers, event handler sometimes don't return to where they so rudely elbowed their way into your code's execution. In figuring this out (don't ask), it appears oolite respect function boundaries (ie. it'll wait until your return statement to butt in). My point is, if you have many short functions vs. a few larger ones, you're more apt to encounter this little gem. You'd think this would only occur amidst a flurry of events but it can happen in a relatively tame environment.
-----
"use tco to avoid recursion" should read "avoid recursion". Seriously.
Well, yes.
The reason I didn't implement tco was I got rid of recursion.
ToBeIncluded
Quote:
I'm with Astrobe wrt minification, even if there was a small performance gain. The minified code would be unreadable, so you'd have a source folder to your oxp. Remember, under our licences, we're allowed to steal share code.
This is what I have in mind: a source folder in the oxp.
Quote:
re: alternative to onFrameCallback()
It's an interesting solution, but according to our wiki, Timer's interval "will be rounded up to 0.25". Is that no longer true?
You can dynamically allocate callbacks but it's of limited use as it can take a handful of frames to take effect; if your list is static and you have, say, 20+ items and want to do 4/frame, it works fine. But if your list is changing and you want to scale the processing rate to measured performance, not so much.
Another way I've done it is a generalized version of the 'chunk' function in your link: functions needing items processed push their request onto a stack while a frame callback checks the stack and executes a set number of them. I still haven't figured out how to vary the number to match the hardware. If I observe a slow frame rate, is it a slow machine or a fast machine over-tasked by oxp's ...
Yes, I've seen that, too. Yet I wanted to document this solution in case it went useful, probably because it would be less costly than a call each frame.
I currently implemented a counter in the frame callback, so as to act only each 10 frames. I thought to make this number variable depending on the time needed to execute tasks. Not done anything yet, as it would be premature optimization.
Quote:
- put everything that can be calculated at load time outside of functions
eg. this.$FORTYFIVE_DEGREES = 45 * Math.PI / 180;
but not: this.$CORRECT_FOR_WIDESCR = oolite.gameSettings.gameWindow.height / oolite.gameSettings.gameWindow.width;
ToBeIncluded
Quote:
On a lighter note, anything you scoop will turn hostile and target you, including cargo pods and splinters!
Also, a spawned entity has isVisible set to true, regardless of distance. It will change to false but I don't know how long that takes.
I beg your pardon

?