--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
class SmallMap {
static const int MAX=32; // to be chosen carefully. Maybe 16 is optimal.
var keys=new List(MAX);
var hashCodes=new List<int>(MAX);
var values=new List(MAX);
var fallbackMap;
int currentSize=0;
int _findIndex(hashCode) {
for (int i=0, j=currentSize-1; j>=i; i++, j--) {
if (hashCodes[i]==hashCode) return i;
if (hashCodes[j]==hashCode) return j;
}
return -1;
}
_createFallback() {
print ("creating fallback!");
fallbackMap=new Map();
for (int i=0; i<currentSize; i++) {
fallbackMap[keys[i]]=values[i];
}
}
operator [](key) {
if (fallbackMap!=null) {
return fallbackMap[key];
}
int index=_findIndex(key.hashCode);
return index>=0 && keys[index]==key ? values[index] : null;
}
operator []=(key,value) {
if (fallbackMap!=null) {
fallbackMap[key]=value;
return;
}
int hashCode=key.hashCode;
int index=_findIndex(hashCode);
if (index>=0) {
if (keys[index]==key) {
values[index]=value;
} else {
_createFallback();
fallbackMap[key]=value;
}
} else if (currentSize==MAX) {
_createFallback();
fallbackMap[key]=value;
} else {
keys[currentSize]=key;
values[currentSize]=value;
hashCodes[currentSize]=hashCode;
currentSize++;
}
}
}
--
Forgot a couple of other points that I wanted to mention1) SmallMap is in fact LInkedHashMap; keys() iterator returns keys in the order of insertion. It might be handy! (Reordering last accessed kills the feature; BTW, when you reorder hashCodes, you have to reorder keys and values, too, otherwise the index is incorrect).2) In java, there's String method intern() which includes your string into static HashMap of string constants. I think this method does too much.What I'd prefer to have in dart is a method like String.xxxxx(str) [ not sure about the name] with the following description:if str is equal to some constant string, returns this constant string. Otherwise just returns str.To make it fast, dart has to be able to figure out whether str is ALREADY a constant string. e.g. str.isConstantString();
3) There's an issue already open that proposes syntax like ##arg,
which is a sugar for "arg". Might be quite handy when you create Jsons, e.gvar priceDollars=100;map.put(##priceDollars, priceDollars).It can be supported by Editor, so when you rename priceDollars to priceInDollars, it will automatically change string.
On Sun, Mar 1, 2015 at 5:18 PM, Alex Tatumizer <tatu...@gmail.com> wrote:Forgot a couple of other points that I wanted to mention1) SmallMap is in fact LInkedHashMap; keys() iterator returns keys in the order of insertion. It might be handy! (Reordering last accessed kills the feature; BTW, when you reorder hashCodes, you have to reorder keys and values, too, otherwise the index is incorrect).2) In java, there's String method intern() which includes your string into static HashMap of string constants. I think this method does too much.What I'd prefer to have in dart is a method like String.xxxxx(str) [ not sure about the name] with the following description:if str is equal to some constant string, returns this constant string. Otherwise just returns str.To make it fast, dart has to be able to figure out whether str is ALREADY a constant string. e.g. str.isConstantString();Just one comment: The Dart language doesn't have any notion of compile-time constant at runtime. At runtime, there is no feature that distinguishes an object originating from a compile-time constant expression from one originating from a "new" instantiation.
[...]
For observatory: I tried, but found the interface clunky, didn't enjoy the look and feel. Probably a work in progress. The idea is good though. Artistic quality is lacking.
@Lasse: I'm still trying to wrap my head around constant strings.If information about constness of string is lost, then GC will try to garbage-collect these strings.
Apparently (I'm speculating here), some mechanism permanently marks them as "used" on individual basis (e.g. by making static final var out of each constant string), so GC will try to collect the uncollectable in vain. And references to const strings can be all over the place, so it's quite a bit of Sisyphean work for GC, no?
> I haven't done the VM GC, so I can't say for sure how they implement it.Hesitating to ask: who implemented GC then?Another topic.In the earlier post, I claimed that performance of TypedMap is 15% worse as a tradeoff for saving memory.This is not true. TypedMap can be made faster than SmallMap, by using same device earlier employed by PigeonMap.I'd like to remind the idea. We have 16 different hash codes. We can pick octet (8 bits) from each hash code (by applying shift:(hashCode[i]>>k)&0xFF with some fixed k) There's a very good chance that all those 16 octets are different at least for one value of k.Then we take 256-byte table which maps each octet directly to index, other entries being -1. Thus we avoid linear search altogether.
I was talking about TypedMaps, where many maps share the same structure. In this case, we have 256 bytes lookup table shared by all instances of same type, that is, practically free.
Take 16 random values out of 256. What is the probability that among those you find 2 equal? Roughly, 1/2 (see http://en.wikipedia.org/wiki/Birthday_problem)
@Lasse: I'm still trying to wrap my head around constant strings.If information about constness of string is lost, then GC will try to garbage-collect these strings. Apparently (I'm speculating here), some mechanism permanently marks them as "used" on individual basis (e.g. by making static final var out of each constant string), so GC will try to collect the uncollectable in vain. And references to const strings can be all over the place, so it's quite a bit of Sisyphean work for GC, no?
Implementing compile-time constants by rewriting the program to have compile-time constant expressions instead read the value from a lazily initialized global variable (only creating the value when the variable is first read) will also create an program that is indistinguishable from the original - and it won't have any compile-time constants at all [2]. Being equivalent to not being constant is pretty much the same as "being constant isn't a detectable property of the object".
int findIndexByLinearSearch(array, value) {
for (int i=0, j=array.length-1; j>=i; i++, j--) {
if (array[i]==value) return i;
if (array[j]==value) return j;
}
return -1;
}
int findIndexByBinarySearch(sortedArray, value) {
int lo = 0;
int hi = sortedArray.length - 1;
if (hi < 0) return -1;
// looking for value in [lo..hi]
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
int diff = value-sortedArray[mid];
if (diff <0) hi = mid - 1;
else if (diff >0) lo = mid + 1;
else return mid;
}
return -1;
}