stinkypete
Au is indeed useful, but not so much as nearly indicated by its current pricing. There's a _long_ history of human predilection for gold-as-a-magical-substance versus gold-as-an-industrially-useful-element.
Another benefit is that since the data structures are immutable you can easily operate over snapshots of them with no worries as to what other threads are doing. This can make them easier to code against and can sometimes be much easier to deal with than locks since you avoid most deadlock/livelock problems that you usually have to worry about with locking, though if you're using straight-up CAS you do have to be mindful of the A-B-A problem.
day count = [last 23 hour buckets] + hour count
hour count = [last 59 minute buckets] + minute count
minute count = [last 59 second buckets] + second count
second count = <running count cleared every 1 second>
You end up losing a small amount of accuracy, the worst being for keeping track of the second counts. You can avoid that by using an actual list of counter values for the seconds bucket and dumping those out when they get older than a second, or maybe by introducing another subdivision -- 1/10th of a second probably is good -- so that you actually have .9 seconds worth of data and can interpolate the last bit.If you're to the point where you are editing lots of multiline expressions you may want to consider using an editor that has a function that will send the contents of a buffer or the current expression to a running interpreter. Emacs is an obvious choice for this, but there are lots of plugins to other editors/IDEs that do the same.
We are able to do this, because starting our LISP-VM and doing all these processes on every
request, is still many times faster that having a VM (with a garbage collector) online all the time.
Self-made LISPs usually aren't that complicated to write, and if you're taking shortcuts like preallocating chunks of memory rather than writing a full-blown VM GC system, then things become even easier. My guess is that most of the LISP code doing the data analysis is composed of calls into primitives written in C that do all the heavy lifting so the performance hit of an interpreted or bytecode-interpreted language is minimal.Having to maintain a small LISP interpreter in C is definitely an extra thing to keep up with, but you have to balance that with the work that would normally go into avoiding long GC pauses once you start tracking a nontrivial amount of objects/data in a VM with garbage collection. Java, for instance, doesn't support separate heaps, which means that a background piggy processing thread that is haphazardly allocating objects can cause "core" threads doing I/O to pause for several seconds for full GCs. Even with Java's fairly sophisticated heap management schemes it is still very difficult to design a system to completely avoid full GC pauses. Erlang is somewhat better in this respect but introduces its own sets of problems to the mix.
In any case, I agree with your sentiment (probably would not be the angle I would have taken), but I can kind of see why the authors might have decided to go this route.
edit: formatting fixes
And while I don't think audiophiles are just about spending money to impress friends, sometimes they go about things in incredibly inefficient ways and pretend they are not susceptible to placebo effects.
This tweak to B-trees to support fast insertions works so well I am really surprised it has not become more common in practice. The only downside I can think of is that flushes down the tree when internal buffers get large may cause lower-level pages to become overfull, but if you allow more than one flush operations at each level you can avoid this problem. Of course, that's only important if you are paranoid about internal nodes actually fitting in a page; if you don't care about that, then the worst-case analysis picture looks much better since a flush operation causes at most one flush in the pages immediately below it in the tree structure.
How are fractal trees different?