Skip to main content

News

Topic: TurboSphere (Read 190466 times) previous topic - next topic

0 Members and 3 Guests are viewing this topic.
Re: TurboSphere
Reply #375
Here, a Python script that creates basic script IFF files out of normal JS files for embedding JIT, parser, or any other engine data into.

Type ID 23 is used for raw scripts. Type ID 24 will be for zlib-compressed scripts. I'm planning on using type 127 for TurboSphere V8 data. Any other engine could also extend these files with embedded engine data, assuming they don't have ID collisions.

Bear in mind this is only for embedded engine scripts right now. This is exactly the script that creates the IFF that holds all the embedded scripts for the new graphics plugin.

My change of heart on the whole embedded scripts issue was because, after some testing, I found out (again) how costly the JS-to-C++ interface is. I still don't really like having scripts built into the engine, but it does improve performance where it cuts down on the number of native-to-script edges.
  • Last Edit: March 03, 2014, 08:26:51 pm by Flying Jester

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: TurboSphere
Reply #376

My change of heart on the whole embedded scripts issue was because, after some testing, I found out (again) how costly the JS-to-C++ interface is.


That bridge of C++ or in my case C# to JS interface is so costly that all V8 based C# wrappers I found were just too slow. The authors of those libraries say they utilize the full power of v8 and are lightning fast. But in actuality when you are running a game that loads images then calls their blit methods, it turns out to be really slow. They say it's fast since math operations and user-created objects are fast, but any native interface-exposed objects all take insane hits.

Jurassic is faster than V8 at this because it is literally C#. You code in JS, but it compiles as C#, or rather CLI, so there is no such thing as a JS-to-C# interface to worry about. It takes the same time to use a wrapped native method as it does to create your own method, theoretically.

The only reason in Jurassic why a C# exposed object is slightly slower than an in-engine object has to do with the fact that JS takes Number for it's number types whereas in C# we have int, float, double, short, byte, etc. and these things take a casting hit. Furthermore, more optimizations could be made to look up methods and things faster with better caching. Also, Jurassic doesn't do what V8 is really good at: identifying static types in a dynamic language. I did a test and in C# a for loop with a double as an incrementor is 10 times slower than an int. In the compiled Jurassic JS it seems to use doubles as the incrementor rather than knowing to use an int and stick with that. If Jurassic could identify these static hotspots it could do very well, potentially.

It also helps if I could find a way to compile the JS to file and load compiled JS straight up. It would help in only one way: faster loading times. But that's hardly a concern right now.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: TurboSphere
Reply #377
V8 can't export compiled JS. It can export parser data and some heap data, which is what I will save in the IFF files.

The JS-C++ boundary is expensive, but not hugely so. If I can limit it to one call per statement, the performance is pretty good.

Re: TurboSphere
Reply #378
I've added the ability to pass flags to V8 on the command line. Some of the flags, such as strict mode, the new Harmony 'var' implications, and the new Harmony numeric literals (which include using 0b### for binary literals) also have config flags now, available in the game.tsgm.

The syntax is:

Code: [Select]


#turbosphere --v8Option
#for instance:

./turbosphere --v8harmony_numeric_literals
#Now you can use 0b to specify a binary literal.

#or:

./turbosphere --v8max_inlined_source_size=1000 --v8type_info_threshold=50 --v8no-harmony_symbols
# disable harmony private names, require half of a function's parameters to have a stabilized type before using the high-optimizer, and allow functions up to 1000 parsed lines to be inlined.



You could use this to optimize V8's inner workings for your game, to specify language options, or help with profiling and tracking performance. V8 can even write debug and profiler info to a file.

For now, to avoid Sphere overwriting any extra engine options, my stance is that games that are aware of TurboSphere should have a tsgm file in addition to an sgm file. The sphere 1.5/1.6 compatibility system script will be automatically included if TurboSphere is run on an sgm file that does not have a version field.

The tsgm can just be a direct copy of an sgm. No extra options are needed.
  • Last Edit: March 05, 2014, 03:20:15 pm by Flying Jester

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #379
@FlyingJester

I just updated my V8 to 3.24.40 and I discovered that they changed a lot of API again. HandleScopes cant return (Close is gone), instead use EscapableHandleScope. Also String::New is gone, and everything needs isolate as parameter (Undefined(), Null(), FunctionTemplate::New(), everything). There is probably more. I think they dropped some Persistent stuff too.

Just sayin'


// Rahkiin

Re: TurboSphere
Reply #380
I know, right?

