5 ms·
Squirrel is roughly similar (in the grand scheme of things) to Lua and JavaScript, with more of a (C++-style) OO flavor. Its main selling point is that it uses
by throwawaymylife 11y ago
Squirrel is roughly similar (in the grand scheme of things) to Lua and JavaScript, with more of a (C++-style) OO flavor. Its main selling point is that it uses reference counting instead of a tracing garbage collector for automatic memory management. With a reference counted language, you pay a small but predictable cost every time something goes out of scope, whereas tracing garbage collectors coalesce all of these small costs into one big collection cycle run every few milliseconds. The tradeoff is that while garbage collected languages provide better throughput (due to cache effects, heap fragmentation, etc) for batch processing jobs, reference counted ones are much more suitable for realtime and soft realtime applications that would much rather take a constant factor hit to throughput if it eliminates the danger of a multi-millisecond GC scan causing the application to miss a deadline.
As such, Squirrel enjoys some popularity as (and was indeed created to serve as, by an engineer that had grown frustrated with the experience of embedding Lua in FarCry) a scripting language for video games, being most notably used in some of Valve's newer games, like Left 4 Dead 2, Portal 2, and CS:GO. The rest of the engine code usually dwarves the performance impact of "scripts" in most games, but GC scans can still cause games embedding other scripting languages to miss a frame presentation deadline, resulting in either a nasty tear or a completely missed frame. There are ways that tracing garbage collected languages can attempt to combat this (like incremental GCs), but some engine programmers have decided to accept the throughput cost for the peace of mind that reference counting provides.
EDIT: I had more but HN is silently ignoring some of my edits for some reason. Is there a post length restriction for new users, or have I tripped some kind of bizarre content filter?
- emodendroket 11y agoI see. That's interesting; I think the page could do more to explain it.
- throwawaymylife 11y agoI agree. With embedded "scripting" languages, you have to differentiate between two kinds of users that don't always (or even usually) overlap: the people writing the scripts (who may or may not even consider themselves to be programmers), and the engine programmers embedding the language in their game engine or other application. IMHO, the current homepage isn't really doing a great job of appealing to either group, and it'd be much more effective if it directly explained the advantages of its implementation to the engine dev crowd; that might alienate the script programmers a bit, but thinking about AAA game development, they're almost never the ones that get to pick the language anyway.
- nanofortnight 11y agoIt's primary advantage over Lua is definitely it's better realtime guarantees.
- codexon 11y agoReference counting is not a complete GC solution, it does not collect circular references which happen quite often. That is why python will occasionally run a mark and sweep GC even though it says it uses reference counting.
- 1morethrowaway 11y agoIt's good enough by itself if you tell programmers not to create circular references and explicitly use weak references if they really need to. That opens you up to memory leaks from accidental circular references, of course, but again, it's a worthwhile tradeoff for many projects.
- codexon 11y agoWhen you have a scripting language with a GC you are targeting a class of users who can't or don't want to be careful enough to prevent circular references. Circular references aren't easy to avoid, sometimes there can be more than 3 levels of indirection. The mental overhead of preventing circular references is often times as high as manually managing memory yourself. If it was as good as you suggest, every new language would be using reference counting and not occasionally run mark and sweep.
- david-given 11y agoRegarding 'small but predictable cost'... that's not entirely true. In an earlier life I worked on an object-oriented operating system based around reference counting, called intent (you won't have heard of it), and it was horrible. One of the major issues with refcounting is that when you dereference an object, it may be freed then and there... which dereferences any dependent objects... which may be freed... which dereference more objects, etc. So any time you dereference your object, you may end up doing an arbitrary amount of work, which isn't good for real-time performance. You can usually avoid this by being sensible about when you reference and dereference objects, but now you're effectively doing manual memory management, which slightly defeats the whole point of the exercise. In our case, we also cocked things up with poor design --- we ended up reffing and dereffing objects a lot, which meant we constantly ran into issues where we needed to deref an object with a lock held, which isn't a good idea. A better designed system wouldn't have done this. Objective C's memory pools work very well: whenever you create an object it gets added to a list, and all objects on the list are dereffed when your app exits to the event loop; so not only do you only need to manually ref objects if you want to keep them until the next event, which is much easier to code for, but the object free overhead all happens at a well-defined point which is usually app idle time. So while reference counting can help, it still doesn't make the problem go away, and when you're using it you have to remember that you are using it and ensure that your app is designed to cope. (It's also worth remembering that modern incremental garbage collectors solve the same problem in a different way, and without some of refcounting's problems.)