addressmap-inl.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. // Copyright (c) 2005, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // ---
  31. // Author: Sanjay Ghemawat
  32. //
  33. // A fast map from addresses to values. Assumes that addresses are
  34. // clustered. The main use is intended to be for heap-profiling.
  35. // May be too memory-hungry for other uses.
  36. //
  37. // We use a user-defined allocator/de-allocator so that we can use
  38. // this data structure during heap-profiling.
  39. //
  40. // IMPLEMENTATION DETAIL:
  41. //
  42. // Some default definitions/parameters:
  43. // * Block -- aligned 128-byte region of the address space
  44. // * Cluster -- aligned 1-MB region of the address space
  45. // * Block-ID -- block-number within a cluster
  46. // * Cluster-ID -- Starting address of cluster divided by cluster size
  47. //
  48. // We use a three-level map to represent the state:
  49. // 1. A hash-table maps from a cluster-ID to the data for that cluster.
  50. // 2. For each non-empty cluster we keep an array indexed by
  51. // block-ID tht points to the first entry in the linked-list
  52. // for the block.
  53. // 3. At the bottom, we keep a singly-linked list of all
  54. // entries in a block (for non-empty blocks).
  55. //
  56. // hash table
  57. // +-------------+
  58. // | id->cluster |---> ...
  59. // | ... |
  60. // | id->cluster |---> Cluster
  61. // +-------------+ +-------+ Data for one block
  62. // | nil | +------------------------------------+
  63. // | ----+---|->[addr/value]-->[addr/value]-->... |
  64. // | nil | +------------------------------------+
  65. // | ----+--> ...
  66. // | nil |
  67. // | ... |
  68. // +-------+
  69. //
  70. // Note that we require zero-bytes of overhead for completely empty
  71. // clusters. The minimum space requirement for a cluster is the size
  72. // of the hash-table entry plus a pointer value for each block in
  73. // the cluster. Empty blocks impose no extra space requirement.
  74. //
  75. // The cost of a lookup is:
  76. // a. A hash-table lookup to find the cluster
  77. // b. An array access in the cluster structure
  78. // c. A traversal over the linked-list for a block
  79. #ifndef BASE_ADDRESSMAP_INL_H_
  80. #define BASE_ADDRESSMAP_INL_H_
  81. #include "config.h"
  82. #include <stddef.h>
  83. #include <string.h>
  84. #if defined HAVE_STDINT_H
  85. #include <stdint.h> // to get uint16_t (ISO naming madness)
  86. #elif defined HAVE_INTTYPES_H
  87. #include <inttypes.h> // another place uint16_t might be defined
  88. #else
  89. #include <sys/types.h> // our last best hope
  90. #endif
  91. // This class is thread-unsafe -- that is, instances of this class can
  92. // not be accessed concurrently by multiple threads -- because the
  93. // callback function for Iterate() may mutate contained values. If the
  94. // callback functions you pass do not mutate their Value* argument,
  95. // AddressMap can be treated as thread-compatible -- that is, it's
  96. // safe for multiple threads to call "const" methods on this class,
  97. // but not safe for one thread to call const methods on this class
  98. // while another thread is calling non-const methods on the class.
  99. template <class Value>
  100. class AddressMap {
  101. public:
  102. typedef void* (*Allocator)(size_t size);
  103. typedef void (*DeAllocator)(void* ptr);
  104. typedef const void* Key;
  105. // Create an AddressMap that uses the specified allocator/deallocator.
  106. // The allocator/deallocator should behave like malloc/free.
  107. // For instance, the allocator does not need to return initialized memory.
  108. AddressMap(Allocator alloc, DeAllocator dealloc);
  109. ~AddressMap();
  110. // If the map contains an entry for "key", return it. Else return NULL.
  111. inline const Value* Find(Key key) const;
  112. inline Value* FindMutable(Key key);
  113. // Insert <key,value> into the map. Any old value associated
  114. // with key is forgotten.
  115. void Insert(Key key, Value value);
  116. // Remove any entry for key in the map. If an entry was found
  117. // and removed, stores the associated value in "*removed_value"
  118. // and returns true. Else returns false.
  119. bool FindAndRemove(Key key, Value* removed_value);
  120. // Similar to Find but we assume that keys are addresses of non-overlapping
  121. // memory ranges whose sizes are given by size_func.
  122. // If the map contains a range into which "key" points
  123. // (at its start or inside of it, but not at the end),
  124. // return the address of the associated value
  125. // and store its key in "*res_key".
  126. // Else return NULL.
  127. // max_size specifies largest range size possibly in existence now.
  128. typedef size_t (*ValueSizeFunc)(const Value& v);
  129. const Value* FindInside(ValueSizeFunc size_func, size_t max_size,
  130. Key key, Key* res_key);
  131. // Iterate over the address map calling 'callback'
  132. // for all stored key-value pairs and passing 'arg' to it.
  133. // We don't use full Closure/Callback machinery not to add
  134. // unnecessary dependencies to this class with low-level uses.
  135. template<class Type>
  136. inline void Iterate(void (*callback)(Key, Value*, Type), Type arg) const;
  137. private:
  138. typedef uintptr_t Number;
  139. // The implementation assumes that addresses inserted into the map
  140. // will be clustered. We take advantage of this fact by splitting
  141. // up the address-space into blocks and using a linked-list entry
  142. // for each block.
  143. // Size of each block. There is one linked-list for each block, so
  144. // do not make the block-size too big. Oterwise, a lot of time
  145. // will be spent traversing linked lists.
  146. static const int kBlockBits = 7;
  147. static const int kBlockSize = 1 << kBlockBits;
  148. // Entry kept in per-block linked-list
  149. struct Entry {
  150. Entry* next;
  151. Key key;
  152. Value value;
  153. };
  154. // We further group a sequence of consecutive blocks into a cluster.
  155. // The data for a cluster is represented as a dense array of
  156. // linked-lists, one list per contained block.
  157. static const int kClusterBits = 13;
  158. static const Number kClusterSize = 1 << (kBlockBits + kClusterBits);
  159. static const int kClusterBlocks = 1 << kClusterBits;
  160. // We use a simple chaining hash-table to represent the clusters.
  161. struct Cluster {
  162. Cluster* next; // Next cluster in hash table chain
  163. Number id; // Cluster ID
  164. Entry* blocks[kClusterBlocks]; // Per-block linked-lists
  165. };
  166. // Number of hash-table entries. With the block-size/cluster-size
  167. // defined above, each cluster covers 1 MB, so an 4K entry
  168. // hash-table will give an average hash-chain length of 1 for 4GB of
  169. // in-use memory.
  170. static const int kHashBits = 12;
  171. static const int kHashSize = 1 << 12;
  172. // Number of entry objects allocated at a time
  173. static const int ALLOC_COUNT = 64;
  174. Cluster** hashtable_; // The hash-table
  175. Entry* free_; // Free list of unused Entry objects
  176. // Multiplicative hash function:
  177. // The value "kHashMultiplier" is the bottom 32 bits of
  178. // int((sqrt(5)-1)/2 * 2^32)
  179. // This is a good multiplier as suggested in CLR, Knuth. The hash
  180. // value is taken to be the top "k" bits of the bottom 32 bits
  181. // of the muliplied value.
  182. static const uint32_t kHashMultiplier = 2654435769u;
  183. static int HashInt(Number x) {
  184. // Multiply by a constant and take the top bits of the result.
  185. const uint32_t m = static_cast<uint32_t>(x) * kHashMultiplier;
  186. return static_cast<int>(m >> (32 - kHashBits));
  187. }
  188. // Find cluster object for specified address. If not found
  189. // and "create" is true, create the object. If not found
  190. // and "create" is false, return NULL.
  191. //
  192. // This method is bitwise-const if create is false.
  193. Cluster* FindCluster(Number address, bool create) {
  194. // Look in hashtable
  195. const Number cluster_id = address >> (kBlockBits + kClusterBits);
  196. const int h = HashInt(cluster_id);
  197. for (Cluster* c = hashtable_[h]; c != NULL; c = c->next) {
  198. if (c->id == cluster_id) {
  199. return c;
  200. }
  201. }
  202. // Create cluster if necessary
  203. if (create) {
  204. Cluster* c = New<Cluster>(1);
  205. c->id = cluster_id;
  206. c->next = hashtable_[h];
  207. hashtable_[h] = c;
  208. return c;
  209. }
  210. return NULL;
  211. }
  212. // Return the block ID for an address within its cluster
  213. static int BlockID(Number address) {
  214. return (address >> kBlockBits) & (kClusterBlocks - 1);
  215. }
  216. //--------------------------------------------------------------
  217. // Memory management -- we keep all objects we allocate linked
  218. // together in a singly linked list so we can get rid of them
  219. // when we are all done. Furthermore, we allow the client to
  220. // pass in custom memory allocator/deallocator routines.
  221. //--------------------------------------------------------------
  222. struct Object {
  223. Object* next;
  224. // The real data starts here
  225. };
  226. Allocator alloc_; // The allocator
  227. DeAllocator dealloc_; // The deallocator
  228. Object* allocated_; // List of allocated objects
  229. // Allocates a zeroed array of T with length "num". Also inserts
  230. // the allocated block into a linked list so it can be deallocated
  231. // when we are all done.
  232. template <class T> T* New(int num) {
  233. void* ptr = (*alloc_)(sizeof(Object) + num*sizeof(T));
  234. memset(ptr, 0, sizeof(Object) + num*sizeof(T));
  235. Object* obj = reinterpret_cast<Object*>(ptr);
  236. obj->next = allocated_;
  237. allocated_ = obj;
  238. return reinterpret_cast<T*>(reinterpret_cast<Object*>(ptr) + 1);
  239. }
  240. };
  241. // More implementation details follow:
  242. template <class Value>
  243. AddressMap<Value>::AddressMap(Allocator alloc, DeAllocator dealloc)
  244. : free_(NULL),
  245. alloc_(alloc),
  246. dealloc_(dealloc),
  247. allocated_(NULL) {
  248. hashtable_ = New<Cluster*>(kHashSize);
  249. }
  250. template <class Value>
  251. AddressMap<Value>::~AddressMap() {
  252. // De-allocate all of the objects we allocated
  253. for (Object* obj = allocated_; obj != NULL; /**/) {
  254. Object* next = obj->next;
  255. (*dealloc_)(obj);
  256. obj = next;
  257. }
  258. }
  259. template <class Value>
  260. inline const Value* AddressMap<Value>::Find(Key key) const {
  261. return const_cast<AddressMap*>(this)->FindMutable(key);
  262. }
  263. template <class Value>
  264. inline Value* AddressMap<Value>::FindMutable(Key key) {
  265. const Number num = reinterpret_cast<Number>(key);
  266. const Cluster* const c = FindCluster(num, false/*do not create*/);
  267. if (c != NULL) {
  268. for (Entry* e = c->blocks[BlockID(num)]; e != NULL; e = e->next) {
  269. if (e->key == key) {
  270. return &e->value;
  271. }
  272. }
  273. }
  274. return NULL;
  275. }
  276. template <class Value>
  277. void AddressMap<Value>::Insert(Key key, Value value) {
  278. const Number num = reinterpret_cast<Number>(key);
  279. Cluster* const c = FindCluster(num, true/*create*/);
  280. // Look in linked-list for this block
  281. const int block = BlockID(num);
  282. for (Entry* e = c->blocks[block]; e != NULL; e = e->next) {
  283. if (e->key == key) {
  284. e->value = value;
  285. return;
  286. }
  287. }
  288. // Create entry
  289. if (free_ == NULL) {
  290. // Allocate a new batch of entries and add to free-list
  291. Entry* array = New<Entry>(ALLOC_COUNT);
  292. for (int i = 0; i < ALLOC_COUNT-1; i++) {
  293. array[i].next = &array[i+1];
  294. }
  295. array[ALLOC_COUNT-1].next = free_;
  296. free_ = &array[0];
  297. }
  298. Entry* e = free_;
  299. free_ = e->next;
  300. e->key = key;
  301. e->value = value;
  302. e->next = c->blocks[block];
  303. c->blocks[block] = e;
  304. }
  305. template <class Value>
  306. bool AddressMap<Value>::FindAndRemove(Key key, Value* removed_value) {
  307. const Number num = reinterpret_cast<Number>(key);
  308. Cluster* const c = FindCluster(num, false/*do not create*/);
  309. if (c != NULL) {
  310. for (Entry** p = &c->blocks[BlockID(num)]; *p != NULL; p = &(*p)->next) {
  311. Entry* e = *p;
  312. if (e->key == key) {
  313. *removed_value = e->value;
  314. *p = e->next; // Remove e from linked-list
  315. e->next = free_; // Add e to free-list
  316. free_ = e;
  317. return true;
  318. }
  319. }
  320. }
  321. return false;
  322. }
  323. template <class Value>
  324. const Value* AddressMap<Value>::FindInside(ValueSizeFunc size_func,
  325. size_t max_size,
  326. Key key,
  327. Key* res_key) {
  328. const Number key_num = reinterpret_cast<Number>(key);
  329. Number num = key_num; // we'll move this to move back through the clusters
  330. while (1) {
  331. const Cluster* c = FindCluster(num, false/*do not create*/);
  332. if (c != NULL) {
  333. while (1) {
  334. const int block = BlockID(num);
  335. bool had_smaller_key = false;
  336. for (const Entry* e = c->blocks[block]; e != NULL; e = e->next) {
  337. const Number e_num = reinterpret_cast<Number>(e->key);
  338. if (e_num <= key_num) {
  339. if (e_num == key_num || // to handle 0-sized ranges
  340. key_num < e_num + (*size_func)(e->value)) {
  341. *res_key = e->key;
  342. return &e->value;
  343. }
  344. had_smaller_key = true;
  345. }
  346. }
  347. if (had_smaller_key) return NULL; // got a range before 'key'
  348. // and it did not contain 'key'
  349. if (block == 0) break;
  350. // try address-wise previous block
  351. num |= kBlockSize - 1; // start at the last addr of prev block
  352. num -= kBlockSize;
  353. if (key_num - num > max_size) return NULL;
  354. }
  355. }
  356. if (num < kClusterSize) return NULL; // first cluster
  357. // go to address-wise previous cluster to try
  358. num |= kClusterSize - 1; // start at the last block of previous cluster
  359. num -= kClusterSize;
  360. if (key_num - num > max_size) return NULL;
  361. // Having max_size to limit the search is crucial: else
  362. // we have to traverse a lot of empty clusters (or blocks).
  363. // We can avoid needing max_size if we put clusters into
  364. // a search tree, but performance suffers considerably
  365. // if we use this approach by using stl::set.
  366. }
  367. }
  368. template <class Value>
  369. template <class Type>
  370. inline void AddressMap<Value>::Iterate(void (*callback)(Key, Value*, Type),
  371. Type arg) const {
  372. // We could optimize this by traversing only non-empty clusters and/or blocks
  373. // but it does not speed up heap-checker noticeably.
  374. for (int h = 0; h < kHashSize; ++h) {
  375. for (const Cluster* c = hashtable_[h]; c != NULL; c = c->next) {
  376. for (int b = 0; b < kClusterBlocks; ++b) {
  377. for (Entry* e = c->blocks[b]; e != NULL; e = e->next) {
  378. callback(e->key, &e->value, arg);
  379. }
  380. }
  381. }
  382. }
  383. }
  384. #endif // BASE_ADDRESSMAP_INL_H_