Skip to content

Commit

Permalink
docs: heap usage profile recorder (pingcap#17103)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yisaer authored May 12, 2020
1 parent a074317 commit 29c6b2b
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions docs/design/2020-05-11-heap-profile-record.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Heap Profile Recorder

- Author(s): [Yisaer](https://github.com/Yisaer) (Song Gao)
- Last updated: 2020-05-11
- Discussion at: https://github.com/pingcap/tidb/pull/16777

## Abstract

"Heap Profiler Recorder" profile the flat heap usage periodically in an extra goroutine to record the global `SimpleLRUCache` memory usage with an similar value.

## Background

Currently, we have support memory usage and disk usage tracker for `Executor`. In [#15407](https://github.com/pingcap/tidb/issues/15407), we are going to support the `Global Memory Tracker`.
However, it would be too much work to realize calculating the memory usage of each Implementation of `Plan` and it might also causing much cpu consuming. To track the memory usage of `SimpleLRUCache`, we are trying to search the memory usage from `runtime/pprof`.

## Proposal

We will record the whole `SimpleLRUCache` memory usage in the `GlobalLRUMemUsageTracker` memory tracker whose parent is `GlobalMemoryUsageTracker` memory tracker by using an extra goroutine to record the value searched and summed from heap profile periodically.

## Rationale

When an golang application started, the runtime would [startProfile](https://github.com/golang/go/blob/48a90d639d578d2b33fdc1903f03e028b4d40fa9/src/cmd/oldlink/internal/ld/main.go#L155) in default including heap usage.
And `runtime.MemProfileRate` controls the fraction of memory allocations that are recorded and reported in the memory profile. In default, `runtime.MemProfileRate` is 512 KB which is also can be configured. When the whole heap usage of `SimpleLRUCache` is larger than the `runtime.MemProfileRate`, it would be reflected in the flat value of the pprof heap profile.

To verify whether `kvcache.(*SimpleLRUCache).Put` would reflect the real heap usage, I use following test to ensure it:

1. fufill the `SimpleLRUCache` by `set @randomString = ? with 20000 times`.
2. profile the heap Usage of `github.com/pingcap/tidb/util/kvcache.(*SimpleLRUCache).Put` and the result is 2.55 MB

Let's dig into the Put then we can find the where the heap consumed:

```sh
(pprof) list Put
Total: 52.23MB
ROUTINE ======================== github.com/pingcap/tidb/util/kvcache.(*SimpleLRUCache).Put in /Users/yisa/Downloads/Github/GoProject/src/github.com/pingcap/tidb/util/kvcache/simple_lru.go
2.55MB 3.05MB (flat, cum) 5.85% of Total
. . 91: return element.Value.(*cacheEntry).value, true
. . 92:}
. . 93:
. . 94:// Put puts the (key, value) pair into the LRU Cache.
. . 95:func (l *SimpleLRUCache) Put(key Key, value Value) {
1.50MB 1.50MB 96: hash := string(key.Hash())
. . 97: element, exists := l.elements[hash]
. . 98: if exists {
. . 99: l.cache.MoveToFront(element)
. . 100: return
. . 101: }
. . 102:
. . 103: newCacheEntry := &cacheEntry{
. . 104: key: key,
. . 105: value: value,
. . 106: }
. . 107: hashSize := SizeOf(hash)
. . 108: singleSize := SizeOf(newCacheEntry)
. 512.02kB 109: element = l.cache.PushFront(newCacheEntry)
1.05MB 1.05MB 110: l.elements[hash] = element
. . 111: l.size++
. . 112: l.capacity = 200000
. . 113: // Getting used memory is expensive and can be avoided by setting quota to 0.
. . 114: if l.quota == 0 {

```
We can find that the `hash` (the key of cache) and the `element`(the value of the cache) totolly consume 2.55 MB.
3. we use [sizeof](https://github.com/templarbit/sizeof) (the result is similar, but lower, not exact) to calculate the size of each key and element is 80byte and 40byte.
4. As 2.28 MB (120 byte * 20000) is similar to the 2.55MB, we can ensure that the heap profile would reflect the heap usage of `SimpleLRUCache`.
## Compatibility and Mirgration Plan
None

0 comments on commit 29c6b2b

Please sign in to comment.