@Emily: why not use hasOwnProperty for contains (rather than the "in"
operator)? (and an hasOwnProperty check within "for (k in map)" loops)
Of course this would mean that get() could return a non-null value
while contains() for the same key returns "false"...
That's what the weird test in "put" is for, as the current working hypothesis is that removing all keys that appear in the prototype object will prevent this problem. I went through and tested a bunch of them, so it seems solid, but only time will tell if all the browsers/random word combinations are licked. This is one of the reasons these classes are going into incubator rather then gwt to begin with.
If you're willing to rely on an implementation detail like this, the
identity hashCode value of an object is based on a per-module counter.
You could use this in web mode, and in hosted mode, just delegate to
an IdentityHashMap.
--
Bob Vawter
Google Web Toolkit Team
-Ray
I don't think it's one-to-one comparable with either identity or normal equality maps, as the definition of when two keys are equal will solely rely on the underlying JavaScript interpretation of the keys, and that will be done using the fastest semantics we can get. So for strings it is equality based, as that is how the underlying JavaScript API treats their strings, but for user class objects it will be identity based, as the fastest way for us to index them is via a extended property added to the object.
Iteration is an interesting question I was planning to punt on until the design was more stable, as I don't believe we can truly answer that question without having the basic implementation nailed down.
I don't think it's one-to-one comparable with either identity or normal equality maps, as the definition of when two keys are equal will solely rely on the underlying JavaScript interpretation of the keys, and that will be done using the fastest semantics we can get. So for strings it is equality based, as that is how the underlying JavaScript API treats their strings, but for user class objects it will be identity based, as the fastest way for us to index them is via a extended property added to the object.
I guess for me the big question is what is trying to be accomplished here. With overlay types, it is pretty trivial to get "bare metal" JS maps, so it seems that this should be something more, with abstractions to make it more "Java-like" while not adding things which make it inefficient. I think it might be worthwhile to preserve Java equality semantics here by using the hash code as the key into the JS map, and managing collisions there. Something like:
map = {hash1: [obj1, obj2, obj3], hash2: [obj4], hash3: [obj5, obj6]}
That also gets you away from worring about keys colliding on different (or future) browsers, and you preserve Java equality semantics. Lookup should still be O(1) since hopefully collisions are rare, iteration is quick, etc. If a hash function is slow, it would be up to the hash function writer to cache the result in the object as is already best practice, rather than the Map implementation doing that automatically for them.
One other suggestion -- I think rather than optimizing lots of puts in a row you want to allow a JSO to be passed to initialize the map. From my experience, simply having all the put calls is slow and takes up more space in the generated JS -- the primary way I improved NumberFormat's startup performance was by simply building a JSO directly with the data I needed rather than doing a bunch of puts into a map. So, for the users that will care abouot this, I think passing in a JSO to initialize the map will be a better choice.
--
John A. Tamplin
Software Engineer (GWT), Google
The benchmarks are somewhat interesting, as it turns out that memory allocation from one can serious screw up the others. Therefore here I've included each variant as separate benchmarks posted on the JsMap wiki page.
Are you having trouble with the patch? The benchmark used is included in it. The benchmark varies by the number of puts and gets, so 500 = 500 puts + 500 gets, so would have been suprised to see sub-linear time.
IE is the primary motivator for this set of changes, as it has the slowest JS system and is most sensitive to memory constraints, so the IE benchmarks are the ones I am focusing on.
Anyway, my main point is that someone just looking at the Wiki isn't going to know what it means so there should be additional text describing what those charts are -- sorry I wasn't more clear.
IE is the primary motivator for this set of changes, as it has the slowest JS system and is most sensitive to memory constraints, so the IE benchmarks are the ones I am focusing on.
That's fine, but it would be helpful to know that there isn't some issue on the other browsers. As an example, remember the pathological case of arrays on Safari when the index exceeds a certain threshold.
--
John A. Tamplin
Software Engineer (GWT), Google
This is not a complete review, but some initial feedback:
- Shouldn't the selenium changes be part of a separate patch? Regardless, Freeland or Eric would be better to review that portion.
- Did you read the GWTC threads about trying to do this in GWT 1.4? The consensus was that it was not safe to rely on being able to remove all properties, and that even if it were possible it would be fragile to future browser changes (the second thread has a test HTML file, though it is missing __proto__). I think you will need to rely on a prefix, just as we do in FastStringMap. At there very least, you should include "__proto__", "prototype", "constructor", "toString", "watch", "unwatch", and "valueOf" in your test. An alternative would be to not attempt to clean up things like that and simply document that no JS-defined property can be used in the string, though that seems problematic.
- Are you sure the complexity regarding a separate hosted-mode implementation is justified? Aside from more opportunities for errors, it means two separate implementations are not tested to be exactly the same, so any holes in the tests are an opportunity for divergent behavior in hosted mode.
- Missing newlines at the end of all the .gwt.xml files.
--
John A. Tamplin
Software Engineer (GWT), Google
Yep, that was already committed to gwt-incubator trunk, the patch is older then the commit.
- Did you read the GWTC threads about trying to do this in GWT 1.4? The consensus was that it was not safe to rely on being able to remove all properties, and that even if it were possible it would be fragile to future browser changes (the second thread has a test HTML file, though it is missing __proto__). I think you will need to rely on a prefix, just as we do in FastStringMap. At there very least, you should include "__proto__", "prototype", "constructor", "toString", "watch", "unwatch", and "valueOf" in your test. An alternative would be to not attempt to clean up things like that and simply document that no JS-defined property can be used in the string, though that seems problematic.
What code are you looking at? I'm not removing any properties and already testing watch.
- Are you sure the complexity regarding a separate hosted-mode implementation is justified? Aside from more opportunities for errors, it means two separate implementations are not tested to be exactly the same, so any holes in the tests are an opportunity for divergent behavior in hosted mode.
Did you have a chance to run the benchmark I sent you?
- Missing newlines at the end of all the .gwt.xml files.
Our gwt.xml are supposed to have an extra new line at the end of them?
Ok, so I should ignore that, right?
- Did you read the GWTC threads about trying to do this in GWT 1.4? The consensus was that it was not safe to rely on being able to remove all properties, and that even if it were possible it would be fragile to future browser changes (the second thread has a test HTML file, though it is missing __proto__). I think you will need to rely on a prefix, just as we do in FastStringMap. At there very least, you should include "__proto__", "prototype", "constructor", "toString", "watch", "unwatch", and "valueOf" in your test. An alternative would be to not attempt to clean up things like that and simply document that no JS-defined property can be used in the string, though that seems problematic.
What code are you looking at? I'm not removing any properties and already testing watch.
The JsMap.patch you sent (I duplicated watch, but the others don't appear to be tested). In particular, __proto__ was determined to be the showstopper before.
- Are you sure the complexity regarding a separate hosted-mode implementation is justified? Aside from more opportunities for errors, it means two separate implementations are not tested to be exactly the same, so any holes in the tests are an opportunity for divergent behavior in hosted mode.
Did you have a chance to run the benchmark I sent you?
Not yet, but the performance in OOPHM is not terribly relevant since this will be in long before OOPHM is.
- Missing newlines at the end of all the .gwt.xml files.
Our gwt.xml are supposed to have an extra new line at the end of them?
Every line should be terminated, but here the last one isn't.
--
John A. Tamplin
Software Engineer (GWT), Google