原生標準庫在文件量過大時效率和內存均表現不好
1400萬文件遍歷Filepath.Walk
1400萬文件重寫直接調用windows api并處理細節
結論
1400萬文件遍歷時對比
對比條目 | filepath.walk | windows api并觸發黑科技 |
---|---|---|
運行時間 | 710秒 | 22秒 |
內存占用 | 480M | 38M |
關鍵代碼
//超級快的文件遍歷
func FindFileWin(dir string, callbackfunc MyFindFileCallBack) {dir = dir + `\`finstruct := win.WIN32_FIND_DATAW{}handle := win.FindFirstFileW(dir+`*`, &finstruct)if win.IsInvalidHandle(handle) {for {//文件夾if (finstruct.DwFileAttributes & win.FILE_ATTRIBUTE_DIRECTORY) != 0 {if (finstruct.CfileNameGo != "..") && (finstruct.CfileNameGo != ".") {FindFileWin(dir+finstruct.CfileNameGo, callbackfunc)}} else {callbackfunc(dir + finstruct.CfileNameGo)}if win.FindNextFileW(handle, &finstruct) == 0 {break}}}
}
var (kernel32 = syscall.NewLazyDLL("Kernel32.dll")procCreateFileW = kernel32.NewProc("CreateFileW")procOpenEventW = kernel32.NewProc("OpenEventW")procSetEvent = kernel32.NewProc("SetEvent")procFindFirstFileW = kernel32.NewProc("FindFirstFileW")procFindNextFileW = kernel32.NewProc("FindNextFileW")//procCreateFileA = kernel32.NewProc("CreateFileA")
)func FindFirstFileW(fileName string, lpFindFileData *WIN32_FIND_DATAW) HANDLE {strname := unsafe.Pointer(syscall.StringToUTF16Ptr(fileName))handle, _, _ := procFindFirstFileW.Call(uintptr(strname),uintptr(unsafe.Pointer(lpFindFileData)),)if handle != 0 {lpFindFileData.CfileNameGo = syscall.UTF16ToString(lpFindFileData.cFileName[:])}return HANDLE(handle)
}
func IsInvalidHandle(handle HANDLE) bool {if handle != 0 && int(handle) != -1 {return true}return false
}
func FindNextFileW(hFindFile HANDLE, lpFindFileData *WIN32_FIND_DATAW) BOOL {ret, _, _ := procFindNextFileW.Call(uintptr(hFindFile),uintptr(unsafe.Pointer(lpFindFileData)),)if ret != 0 {lpFindFileData.CfileNameGo = syscall.UTF16ToString(lpFindFileData.cFileName[:])}return BOOL(ret)
}