JavaScriptCore merge & binary compatibility
Maciej Stachowiak
mjs@apple.com
Mon, 17 Feb 2003 16:15:38 -0800
On Sunday, February 16, 2003, at 07:51 AM, Harri Porten wrote:
>
> In regards to API changes I'm still a bit more hesitant than just BIC
> changes.
I have some specific comments about these changes. But before going
into specifics, I'd like to say a few words about the general approach.
When deciding whether a particular API change is worthwhile for
performance, or which of several alternatives is better, it is
essential to measure the real effect on performance. For Safari we have
been very careful to justify all our changes using both examples from
real-world pages and from artificial benchmarks.
I would like JavaScriptCore to track the mainline kjs as closely as
possible, so it would be great if we could come up with a shared
methodology for measuring performance, and use that to make decisions.
That way, we'd be able to make the right choices to get excellent
performance for both Konqueror and Safari .
(I also wrote to Harri and Peter off-list about setting up a shared way
of measuring performance).
> The most dramatic one will be the use of Identifier rather than
> UString in the extension API but a fallback virtual function should be
> possible so that old code will keep compiling.
I think the Identifier change has been a very important performance
win, so I hope your fallback approach works. It greatly reduces both
string compares
> When it comes to Apple's optimized storage of Numbers I would still
> like
> to present the approach taken in QSA first. It allows for more types
> to be
> stored more efficiently without coding any special excemptions.
I think it is a good idea to consider other approaches, and measure the
results. However, based on some past measurements and my personal
intuition, I think the SimpleNumber approach is very worthwhile, and
may work even better in combination with your approach of using a
union. Here is some information you may find useful:
- A while back, I instrumented KJS to count total JS ValueImp
allocations of various types, and tried it on a particular suite of
real-world JS-intensive web pages. I found that out of the 1 million
total allocations over the course of the test, half were NumberImps.
From my background with Lisp, I knew of a technique for storing small
integers inside the pointer for a GC-based system; to test it out I
measured how many of the numbers allocated were integers that would fit
in a 30-bit signed value. I found that this was true of nearly all of
them. This is because most numbers used in a web page are either array
indexes or screen coordinates. So by doing the "number in the pointer"
optimization, we cut the number of allocations in half, and got nearly
all the possible win of the more complex approach for numbers.
- On the other hand, the JavaScript iBench does a lot of math with real
floating-point numbers, and keeps them in arrays. It would be nice to
avoid allocating for this case, and I believe the fancier union-based
approach can help with that.
- The SimpleNumber optimization has the advantage that you can store a
small number anywhere that a ValueImp * goes, without increasing the
storage requirements, or changing the API. With the new GC, it is
especially important to keep objects as small as possible, so they fit
within the cell allocator threshold. I don't know what the QSA approach
for this is exactly, but I assume the union only goes in Value, and
does not help places that store a ValueImp directly (like arrays or
property maps), or that every place that might store a ValueImp
directly instead stores the union. I don't think either of these is the
best approach.
Based on all this, I think a hybrid approach might be the best of all.
SimpleNumber would still exist and be stored directly in a ValueImp *
using special bits inside the pointer, so small numbers could always
avoid allocating, no matter what you do with them. The union would go
inside a new class, called something like ValueRep. A ValueRep would be
stored directly inside a union, but could also be stored in other
places where it is important to avoid allocating. For example, the
non-sparse part of Arrays, and perhaps even values in property maps
could be stored as ValueRep, allowing floats to be stored there without
allocation.
Can you give me access to the union-based code so I can make some more
informed remarks?
In any case, I think we should decide what to do (number-in-pointer
only, union only, or some combination of both), based on measurement.
Regards,
Maciej