ChaiScript icon indicating copy to clipboard operation
ChaiScript copied to clipboard

ChaiScript vs. Alternatives

Open AndrewDavis opened this issue 6 years ago • 13 comments

Hi,

Sorry to ask this question, but I genuinely want to know: Why would I use ChaiScript over other engines, such as V8?

Edit: Besides the fact that it's like impossible to get, build, and use V8 in a basic project...

AndrewDavis avatar Dec 22 '19 23:12 AndrewDavis

Personal preference? I find ChaiScript slower than Lua, but easier to integrate and use. Aside from V8, what others are you considering?

RobLoach avatar Dec 23 '19 19:12 RobLoach

https://bellard.org/quickjs and https://duktape.org also look nice.

According to QuickJS, V8 JIT blasts all of these out the window in terms of speed.

AndrewDavis avatar Dec 23 '19 19:12 AndrewDavis

I'm personally running across this as I'm curious what the performance is of AngelScript vs ChaiScript. I really like ChaiScript, but it hasn't had much support the past two years as I understand @lefticus has been (reasonably) very focused on professional pursuits with training and cpp chat and cpp talks.

This is just idle curiosity at this point, but since this thread exists I'm curious if anyone else has looked.

Devacor avatar Jan 07 '20 01:01 Devacor

The main reason to choose ChaiScript over any of the others is the designed 100% for C++ integration. Natural cross language exception support, cross language function support, etc.

It is not the fastest and will never be. It is extremely flexible however. This is due to early design decisions.

My main reason for not focusing on it is that I spent ~10 years working on ChaiScript. I learned a lot and it was time to spend time on other things.

lefticus avatar Jan 07 '20 23:01 lefticus

I have no critique of design decisions and am actively enjoying and using ChaiScript currently. With no future roadmap however it's not unreasonable to ask what else exists.

I also have no critique of your focus on other things. I only have gratitude for all of the effort and focus you've poured into this project over the years and made completely free to anyone who wants to use it or even contribute. I anticipate I will be sticking with ChaiScript personally for the foreseeable future.

If my personal projects ever take off and I find myself independently wealthy I would be overjoyed to invest in your services for future support as well, or even just join your patreon as I value and appreciate your content. Keep up the amazing work!

I chose ChaiScript because it is a hassle free header only low effort integration. Looking at AngelScript again after it came up in one of your CppCast's reminded me why I originally avoided it, it seems to rely on non-portable assembler and is enough friction to get up and running on Android/iOS for those reasons to avoid it unless necessary. Plus I like the typeless flexibility of ChaiScript.

Build time and runtime tradeoffs may at some point force me to make different decisions, but in terms of ease of use and developer time ChaiScript is very solid.

One example of a wish-list item that showcases why having active development would be amazing: http://discourse.chaiscript.com/t/is-there-a-way-to-redefine-reload-a-type-in-chaiscript/203/23

