Last active
November 15, 2016 11:16
-
-
Save egonelbre/ab6c7a4a004227a168a8229656e9863c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" | |
call %VCVARS% x64 | |
cl /O1 -Feloader.64.exe loader.cpp | |
call %VCVARS% x86 | |
cl /O1 -Feloader.32.exe loader.cpp | |
del *.obj | |
go build timemem.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define WIN32_LEAN_AND_MEAN | |
#include <Windows.h> | |
int main(int argc, char const *argv[]) | |
{ | |
for(int i = 1; i < argc; i++){ | |
HINSTANCE libx = LoadLibrary(argv[i]); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set N=1000 | |
echo "32bit none" | |
timemem -n %N% loader.32.exe | |
echo "32bit stdlib" | |
timemem -n %N% loader.32.exe kernel32.dll advapi32.dll shell32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll winmm.dll | |
echo "32bit stdlib wo shell32" | |
timemem -n %N% loader.32.exe kernel32.dll advapi32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll winmm.dll | |
echo "32bit stdlib wo shell32,winmm" | |
timemem -n %N% loader.32.exe kernel32.dll advapi32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll | |
echo "64bit none" | |
timemem -n %N% loader.64.exe | |
echo "64bit stdlib" | |
timemem -n %N% loader.64.exe kernel32.dll advapi32.dll shell32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll winmm.dll | |
echo "64bit stdlib wo shell32" | |
timemem -n %N% loader.64.exe kernel32.dll advapi32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll winmm.dll | |
echo "64bit stdlib wo shell32,winmm" | |
timemem -n %N% loader.64.exe kernel32.dll advapi32.dll mswsock.dll crypt32.dll ws2_32.dll dnsapi.dll iphlpapi.dll secur32.dll netapi32.dll userenv.dll |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"flag" | |
"fmt" | |
"os" | |
"runtime" | |
"strings" | |
"syscall" | |
"time" | |
"unsafe" | |
"golang.org/x/sys/windows" | |
) | |
var ( | |
N = flag.Int("n", 1000, "number of measurements") | |
) | |
type Measurement struct { | |
N int | |
Elapsed time.Duration | |
Kernel time.Duration | |
User time.Duration | |
PageFault int | |
WorkingSet int | |
PagedPool int | |
NonPagedPool int | |
PageFileSize int | |
} | |
func (m *Measurement) Add(b *Measurement) { | |
m.N += b.N | |
m.Elapsed += b.Elapsed | |
m.Kernel += b.Kernel | |
m.User += b.User | |
m.PageFault += b.PageFault | |
m.WorkingSet += b.WorkingSet | |
m.PagedPool += b.PagedPool | |
m.NonPagedPool += b.NonPagedPool | |
m.PageFileSize += b.PageFileSize | |
} | |
func (m *Measurement) Print() { | |
fmt.Printf("Elapsed %3.6fms\n", (m.Elapsed/time.Duration(m.N)).Seconds()*1000) | |
fmt.Printf("Kernel %3.6fms\n", (m.Kernel/time.Duration(m.N)).Seconds()*1000) | |
fmt.Printf("User %3.6fms\n", (m.User/time.Duration(m.N)).Seconds()*1000) | |
fmt.Printf("PageFault %3v KB\n", m.PageFault/m.N) | |
fmt.Printf("WorkingSet %3v KB\n", m.WorkingSet/m.N) | |
fmt.Printf("PagedPool %3v KB\n", m.PagedPool/m.N) | |
fmt.Printf("NonPagedPool %3v KB\n", m.NonPagedPool/m.N) | |
fmt.Printf("PageFileSize %3v KB\n", m.PageFileSize/m.N) | |
} | |
func filetimeToDuration(ft windows.Filetime) time.Duration { | |
nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) | |
return time.Duration(nsec*100) * time.Nanosecond | |
} | |
func Inspect(pid windows.Handle) (*Measurement, error) { | |
m := &Measurement{N: 1} | |
var creation, exit, kernel, user windows.Filetime | |
if err := windows.GetProcessTimes(pid, &creation, &exit, &kernel, &user); err != nil { | |
return nil, err | |
} | |
m.Elapsed = filetimeToDuration(exit) - filetimeToDuration(creation) | |
m.Kernel = filetimeToDuration(kernel) | |
m.User = filetimeToDuration(user) | |
var pmc ProcessMemoryCounters | |
if err := GetProcessMemoryInfo(pid, &pmc); err != nil { | |
return nil, err | |
} | |
m.PageFault = int(pmc.PageFaultCount) | |
m.WorkingSet = int(pmc.PeakWorkingSetSize) | |
m.PagedPool = int(pmc.QuotaPeakPagedPoolUsage) | |
m.NonPagedPool = int(pmc.QuotaPeakNonPagedPoolUsage) | |
m.PageFileSize = int(pmc.PeakPagefileUsage) | |
return m, nil | |
} | |
func MeasureProcess(args string) (*Measurement, error) { | |
si := &windows.StartupInfo{} | |
pi := &windows.ProcessInformation{} | |
argsp := windows.StringToUTF16Ptr(args) | |
defer runtime.KeepAlive(argsp) | |
err := windows.CreateProcess(nil, argsp, nil, nil, false, 0, nil, nil, si, pi) | |
if err != nil { | |
return &Measurement{}, err | |
} | |
defer windows.CloseHandle(pi.Thread) | |
defer windows.CloseHandle(pi.Process) | |
ev, err := windows.WaitForSingleObject(pi.Process, windows.INFINITE) | |
if err != nil { | |
return &Measurement{}, err | |
} | |
if ev != windows.WAIT_OBJECT_0 { | |
return &Measurement{}, errors.New("cannot wait for process") | |
} | |
return Inspect(pi.Process) | |
} | |
func main() { | |
flag.Parse() | |
args := strings.Join(flag.Args(), " ") | |
var total Measurement | |
for i := 0; i < *N; i++ { | |
m, err := MeasureProcess(args) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
continue | |
} | |
total.Add(m) | |
} | |
total.Print() | |
} | |
// psapi | |
var ( | |
modpsapi = windows.NewLazySystemDLL("psapi.dll") | |
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") | |
) | |
type ProcessMemoryCounters struct { | |
CB uint32 | |
PageFaultCount uint32 | |
PeakWorkingSetSize uintptr | |
WorkingSetSize uintptr | |
QuotaPeakPagedPoolUsage uintptr | |
QuotaPagedPoolUsage uintptr | |
QuotaPeakNonPagedPoolUsage uintptr | |
QuotaNonPagedPoolUsage uintptr | |
PagefileUsage uintptr | |
PeakPagefileUsage uintptr | |
} | |
func GetProcessMemoryInfo(h windows.Handle, pmc *ProcessMemoryCounters) (err error) { | |
r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(h), uintptr(unsafe.Pointer(pmc)), uintptr(unsafe.Sizeof(*pmc))) | |
if r1 == 0 { | |
if e1 != 0 { | |
err = error(e1) | |
} else { | |
err = syscall.EINVAL | |
} | |
} | |
return | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment