File: DictionaryStatistics.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (62 lines) | stat: -rw-r--r-- 2,623 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2022 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

struct DictionaryStatistics {
  /// The sum of all storage within the hash table that is available for
  /// item storage, measured in bytes. This does account for the maximum
  /// load factor.
  var capacityBytes: Int = 0

  /// The number of bytes of storage currently used for storing items.
  var itemBytes: Int = 0

  /// The number of bytes currently available in storage for storing items.
  var freeBytes: Int = 0

  /// An estimate of the actual memory occupied by this hash table.
  /// This includes not only storage space available for items,
  /// but also the memory taken up by the object header and the hash table
  /// occupation bitmap.
  var grossBytes: Int = 0

  /// An estimate of how efficiently this data structure manages memory.
  /// This is a value between 0 and 1 -- the ratio between how much space
  /// the actual stored data occupies and the overall number of bytes allocated
  /// for the entire data structure. (`itemBytes / grossBytes`)
  var memoryEfficiency: Double {
    guard grossBytes > 0 else { return 1 }
    return Double(itemBytes) / Double(grossBytes)
  }
}

extension Dictionary {
  var statistics: DictionaryStatistics {
    // Note: This logic is based on the Dictionary ABI. It may be off by a few
    // bytes due to not accounting for padding bytes between storage regions.
    // The gross bytes reported also do not include extra memory that was
    // allocated by malloc but not actually used for Dictionary storage.
    var stats = DictionaryStatistics()
    let keyStride = MemoryLayout<Key>.stride
    let valueStride = MemoryLayout<Value>.stride
    stats.capacityBytes = self.capacity * (keyStride + valueStride)
    stats.itemBytes = self.count * (keyStride + valueStride)
    stats.freeBytes = stats.capacityBytes - stats.itemBytes

    let bucketCount = self.capacity._roundUpToPowerOfTwo()
    let bitmapBitcount = (bucketCount + UInt.bitWidth - 1)

    let objectHeaderBits = 2 * Int.bitWidth
    let ivarBits = 5 * Int.bitWidth + 64
    stats.grossBytes = (objectHeaderBits + ivarBits + bitmapBitcount) / 8
    stats.grossBytes += bucketCount * keyStride + bucketCount * valueStride
    return stats
  }
}