Currently I need to write my scripts in a kinda funny way to allow re-definition of functions (it's possible but goofy). This is something that I do to allow hot-loading creature AI scripts at runtime if changes are detected in the filesystem so I can iterate on my scripts without restarting my application or completely recreating the scripting engine.

This is a creature.script file which hooks into a chaiscript registered creature class which has a registered spawn method which calls into the script, and it has a registered std::map<std::string, BoxedValue> to the operator[] so that I can assign local script driven variables as I desire:

self.spawn = fun(self){
	self["update"] = fun(self, dt){
		//Do stuff here, call out to self["move"](self); for example.
	};

	self["move"] = fun(self){
		//Do Stuff Here
	};

	self["die"] = fun(self){
		//Do Stuff Here
	};
};

I had to convert all my scripts to use this kind of prototype-driven approach instead of something like this (bear in mind this is a toy example just showing that I'd love to be able to use ChaiScript to define classes and functions, this is not complete or exactly descriptive):

//Can't do this because VoidElemental will be redefined if we re-parse this script.
class VoidElemental {
	def VoidElementalCombat(self){
		cppObject = self;
	}

	def update(dt){
		//Call move and die and so on.
	}

	def move(){
	}

	def die(){
	}

	var cppObject;
}

//The binding script could be a separate file and just focus on all the game logic in the VoidElemental class.
self.spawn = fun(self){
	self.scriptController = VoidElementalCombat();
};

self.update = fun(self, dt){
	self.scriptController.update(dt);
};

It becomes impossible to define classes or named functions if your script could ever potentially reload during gameplay. This encourages some weird patterns with callbacks being stored in variables, but maybe that's reasonable. Anyway, just wanted to call out one wish list item specifically.

Another would be a built-in method for nulling out shared_ptr variables of all types. I may just do this one and submit a pull request, but the previous issue may be out of my depth to resolve.

C++ 20 modules and so on would be super great to have support for later on down the line when it's more widely adopted to help with any amount of build time improvements (as you've said it's unclear how much that may help with in a highly templated solution.)

Anyway, thank you again, genuinely. I hope my examples above show the motivation for inquiring go beyond performance, though obviously nobody would be upset if performance improved too haha.

Devacor avatar Jan 08 '20 00:01 Devacor

I'm personally running across this as I'm curious what the performance is of AngelScript vs ChaiScript.

@M2tM Here there's some performance comparisons from various script engines with a recursive fibonacci calculation. These values are from Jul 2015, although.

https://github.com/r-lyeh-archived/scriptorium

jespa007 avatar Jan 29 '20 10:01 jespa007

I have been unable to find a way to add lua to a c++ project where you can register variables like with Chai script, is that possible with JIT for example?

n-ham avatar Feb 26 '20 13:02 n-ham

I have been unable to find a way to add lua to a c++ project where you can register variables like with Chai script, is that possible with JIT for example?

Might be a good question for some Lua peeps. I've had success with https://github.com/ThePhD/sol2 .

RobLoach avatar Feb 26 '20 17:02 RobLoach

I did a quick test and compared the is_prime.chai to angelscript and chaiscript is ~14 times slower. That's really slow.

A quick look at chaiscript reveals that

  • it interprets from AST (no bytecode)
  • abuses C++ exceptions to control program flow (return, break and continue throw exceptions)
  • collects arguments into a local std::vector per function call (heap allocation per function call with arguments)

kmar avatar Mar 03 '20 10:03 kmar

A redesign with simplicity of integration AND top performance of Chaiscript would be great.

patlecat avatar Mar 08 '20 09:03 patlecat

That's on my 10 year todo list.

It would have to drop a lot of the flexible that ChaiScript offers, like being able to dynamically add to the overload set, and having C++ and Chai share overloads.

Yes, the poor decisions made with abusing exceptions affect performance, but the ChaiScript optimizer removes many of those. The performance tests test where we know the bottlenecks are.

The thing that really affects preformance is not the lack of a byte code or the dumb abuse of exceptions, it's overload resolution.

We do type based overload resolution, with mixed C++ and ChaiScript. We have to sort the candidates for each function call and take into account existing conversions.

And we can never ever cache this data because every part of it can change. The types passed, the overloads available, and the conversions available.

I've implemented caches in the past but they always make the performance worse because I now have to manage the cache itself and know when to invalidate it.

As far as I know ChaiScript is the only non compiled language that has native support for type based overloads, and it's certainly the only system that allows you to mix and match these things between script and native code.

Do we lose this flexibility? Do we make it so once a function is called the overload set is fixed at that point? I don't know.

Jason

On Sun, Mar 8, 2020, 03:08 patlecat [email protected] wrote:

A redesign with simplicity of integration AND top performance of Chaiscript would be great.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ChaiScript/ChaiScript/issues/507?email_source=notifications&email_token=AABZGJ4ED3C2PW5MNRQDCKLRGNOCJA5CNFSM4J6N7CCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEOEQNZQ#issuecomment-596182758, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABZGJYWV5URA4KBEP7XMLLRGNOCJANCNFSM4J6N7CCA .

lefticus avatar Mar 08 '20 14:03 lefticus

I have something I want to share as I gain further experience with and generally enjoy ChaiScript:

The common use of exceptions within ChaiScript actually makes it a little harder to effectively debug the rest of the application. I state this because when you turn on "break on exception" you'll end up with lots of non-exceptional mis-casts which resolve properly, and it can easily mask where things have actually gone off the rails. I often find myself skipping forward a dozen or so exceptions until I hit the one I actually want when I encounter a real error.

I wanted to share this because it is not a performance-based gripe, but a testing related one which could inform future API internals @lefticus or others stumbling across this post might tackle!

(Again, genuinely thank you for the work, I am only commenting here because I actively use and enjoy ChaiScript.)

Devacor avatar Mar 11 '20 04:03 Devacor

@lefticus I honestly can't say what is better for this language and that depends entirely on how it is supposed to be used. If in your view the USP is "type based overloads" and you see it more being used where performance doesn't matter that much, then I guess it's already fine as it is.

If on the other hand you want less flexibility because Chaiscript is usually going to be embedded and not being used as a standalone language then the flexibility can be delegated to the C++ part without remorse and the scripting language can then shine as a fast and easy to learn way to individualize and enhance a product without the need of a developer to recompile. And if you think about where it could be used then it is in use cases and situations where the developers have chosen C++ already because it's the fastest and leanest of them all. So shouldn't the scripting language embedded into it not also follow the same principals?

Sidenote for embedding the likes of Python, Javascript and other heavy weight scripting engines: Those are usually not chosen for the above mentioned reasons but for their wide popularity and because the targeted users already know that language well. Then those advantages are traded in for speed and memory usages.

patlecat avatar Mar 11 '20 16:03 patlecat