Skip to content

Commit

Permalink
Implement Lazy Loading of NameTable
Browse files Browse the repository at this point in the history
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
  • Loading branch information
jkroepke committed Jul 15, 2023
1 parent 9b5bc37 commit 11218a9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 41 deletions.
4 changes: 1 addition & 3 deletions collector/perflib.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import (
"github.com/go-kit/log/level"
)

var nametable = perflib.CounterNameTable

func MapCounterToIndex(name string) string {
return strconv.Itoa(int(nametable.LookupIndex(name)))
return strconv.Itoa(int(perflib.CounterNameTable.LookupIndex(name)))
}

func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) {
Expand Down
78 changes: 44 additions & 34 deletions perflib/nametable.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"strconv"
"sync"
)

// Initialize global name tables
Expand All @@ -18,54 +19,63 @@ func (p *perfObjectType) LookupName() string {
}

type NameTable struct {
byIndex map[uint32]string
byString map[string]uint32
once sync.Once

name string

table struct {
index map[uint32]string
string map[string]uint32
}
}

func (t *NameTable) LookupString(index uint32) string {
return t.byIndex[index]
t.initialize()
return t.table.index[index]
}

func (t *NameTable) LookupIndex(str string) uint32 {
return t.byString[str]
t.initialize()
return t.table.string[str]
}

// QueryNameTable Query a perflib name table from the registry. Specify the type and the language
// code (i.e. "Counter 009" or "Help 009") for English language.
func QueryNameTable(tableName string) *NameTable {
nameTable := new(NameTable)
nameTable.byIndex = make(map[uint32]string)

buffer, err := queryRawData(tableName)
if err != nil {
panic(err)
return &NameTable{
name: tableName,
}
r := bytes.NewReader(buffer)
for {
index, err := readUTF16String(r)
if err != nil {
break
}

desc, err := readUTF16String(r)
if err != nil {
break
}
}

indexInt, _ := strconv.Atoi(index)
func (t *NameTable) initialize() {
t.once.Do(func() {
t.table.index = make(map[uint32]string)
t.table.string = make(map[string]uint32)

buffer, err := queryRawData(t.name)
if err != nil {
panic(fmt.Sprint("Invalid index ", index))
panic(err)
}

nameTable.byIndex[uint32(indexInt)] = desc
}

nameTable.byString = make(map[string]uint32)

for k, v := range nameTable.byIndex {
nameTable.byString[v] = k
}

return nameTable
r := bytes.NewReader(buffer)
for {
index, err := readUTF16String(r)
if err != nil {
break
}

desc, err := readUTF16String(r)
if err != nil {
break
}

if err != nil {
panic(fmt.Sprint("Invalid index ", index))
}

indexInt, _ := strconv.Atoi(index)

t.table.index[uint32(indexInt)] = desc
t.table.string[desc] = uint32(indexInt)
}
})
}
5 changes: 1 addition & 4 deletions perflib/perflib.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,6 @@ type PerfCounter struct {
SecondValue int64
}

// Error value returned by RegQueryValueEx if the buffer isn't sufficiently large
const errorMoreData = syscall.Errno(syscall.ERROR_MORE_DATA)

var (
bufLenGlobal = uint32(400000)
bufLenCostly = uint32(2000000)
Expand Down Expand Up @@ -223,7 +220,7 @@ func queryRawData(query string) ([]byte, error) {
(*byte)(unsafe.Pointer(&buffer[0])),
&bufLen)

if err == errorMoreData {
if err == error(syscall.ERROR_MORE_DATA) {
newBuffer := make([]byte, len(buffer)+16384)
copy(newBuffer, buffer)
buffer = newBuffer
Expand Down

0 comments on commit 11218a9

Please sign in to comment.