(buckets map[int]int64)
| 2004 | } |
| 2005 | |
| 2006 | func makeBucketsFromMap(buckets map[int]int64) ([]*dto.BucketSpan, []int64) { |
| 2007 | if len(buckets) == 0 { |
| 2008 | return nil, nil |
| 2009 | } |
| 2010 | var ii []int |
| 2011 | for k := range buckets { |
| 2012 | ii = append(ii, k) |
| 2013 | } |
| 2014 | sort.Ints(ii) |
| 2015 | |
| 2016 | var ( |
| 2017 | spans []*dto.BucketSpan |
| 2018 | deltas []int64 |
| 2019 | prevCount int64 |
| 2020 | nextI int |
| 2021 | ) |
| 2022 | |
| 2023 | appendDelta := func(count int64) { |
| 2024 | *spans[len(spans)-1].Length++ |
| 2025 | deltas = append(deltas, count-prevCount) |
| 2026 | prevCount = count |
| 2027 | } |
| 2028 | |
| 2029 | for n, i := range ii { |
| 2030 | count := buckets[i] |
| 2031 | // Multiple spans with only small gaps in between are probably |
| 2032 | // encoded more efficiently as one larger span with a few empty |
| 2033 | // buckets. Needs some research to find the sweet spot. For now, |
| 2034 | // we assume that gaps of one or two buckets should not create |
| 2035 | // a new span. |
| 2036 | iDelta := int32(i - nextI) |
| 2037 | if n == 0 || iDelta > 2 { |
| 2038 | // We have to create a new span, either because we are |
| 2039 | // at the very beginning, or because we have found a gap |
| 2040 | // of more than two buckets. |
| 2041 | spans = append(spans, &dto.BucketSpan{ |
| 2042 | Offset: proto.Int32(iDelta), |
| 2043 | Length: proto.Uint32(0), |
| 2044 | }) |
| 2045 | } else { |
| 2046 | // We have found a small gap (or no gap at all). |
| 2047 | // Insert empty buckets as needed. |
| 2048 | for j := int32(0); j < iDelta; j++ { |
| 2049 | appendDelta(0) |
| 2050 | } |
| 2051 | } |
| 2052 | appendDelta(count) |
| 2053 | nextI = i + 1 |
| 2054 | } |
| 2055 | return spans, deltas |
| 2056 | } |
no outgoing calls