forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use a perfect hash map for the registry controlled domain service.
On my very fast machine, building the std::set in release mode on startup and blocks the UI thread for 15ms (there are > 3300 entries). It also uses 275KB of memory, not including 50KB of data in the dll. Using a perfect hash map, there's no startup cost. The dll's size increases by 135KB but there's no extra memory consumption, leading to a memory reduction of 140KB. Review URL: http://codereview.chromium.org/515001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35196 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
jam@chromium.org
committed
Dec 23, 2009
1 parent
f09bc4e
commit 4fa642f
Showing
11 changed files
with
18,583 additions
and
3,927 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/* C++ code produced by gperf version 3.0.3 */ | ||
/* Command-line: gperf -a -L C++ -C -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test1 -D effective_tld_names_unittest1.gperf */ | ||
|
||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ | ||
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ | ||
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ | ||
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ | ||
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ | ||
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ | ||
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ | ||
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ | ||
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ | ||
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ | ||
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ | ||
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ | ||
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ | ||
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ | ||
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ | ||
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ | ||
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ | ||
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ | ||
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ | ||
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ | ||
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ | ||
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ | ||
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) | ||
/* The character set is not based on ISO-646. */ | ||
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." | ||
#endif | ||
|
||
#line 1 "effective_tld_names_unittest1.gperf" | ||
|
||
// Copyright (c) 2009 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that | ||
// can be found in the LICENSE file. | ||
// Test file used by registry_controlled_domain_unittest. | ||
// We edit this file manually, then run | ||
// gperf -a -L "C++" -C -G -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test2 -Hhash_test1 -Wword_list1 -D effective_tld_names_unittest1.gperf > effective_tld_names_unittest1.cc | ||
// to generate the perfect hashmap. | ||
#line 10 "effective_tld_names_unittest1.gperf" | ||
struct DomainRule { | ||
const char *name; | ||
int type; // 1: exception, 2: wildcard | ||
}; | ||
|
||
#define TOTAL_KEYWORDS 8 | ||
#define MIN_WORD_LENGTH 1 | ||
#define MAX_WORD_LENGTH 11 | ||
#define MIN_HASH_VALUE 1 | ||
#define MAX_HASH_VALUE 16 | ||
/* maximum key range = 16, duplicates = 0 */ | ||
|
||
class Perfect_Hash_Test1 | ||
{ | ||
private: | ||
static inline unsigned int hash (const char *str, unsigned int len); | ||
public: | ||
static const struct DomainRule *FindDomain (const char *str, unsigned int len); | ||
}; | ||
|
||
inline unsigned int | ||
Perfect_Hash_Test1::hash (register const char *str, register unsigned int len) | ||
{ | ||
static const unsigned char asso_values[] = | ||
{ | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 0, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 0, 0, 0, | ||
17, 5, 0, 17, 17, 17, 0, 17, 17, 0, | ||
17, 0, 0, 17, 0, 17, 17, 17, 17, 17, | ||
17, 17, 0, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
17, 17, 17, 17, 17, 17 | ||
}; | ||
register int hval = len; | ||
|
||
switch (hval) | ||
{ | ||
default: | ||
hval += asso_values[(unsigned char)str[10]]; | ||
/*FALLTHROUGH*/ | ||
case 10: | ||
hval += asso_values[(unsigned char)str[9]]; | ||
/*FALLTHROUGH*/ | ||
case 9: | ||
hval += asso_values[(unsigned char)str[8]]; | ||
/*FALLTHROUGH*/ | ||
case 8: | ||
hval += asso_values[(unsigned char)str[7]]; | ||
/*FALLTHROUGH*/ | ||
case 7: | ||
hval += asso_values[(unsigned char)str[6]]; | ||
/*FALLTHROUGH*/ | ||
case 6: | ||
hval += asso_values[(unsigned char)str[5]]; | ||
/*FALLTHROUGH*/ | ||
case 5: | ||
hval += asso_values[(unsigned char)str[4]]; | ||
/*FALLTHROUGH*/ | ||
case 4: | ||
hval += asso_values[(unsigned char)str[3]]; | ||
/*FALLTHROUGH*/ | ||
case 3: | ||
hval += asso_values[(unsigned char)str[2]]; | ||
/*FALLTHROUGH*/ | ||
case 2: | ||
hval += asso_values[(unsigned char)str[1]]; | ||
/*FALLTHROUGH*/ | ||
case 1: | ||
hval += asso_values[(unsigned char)str[0]]; | ||
break; | ||
} | ||
return hval; | ||
} | ||
|
||
const struct DomainRule * | ||
Perfect_Hash_Test1::FindDomain (register const char *str, register unsigned int len) | ||
{ | ||
static const struct DomainRule wordlist[] = | ||
{ | ||
#line 21 "effective_tld_names_unittest1.gperf" | ||
{"c", 2}, | ||
#line 15 "effective_tld_names_unittest1.gperf" | ||
{"jp", 0}, | ||
#line 22 "effective_tld_names_unittest1.gperf" | ||
{"b.c", 1}, | ||
#line 16 "effective_tld_names_unittest1.gperf" | ||
{"ac.jp", 0}, | ||
#line 17 "effective_tld_names_unittest1.gperf" | ||
{"bar.jp", 2}, | ||
#line 18 "effective_tld_names_unittest1.gperf" | ||
{"baz.bar.jp", 2}, | ||
#line 20 "effective_tld_names_unittest1.gperf" | ||
{"bar.baz.com", 0}, | ||
#line 19 "effective_tld_names_unittest1.gperf" | ||
{"pref.bar.jp", 1} | ||
}; | ||
|
||
static const signed char lookup[] = | ||
{ | ||
-1, 0, 1, 2, -1, 3, 4, -1, -1, -1, 5, 6, -1, -1, | ||
-1, -1, 7 | ||
}; | ||
|
||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) | ||
{ | ||
register int key = hash (str, len); | ||
|
||
if (key <= MAX_HASH_VALUE && key >= 0) | ||
{ | ||
register int index = lookup[key]; | ||
|
||
if (index >= 0) | ||
{ | ||
register const char *s = wordlist[index].name; | ||
|
||
if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') | ||
return &wordlist[index]; | ||
} | ||
} | ||
} | ||
return 0; | ||
} | ||
#line 23 "effective_tld_names_unittest1.gperf" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
%{ | ||
// Copyright (c) 2009 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that | ||
// can be found in the LICENSE file. | ||
// Test file used by registry_controlled_domain_unittest. | ||
// We edit this file manually, then run | ||
// gperf -a -L "C++" -C -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test1 -D effective_tld_names_unittest1.gperf > effective_tld_names_unittest1.cc | ||
// to generate the perfect hashmap. | ||
%} | ||
struct DomainRule { | ||
const char *name; | ||
int type; // 1: exception, 2: wildcard | ||
}; | ||
%% | ||
jp, 0 | ||
ac.jp, 0 | ||
bar.jp, 2 | ||
baz.bar.jp, 2 | ||
pref.bar.jp, 1 | ||
bar.baz.com, 0 | ||
c, 2 | ||
b.c, 1 | ||
%% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* C++ code produced by gperf version 3.0.3 */ | ||
/* Command-line: gperf -a -L C++ -C -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test2 -D effective_tld_names_unittest2.gperf */ | ||
|
||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ | ||
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ | ||
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ | ||
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ | ||
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ | ||
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ | ||
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ | ||
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ | ||
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ | ||
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ | ||
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ | ||
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ | ||
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ | ||
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ | ||
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ | ||
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ | ||
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ | ||
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ | ||
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ | ||
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ | ||
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ | ||
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ | ||
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) | ||
/* The character set is not based on ISO-646. */ | ||
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." | ||
#endif | ||
|
||
#line 1 "effective_tld_names_unittest2.gperf" | ||
|
||
// Copyright (c) 2009 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that | ||
// can be found in the LICENSE file. | ||
// Test file used by registry_controlled_domain_unittest. | ||
// We edit this file manually, then run | ||
// gperf -a -L "C++" -C -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test2 -D effective_tld_names_unittest2.gperf > effective_tld_names_unittest2.cc | ||
// to generate the perfect hashmap. | ||
#line 10 "effective_tld_names_unittest2.gperf" | ||
struct DomainRule { | ||
const char *name; | ||
int type; // 1: exception, 2: wildcard | ||
}; | ||
|
||
#define TOTAL_KEYWORDS 2 | ||
#define MIN_WORD_LENGTH 2 | ||
#define MAX_WORD_LENGTH 6 | ||
#define MIN_HASH_VALUE 2 | ||
#define MAX_HASH_VALUE 6 | ||
/* maximum key range = 5, duplicates = 0 */ | ||
|
||
class Perfect_Hash_Test2 | ||
{ | ||
private: | ||
static inline unsigned int hash (const char *str, unsigned int len); | ||
public: | ||
static const struct DomainRule *FindDomain (const char *str, unsigned int len); | ||
}; | ||
|
||
inline unsigned int | ||
Perfect_Hash_Test2::hash (register const char *str, register unsigned int len) | ||
{ | ||
static const unsigned char asso_values[] = | ||
{ | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 0, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 0, 0, 7, | ||
7, 7, 7, 7, 7, 7, 0, 7, 7, 7, | ||
7, 7, 0, 7, 0, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
7, 7, 7, 7, 7, 7 | ||
}; | ||
register int hval = len; | ||
|
||
switch (hval) | ||
{ | ||
default: | ||
hval += asso_values[(unsigned char)str[5]]; | ||
/*FALLTHROUGH*/ | ||
case 5: | ||
hval += asso_values[(unsigned char)str[4]]; | ||
/*FALLTHROUGH*/ | ||
case 4: | ||
hval += asso_values[(unsigned char)str[3]]; | ||
/*FALLTHROUGH*/ | ||
case 3: | ||
hval += asso_values[(unsigned char)str[2]]; | ||
/*FALLTHROUGH*/ | ||
case 2: | ||
hval += asso_values[(unsigned char)str[1]]; | ||
/*FALLTHROUGH*/ | ||
case 1: | ||
hval += asso_values[(unsigned char)str[0]]; | ||
break; | ||
} | ||
return hval; | ||
} | ||
|
||
const struct DomainRule * | ||
Perfect_Hash_Test2::FindDomain (register const char *str, register unsigned int len) | ||
{ | ||
static const struct DomainRule wordlist[] = | ||
{ | ||
#line 15 "effective_tld_names_unittest2.gperf" | ||
{"jp", 0}, | ||
#line 16 "effective_tld_names_unittest2.gperf" | ||
{"bar.jp", 0} | ||
}; | ||
|
||
static const signed char lookup[] = | ||
{ | ||
-1, -1, 0, -1, -1, -1, 1 | ||
}; | ||
|
||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) | ||
{ | ||
register int key = hash (str, len); | ||
|
||
if (key <= MAX_HASH_VALUE && key >= 0) | ||
{ | ||
register int index = lookup[key]; | ||
|
||
if (index >= 0) | ||
{ | ||
register const char *s = wordlist[index].name; | ||
|
||
if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') | ||
return &wordlist[index]; | ||
} | ||
} | ||
} | ||
return 0; | ||
} | ||
#line 17 "effective_tld_names_unittest2.gperf" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
%{ | ||
// Copyright (c) 2009 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that | ||
// can be found in the LICENSE file. | ||
// Test file used by registry_controlled_domain_unittest. | ||
// We edit this file manually, then run | ||
// gperf -a -L "C++" -C -c -o -t -k '*' -NFindDomain -ZPerfect_Hash_Test2 -D effective_tld_names_unittest2.gperf > effective_tld_names_unittest2.cc | ||
// to generate the perfect hashmap. | ||
%} | ||
struct DomainRule { | ||
const char *name; | ||
int type; // 1: exception, 2: wildcard | ||
}; | ||
%% | ||
jp, 0 | ||
bar.jp, 0 | ||
%% |
Oops, something went wrong.