Implement Lazy Loading of NameTable
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
parent
9b5bc37a42
commit
11218a95d0
|
@ -12,10 +12,8 @@ import (
|
||||||
"github.com/go-kit/log/level"
|
"github.com/go-kit/log/level"
|
||||||
)
|
)
|
||||||
|
|
||||||
var nametable = perflib.CounterNameTable
|
|
||||||
|
|
||||||
func MapCounterToIndex(name string) string {
|
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) {
|
func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initialize global name tables
|
// Initialize global name tables
|
||||||
|
@ -18,54 +19,63 @@ func (p *perfObjectType) LookupName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NameTable struct {
|
type NameTable struct {
|
||||||
byIndex map[uint32]string
|
once sync.Once
|
||||||
byString map[string]uint32
|
|
||||||
|
name string
|
||||||
|
|
||||||
|
table struct {
|
||||||
|
index map[uint32]string
|
||||||
|
string map[string]uint32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NameTable) LookupString(index uint32) string {
|
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 {
|
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
|
// 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.
|
// code (i.e. "Counter 009" or "Help 009") for English language.
|
||||||
func QueryNameTable(tableName string) *NameTable {
|
func QueryNameTable(tableName string) *NameTable {
|
||||||
nameTable := new(NameTable)
|
return &NameTable{
|
||||||
nameTable.byIndex = make(map[uint32]string)
|
name: tableName,
|
||||||
|
|
||||||
buffer, err := queryRawData(tableName)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
r := bytes.NewReader(buffer)
|
}
|
||||||
for {
|
|
||||||
index, err := readUTF16String(r)
|
func (t *NameTable) initialize() {
|
||||||
if err != nil {
|
t.once.Do(func() {
|
||||||
break
|
t.table.index = make(map[uint32]string)
|
||||||
}
|
t.table.string = make(map[string]uint32)
|
||||||
|
|
||||||
desc, err := readUTF16String(r)
|
buffer, err := queryRawData(t.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
panic(err)
|
||||||
}
|
}
|
||||||
|
r := bytes.NewReader(buffer)
|
||||||
indexInt, _ := strconv.Atoi(index)
|
for {
|
||||||
|
index, err := readUTF16String(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprint("Invalid index ", index))
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
nameTable.byIndex[uint32(indexInt)] = desc
|
desc, err := readUTF16String(r)
|
||||||
}
|
if err != nil {
|
||||||
|
break
|
||||||
nameTable.byString = make(map[string]uint32)
|
}
|
||||||
|
|
||||||
for k, v := range nameTable.byIndex {
|
if err != nil {
|
||||||
nameTable.byString[v] = k
|
panic(fmt.Sprint("Invalid index ", index))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nameTable
|
indexInt, _ := strconv.Atoi(index)
|
||||||
|
|
||||||
|
t.table.index[uint32(indexInt)] = desc
|
||||||
|
t.table.string[desc] = uint32(indexInt)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,9 +175,6 @@ type PerfCounter struct {
|
||||||
SecondValue int64
|
SecondValue int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error value returned by RegQueryValueEx if the buffer isn't sufficiently large
|
|
||||||
const errorMoreData = syscall.Errno(syscall.ERROR_MORE_DATA)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bufLenGlobal = uint32(400000)
|
bufLenGlobal = uint32(400000)
|
||||||
bufLenCostly = uint32(2000000)
|
bufLenCostly = uint32(2000000)
|
||||||
|
@ -223,7 +220,7 @@ func queryRawData(query string) ([]byte, error) {
|
||||||
(*byte)(unsafe.Pointer(&buffer[0])),
|
(*byte)(unsafe.Pointer(&buffer[0])),
|
||||||
&bufLen)
|
&bufLen)
|
||||||
|
|
||||||
if err == errorMoreData {
|
if err == error(syscall.ERROR_MORE_DATA) {
|
||||||
newBuffer := make([]byte, len(buffer)+16384)
|
newBuffer := make([]byte, len(buffer)+16384)
|
||||||
copy(newBuffer, buffer)
|
copy(newBuffer, buffer)
|
||||||
buffer = newBuffer
|
buffer = newBuffer
|
||||||
|
|
Loading…
Reference in New Issue