Fix (most) OpenBSD link errors
[deliverable/binutils-gdb.git] / gdb / bcache.h
CommitLineData
c906108c 1/* Include file cached obstack implementation.
c2d11a7d
JM
2 Written by Fred Fish <fnf@cygnus.com>
3 Rewritten by Jim Blandy <jimb@cygnus.com>
af5f3db6 4
42a4f53d 5 Copyright (C) 1999-2019 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
c5aa993b 12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b 19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#ifndef BCACHE_H
23#define BCACHE_H 1
24
c2d11a7d
JM
25/* A bcache is a data structure for factoring out duplication in
26 read-only structures. You give the bcache some string of bytes S.
27 If the bcache already contains a copy of S, it hands you back a
28 pointer to its copy. Otherwise, it makes a fresh copy of S, and
29 hands you back a pointer to that. In either case, you can throw
30 away your copy of S, and use the bcache's.
31
32 The "strings" in question are arbitrary strings of bytes --- they
33 can contain zero bytes. You pass in the length explicitly when you
34 call the bcache function.
35
36 This means that you can put ordinary C objects in a bcache.
37 However, if you do this, remember that structs can contain `holes'
38 between members, added for alignment. These bytes usually contain
39 garbage. If you try to bcache two objects which are identical from
40 your code's point of view, but have different garbage values in the
41 structure's holes, then the bcache will treat them as separate
42 strings, and you won't get the nice elimination of duplicates you
43 were hoping for. So, remember to memset your structures full of
44 zeros before bcaching them!
45
46 You shouldn't modify the strings you get from a bcache, because:
47
48 - You don't necessarily know who you're sharing space with. If I
49df298f
AC
49 stick eight bytes of text in a bcache, and then stick an eight-byte
50 structure in the same bcache, there's no guarantee those two
51 objects don't actually comprise the same sequence of bytes. If
52 they happen to, the bcache will use a single byte string for both
53 of them. Then, modifying the structure will change the string. In
54 bizarre ways.
c2d11a7d
JM
55
56 - Even if you know for some other reason that all that's okay,
49df298f
AC
57 there's another problem. A bcache stores all its strings in a hash
58 table. If you modify a string's contents, you will probably change
59 its hash value. This means that the modified string is now in the
60 wrong place in the hash table, and future bcache probes will never
61 find it. So by mutating a string, you give up any chance of
62 sharing its space with future duplicates.
63
64
65 Size of bcache VS hashtab:
66
67 For bcache, the most critical cost is size (or more exactly the
68 overhead added by the bcache). It turns out that the bcache is
69 remarkably efficient.
70
71 Assuming a 32-bit system (the hash table slots are 4 bytes),
72 ignoring alignment, and limit strings to 255 bytes (1 byte length)
73 we get ...
74
75 bcache: This uses a separate linked list to track the hash chain.
76 The numbers show roughly 100% occupancy of the hash table and an
77 average chain length of 4. Spreading the slot cost over the 4
78 chain elements:
79
80 4 (slot) / 4 (chain length) + 1 (length) + 4 (chain) = 6 bytes
81
82 hashtab: This uses a more traditional re-hash algorithm where the
83 chain is maintained within the hash table. The table occupancy is
84 kept below 75% but we'll assume its perfect:
85
86 4 (slot) x 4/3 (occupancy) + 1 (length) = 6 1/3 bytes
87
88 So a perfect hashtab has just slightly larger than an average
89 bcache.
90
91 It turns out that an average hashtab is far worse. Two things
92 hurt:
93
94 - Hashtab's occupancy is more like 50% (it ranges between 38% and
95 75%) giving a per slot cost of 4x2 vs 4x4/3.
96
97 - the string structure needs to be aligned to 8 bytes which for
98 hashtab wastes 7 bytes, while for bcache wastes only 3.
99
100 This gives:
101
102 hashtab: 4 x 2 + 1 + 7 = 16 bytes
103
104 bcache 4 / 4 + 1 + 4 + 3 = 9 bytes
105
106 The numbers of GDB debugging GDB support this. ~40% vs ~70% overhead.
107
108
109 Speed of bcache VS hashtab (the half hash hack):
110
111 While hashtab has a typical chain length of 1, bcache has a chain
112 length of round 4. This means that the bcache will require
113 something like double the number of compares after that initial
114 hash. In both cases the comparison takes the form:
115
116 a.length == b.length && memcmp (a.data, b.data, a.length) == 0
117
118 That is lengths are checked before doing the memcmp.
119
120 For GDB debugging GDB, it turned out that all lengths were 24 bytes
121 (no C++ so only psymbols were cached) and hence, all compares
122 required a call to memcmp. As a hack, two bytes of padding
123 (mentioned above) are used to store the upper 16 bits of the
124 string's hash value and then that is used in the comparison vis:
125
126 a.half_hash == b.half_hash && a.length == b.length && memcmp
127 (a.data, b.data, a.length)
128
129 The numbers from GDB debugging GDB show this to be a remarkable
130 100% effective (only necessary length and memcmp tests being
131 performed).
132
133 Mind you, looking at the wall clock, the same GDB debugging GDB
134 showed only marginal speed up (0.780 vs 0.773s). Seems GDB is too
135 busy doing something else :-(
136
137*/
c2d11a7d 138
25629dfd 139struct bstring;
af5f3db6 140
25629dfd
TT
141struct bcache
142{
143 /* Allocate a bcache. HASH_FN and COMPARE_FN can be used to pass in
144 custom hash, and compare functions to be used by this bcache. If
4cbd39b2 145 HASH_FUNCTION is NULL fast_hash() is used and if COMPARE_FUNCTION is
25629dfd
TT
146 NULL memcmp() is used. */
147
148 explicit bcache (unsigned long (*hash_fn)(const void *,
149 int length) = nullptr,
150 int (*compare_fn)(const void *, const void *,
151 int length) = nullptr)
4cbd39b2 152 : m_hash_function (hash_fn == nullptr ? default_hash : hash_fn),
25629dfd
TT
153 m_compare_function (compare_fn == nullptr ? compare : compare_fn)
154 {
155 }
156
157 ~bcache ();
158
159 /* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
160 never seen those bytes before, add a copy of them to BCACHE. In
161 either case, return a pointer to BCACHE's copy of that string.
162 Since the cached value is ment to be read-only, return a const
163 buffer. If ADDED is not NULL, set *ADDED to true if the bytes
164 were newly added to the cache, or to false if the bytes were
165 found in the cache. */
166
167 const void *insert (const void *addr, int length, int *added = nullptr);
168
169 /* Print statistics on this bcache's memory usage and efficacity at
170 eliminating duplication. TYPE should be a string describing the
171 kind of data this bcache holds. Statistics are printed using
172 `printf_filtered' and its ilk. */
173 void print_statistics (const char *type);
174 int memory_used ();
175
176private:
177
178 /* All the bstrings are allocated here. */
179 struct obstack m_cache {};
180
181 /* How many hash buckets we're using. */
182 unsigned int m_num_buckets = 0;
183
184 /* Hash buckets. This table is allocated using malloc, so when we
185 grow the table we can return the old table to the system. */
186 struct bstring **m_bucket = nullptr;
187
188 /* Statistics. */
189 unsigned long m_unique_count = 0; /* number of unique strings */
190 long m_total_count = 0; /* total number of strings cached, including dups */
191 long m_unique_size = 0; /* size of unique strings, in bytes */
192 long m_total_size = 0; /* total number of bytes cached, including dups */
193 long m_structure_size = 0; /* total size of bcache, including infrastructure */
194 /* Number of times that the hash table is expanded and hence
195 re-built, and the corresponding number of times that a string is
196 [re]hashed as part of entering it into the expanded table. The
197 total number of hashes can be computed by adding TOTAL_COUNT to
198 expand_hash_count. */
199 unsigned long m_expand_count = 0;
200 unsigned long m_expand_hash_count = 0;
201 /* Number of times that the half-hash compare hit (compare the upper
202 16 bits of hash values) hit, but the corresponding combined
203 length/data compare missed. */
204 unsigned long m_half_hash_miss_count = 0;
205
206 /* Hash function to be used for this bcache object. */
207 unsigned long (*m_hash_function)(const void *addr, int length);
208
209 /* Compare function to be used for this bcache object. */
210 int (*m_compare_function)(const void *, const void *, int length);
211
212 /* Default compare function. */
213 static int compare (const void *addr1, const void *addr2, int length);
214
4cbd39b2
CB
215 /* Default hash function. */
216 static unsigned long default_hash (const void *ptr, int length)
217 {
218 return fast_hash (ptr, length, 0);
219 }
220
25629dfd
TT
221 /* Expand the hash table. */
222 void expand_hash_table ();
223};
224
c906108c 225#endif /* BCACHE_H */
This page took 1.299376 seconds and 4 git commands to generate.