1/* Include file cached obstack implementation.
2   Written by Fred Fish <fnf@cygnus.com>
3   Rewritten by Jim Blandy <jimb@cygnus.com>
4
5   Copyright 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
6
7   This file is part of GDB.
8
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
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
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.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330,
22   Boston, MA 02111-1307, USA.  */
23
24#ifndef BCACHE_H
25#define BCACHE_H 1
26
27/* A bcache is a data structure for factoring out duplication in
28   read-only structures.  You give the bcache some string of bytes S.
29   If the bcache already contains a copy of S, it hands you back a
30   pointer to its copy.  Otherwise, it makes a fresh copy of S, and
31   hands you back a pointer to that.  In either case, you can throw
32   away your copy of S, and use the bcache's.
33
34   The "strings" in question are arbitrary strings of bytes --- they
35   can contain zero bytes.  You pass in the length explicitly when you
36   call the bcache function.
37
38   This means that you can put ordinary C objects in a bcache.
39   However, if you do this, remember that structs can contain `holes'
40   between members, added for alignment.  These bytes usually contain
41   garbage.  If you try to bcache two objects which are identical from
42   your code's point of view, but have different garbage values in the
43   structure's holes, then the bcache will treat them as separate
44   strings, and you won't get the nice elimination of duplicates you
45   were hoping for.  So, remember to memset your structures full of
46   zeros before bcaching them!
47
48   You shouldn't modify the strings you get from a bcache, because:
49
50   - You don't necessarily know who you're sharing space with.  If I
51   stick eight bytes of text in a bcache, and then stick an eight-byte
52   structure in the same bcache, there's no guarantee those two
53   objects don't actually comprise the same sequence of bytes.  If
54   they happen to, the bcache will use a single byte string for both
55   of them.  Then, modifying the structure will change the string.  In
56   bizarre ways.
57
58   - Even if you know for some other reason that all that's okay,
59   there's another problem.  A bcache stores all its strings in a hash
60   table.  If you modify a string's contents, you will probably change
61   its hash value.  This means that the modified string is now in the
62   wrong place in the hash table, and future bcache probes will never
63   find it.  So by mutating a string, you give up any chance of
64   sharing its space with future duplicates.
65
66
67   Size of bcache VS hashtab:
68
69   For bcache, the most critical cost is size (or more exactly the
70   overhead added by the bcache).  It turns out that the bcache is
71   remarkably efficient.
72
73   Assuming a 32-bit system (the hash table slots are 4 bytes),
74   ignoring alignment, and limit strings to 255 bytes (1 byte length)
75   we get ...
76
77   bcache: This uses a separate linked list to track the hash chain.
78   The numbers show roughly 100% occupancy of the hash table and an
79   average chain length of 4.  Spreading the slot cost over the 4
80   chain elements:
81
82   4 (slot) / 4 (chain length) + 1 (length) + 4 (chain) = 6 bytes
83
84   hashtab: This uses a more traditional re-hash algorithm where the
85   chain is maintained within the hash table.  The table occupancy is
86   kept below 75% but we'll assume its perfect:
87
88   4 (slot) x 4/3 (occupancy) +  1 (length) = 6 1/3 bytes
89
90   So a perfect hashtab has just slightly larger than an average
91   bcache.
92
93   It turns out that an average hashtab is far worse.  Two things
94   hurt:
95
96   - Hashtab's occupancy is more like 50% (it ranges between 38% and
97   75%) giving a per slot cost of 4x2 vs 4x4/3.
98
99   - the string structure needs to be aligned to 8 bytes which for
100   hashtab wastes 7 bytes, while for bcache wastes only 3.
101
102   This gives:
103
104   hashtab: 4 x 2 + 1 + 7 = 16 bytes
105
106   bcache 4 / 4 + 1 + 4 + 3 = 9 bytes
107
108   The numbers of GDB debugging GDB support this.  ~40% vs ~70% overhead.
109
110
111   Speed of bcache VS hashtab (the half hash hack):
112
113   While hashtab has a typical chain length of 1, bcache has a chain
114   length of round 4.  This means that the bcache will require
115   something like double the number of compares after that initial
116   hash.  In both cases the comparison takes the form:
117
118   a.length == b.length && memcmp (a.data, b.data, a.length) == 0
119
120   That is lengths are checked before doing the memcmp.
121
122   For GDB debugging GDB, it turned out that all lengths were 24 bytes
123   (no C++ so only psymbols were cached) and hence, all compares
124   required a call to memcmp.  As a hack, two bytes of padding
125   (mentioned above) are used to store the upper 16 bits of the
126   string's hash value and then that is used in the comparison vis:
127
128   a.half_hash == b.half_hash && a.length == b.length && memcmp
129   (a.data, b.data, a.length)
130
131   The numbers from GDB debugging GDB show this to be a remarkable
132   100% effective (only necessary length and memcmp tests being
133   performed).
134
135   Mind you, looking at the wall clock, the same GDB debugging GDB
136   showed only marginal speed up (0.780 vs 0.773s).  Seems GDB is too
137   busy doing something else :-(
138
139*/
140
141
142struct bcache;
143
144/* Find a copy of the LENGTH bytes at ADDR in BCACHE.  If BCACHE has
145   never seen those bytes before, add a copy of them to BCACHE.  In
146   either case, return a pointer to BCACHE's copy of that string.
147   Since the cached value is ment to be read-only, return a const
148   buffer.  */
149extern void *deprecated_bcache (const void *addr, int length,
150				struct bcache *bcache);
151extern const void *bcache (const void *addr, int length,
152			   struct bcache *bcache);
153
154/* Free all the storage used by BCACHE.  */
155extern void bcache_xfree (struct bcache *bcache);
156
157/* Create a new bcache object.  */
158extern struct bcache *bcache_xmalloc (void);
159
160/* Print statistics on BCACHE's memory usage and efficacity at
161   eliminating duplication.  TYPE should be a string describing the
162   kind of data BCACHE holds.  Statistics are printed using
163   `printf_filtered' and its ilk.  */
164extern void print_bcache_statistics (struct bcache *bcache, char *type);
165extern int bcache_memory_used (struct bcache *bcache);
166
167/* The hash function */
168extern unsigned long hash(const void *addr, int length);
169
170#endif /* BCACHE_H */
171