mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 18:57:18 +08:00 
			
		
		
		
	proc: Caching type offsets
Caches the mapping of type names to offset in debug_info to speed up variable evaluation. BEFORE: BenchmarkArray-4 100 13'238'441 ns/op 0.62 MB/s BenchmarkArrayPointer-4 200 10'044'093 ns/op 0.87 MB/s BenchmarkMap-4 1000 1'332'530 ns/op 0.77 MB/s BenchmarkGoroutinesInfo-4 10 114'677'462 ns/op BenchmarkLocalVariables-4 2000 1'223'975 ns/op AFTER: BenchmarkArray-4 200 9'925'686 ns/op 0.83 MB/s BenchmarkArrayPointer-4 100 11'143'930 ns/op 0.78 MB/s BenchmarkMap-4 2000 1'302'520 ns/op 0.79 MB/s BenchmarkGoroutinesInfo-4 30 35'079'549 ns/op BenchmarkLocalVariables-4 1000 1'137'299 ns/op Note in particular the speedup of BenchmarkGoroutinesInfo, since proc.(*Variable).parseG is a function we call a lot.
This commit is contained in:
		
							
								
								
									
										20
									
								
								proc/proc.go
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								proc/proc.go
									
									
									
									
									
								
							| @ -58,6 +58,7 @@ type Process struct { | |||||||
| 	exited                  bool | 	exited                  bool | ||||||
| 	ptraceChan              chan func() | 	ptraceChan              chan func() | ||||||
| 	ptraceDoneChan          chan interface{} | 	ptraceDoneChan          chan interface{} | ||||||
|  | 	types                   map[string]dwarf.Offset | ||||||
| } | } | ||||||
|  |  | ||||||
| // New returns an initialized Process struct. Before returning, | // New returns an initialized Process struct. Before returning, | ||||||
| @ -149,11 +150,12 @@ func (dbp *Process) LoadInformation(path string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	wg.Add(4) | 	wg.Add(5) | ||||||
| 	go dbp.loadProcessInformation(&wg) | 	go dbp.loadProcessInformation(&wg) | ||||||
| 	go dbp.parseDebugFrame(exe, &wg) | 	go dbp.parseDebugFrame(exe, &wg) | ||||||
| 	go dbp.obtainGoSymbols(exe, &wg) | 	go dbp.obtainGoSymbols(exe, &wg) | ||||||
| 	go dbp.parseDebugLineInfo(exe, &wg) | 	go dbp.parseDebugLineInfo(exe, &wg) | ||||||
|  | 	go dbp.loadTypeMap(&wg) | ||||||
| 	wg.Wait() | 	wg.Wait() | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @ -658,19 +660,9 @@ func (dbp *Process) Funcs() []gosym.Func { | |||||||
|  |  | ||||||
| // Types returns list of types present in the debugged program. | // Types returns list of types present in the debugged program. | ||||||
| func (dbp *Process) Types() ([]string, error) { | func (dbp *Process) Types() ([]string, error) { | ||||||
| 	reader := dbp.DwarfReader() | 	types := make([]string, 0, len(dbp.types)) | ||||||
| 	types := []string{} | 	for k := range dbp.types { | ||||||
| 	seen := map[string]struct{}{} | 		types = append(types, k) | ||||||
| 	for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() { |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		if n, ok := entry.Val(dwarf.AttrName).(string); ok { |  | ||||||
| 			if _, isseen := seen[n]; !isseen { |  | ||||||
| 				seen[n] = struct{}{} |  | ||||||
| 				types = append(types, n) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return types, nil | 	return types, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -1626,7 +1626,7 @@ func TestPackageVariables(t *testing.T) { | |||||||
|  |  | ||||||
| func TestIssue149(t *testing.T) { | func TestIssue149(t *testing.T) { | ||||||
| 	ver, _ := ParseVersionString(runtime.Version()) | 	ver, _ := ParseVersionString(runtime.Version()) | ||||||
| 	if ver.Major	> 0 && !ver.AfterOrEqual(GoVersion{1, 7, 0, 0, 0}) { | 	if ver.Major > 0 && !ver.AfterOrEqual(GoVersion{1, 7, 0, 0, 0}) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// setting breakpoint on break statement | 	// setting breakpoint on break statement | ||||||
|  | |||||||
| @ -1,20 +1,21 @@ | |||||||
| package proc | package proc | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/derekparker/delve/dwarf/reader" | ||||||
| 	"go/ast" | 	"go/ast" | ||||||
| 	"golang.org/x/debug/dwarf" | 	"golang.org/x/debug/dwarf" | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"sync" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Do not call this function directly it isn't able to deal correctly with package paths | // Do not call this function directly it isn't able to deal correctly with package paths | ||||||
| func (dbp *Process) findType(name string) (dwarf.Type, error) { | func (dbp *Process) findType(name string) (dwarf.Type, error) { | ||||||
| 	reader := dbp.DwarfReader() | 	off, found := dbp.types[name] | ||||||
| 	typentry, err := reader.SeekToTypeNamed(name) | 	if !found { | ||||||
| 	if err != nil { | 		return nil, reader.TypeNotFoundErr | ||||||
| 		return nil, err |  | ||||||
| 	} | 	} | ||||||
| 	return dbp.dwarf.Type(typentry.Offset) | 	return dbp.dwarf.Type(off) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dbp *Process) pointerTo(typ dwarf.Type) dwarf.Type { | func (dbp *Process) pointerTo(typ dwarf.Type) dwarf.Type { | ||||||
| @ -83,6 +84,24 @@ func (dbp *Process) loadPackageMap() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (dbp *Process) loadTypeMap(wg *sync.WaitGroup) { | ||||||
|  | 	defer wg.Done() | ||||||
|  | 	dbp.types = make(map[string]dwarf.Offset) | ||||||
|  | 	reader := dbp.DwarfReader() | ||||||
|  | 	for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() { | ||||||
|  | 		if err != nil { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		name, ok := entry.Val(dwarf.AttrName).(string) | ||||||
|  | 		if !ok { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		if _, exists := dbp.types[name]; !exists { | ||||||
|  | 			dbp.types[name] = entry.Offset | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (dbp *Process) expandPackagesInType(expr ast.Expr) { | func (dbp *Process) expandPackagesInType(expr ast.Expr) { | ||||||
| 	switch e := expr.(type) { | 	switch e := expr.(type) { | ||||||
| 	case *ast.ArrayType: | 	case *ast.ArrayType: | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 aarzilli
					aarzilli