I worked out a new set of plugin tools to work with V8 3.24.

Persistents still work, but it's very difficult to make a persistent back into a handle. Did you know that you don't normally need handle scopes at all? Every script callback is implicitly in its own handle scope, and its return value (now a part of the argument parameter) is automatically passed out of it. The whole String::New thing is a good thing. There's no such thing as `plain text', and they have finally made V8 fully UTF-8 aware.

They have been talking about this for a long time. Someday soon (they've got almost all the infrastructure in place now), Persistents will be removed altogether. The whole concept of a persistent is a little strange, and they were kind of a mistake to have at all.

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #381
About the persistensts: they have been splitting them up. There is PersistentBase, and both Persistent and UniquePersistent inherit from it. The latter has some unique id stuff so you can use them in collections I think. The first one allows traits for copying, so you can actually set them. Then you can also use PersistentBase, I think. But Persistent is still there and I use it, and need it.
There is now also Eternal: it makes an object persistent for ever. Pretty cool. Using it for FunctionTemplate cache.

HandleScope was never clear to me. I am just gonna try it out. I am also going to spread Isolate everywhere and eliminate Isolate::GetCurrent() so i can have multiple isolates and contexts. There are EscapableHandleScope, that have an Escape method, like HandleScope has Close. It is just so annoying that the only source of information about what we should actually do, is the mailing list archive.

The String::NewFromUtf8(isolate,str) is indeed good (as it is good that all New() etc now require an isolate), but it is so long and messes up my code width :P. Null(isolate) and Undefined(isolate) is also less nice than Null().

I made all my tests run again. It was fun xD

Did you know they will also get rid of Handle, and only keep Local?
  • Last Edit: March 13, 2014, 10:58:17 pm by Rahkiin

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #382
Now we are talking about it:

Is there a way to do V8 stuff like creating Locals without creating a Context::Scope within scope?
Currently I think I must, and it means I have this awful piece of code that allows users of my framework to execute code within the context scope. https://github.com/joskuijpers/L8Framework/blob/master/L8Framework/Source/L8Runtime.mm#L112


Re: TurboSphere
Reply #383
You need at least one context, context scope, and isolate. You always have, it's just that there used to be one that was implicit to initializing V8. Now you need to do it all explicitly.

Also, FYI, the Isolate::GetCurrent() is deprecated, although not marked as such. That's going to be fun to work around, isn't it?

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #384

Also, FYI, the Isolate::GetCurrent() is deprecated, although not marked as such. That's going to be fun to work around, isn't it?


Blagh yes. I can eliminate it everywhere, except in all my [L8Runtime current*] spots, where I actually ask for current isolate, current context...

Do you follow the mailing list?

Re: TurboSphere
Reply #385
I read both the V8 Users and V8 Dev mailing lists all the time. It'd be really hard to use V8 and not!

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #386
Hehe yeah. I follow it since a day or two now. I used to do some trial&error and Google the ML archives & issuelists. And #v8 on freenode.net.

In my last code of L8, I eliminated every possible use of Isolate::GetCurrent() and GetCurrentContext(). I pass around Isolates everywhere. And the new L8VirtualMachine wraps an Isolate. I can also have multiple VirtualMachines at the same time, as long as each one is in a different thread (did not test this xD).
There is a way to avoid using Context::Scope. Context::Scope() does context->Enter(), and ~Scope() runs context->Exit(). You can call those yourself too. If you only ever have 1 context in 1 isolate, you could just run context->Enter() and be done with it ;)

Re: TurboSphere
Reply #387
I actually only use context and context scopes in a single file in TurboSphere, only right when the engine is started. You don't really need to manage them at all if you just pass isolates around.

  • Rahkiin
  • [*][*][*]
Re: TurboSphere
Reply #388
I still have to figure out when exactly it is necessary. But yes, V8 is much easier to use when the whole system is not event based and has a single entry point :P

Re: TurboSphere
Reply #389
The only point at which you need to wrangle contexts and context scopes is if you allow for multiple games running at once.

Although even then, as I found out by compiling TurboSphere's engine binary as a shared library when I was trying to get it working on Android, you can get away with the context handling being extremely simple. In that case you could even have it spawn a new thread for every open game, every open game would run in its own thread and have its own context and context scope.
That would be slightly wasteful, since I could theoretically have all the games run in different contexts in the same scope, and even share the threaded backends in plugins. But it would be so much more complicated.
  • Last Edit: March 18, 2014, 06:45:30 pm by Flying Jester