io.Copy比调用mv命令慢很多

时间:2018-07-14 03:29:14

标签: windows go

似乎io.Copy对我来说很慢:

   _,err = io.Copy(destf,srcf)

io.Copy需要更长的时间,大约需要2分钟才能将1GB的文件复制到网络共享中。注意,mv.exe最多可以在25秒内完成工作-因此,我开始为我的工作调用mv。

    output, err := exec.Command("mv", src, dest_folder).CombinedOutput()

这种缓慢的感觉在我的身上始终是可以重现的,关于如何加快速度的任何提示将不胜感激!

更新:

感谢使用io.CopyBuffer()的建议,但是mv.exe仍然是唯一的获胜者,可观的优势。

详细信息:

PS C:\temp> .\move_files.exe .\testfile.data "\\somehost\somefolder\bleh13.txt"
2018/07/14 19:04:54 Created C:\Temp\2\deleteME__913153343, copy of .\testfile.data, Size: 1073745920 bytes
2018/07/14 19:05:55 Transfer with io.Copy() took us 60.836702 seconds
2018/07/14 19:06:47 Transfer with io.CopyBuffer() took us 50.729625 seconds
2018/07/14 19:06:59 Transfer with mv command took us 11.470456 seconds
PS C:\temp>

欢迎您自己尝试:https://play.golang.org/p/2_lR83A4BXe

3 个答案:

答案 0 :(得分:3)

您比较复制和移动这是不同的事情。移动文件并不假定将所有数据的副本写入新的物理内存目标中,而只是重写文件系统中的某些标头/描述符。因此,为了获得适当的比较基准

答案 1 :(得分:2)

也许尝试io.CopyBufferio.Copy使用buffer of 32*1024 bytes

检查更大或更小的缓冲区大小是否有所不同。

答案 2 :(得分:2)

我继续建议尝试使用CopyFile Win32 API函数的评论,下面是一个包装它的工作程序:

package main

import (
    "log"
    "os"
    "syscall"
    "unsafe"
)

var (
    kernel32     = syscall.MustLoadDLL("kernel32.dll")
    copyFileProc = kernel32.MustFindProc("CopyFileW")
)

func CopyFile(src, dst string, overwrite bool) error {
    srcW := syscall.StringToUTF16(src)
    dstW := syscall.StringToUTF16(dst)

    var failIfExists uintptr
    if overwrite {
        failIfExists = 0
    } else {
        failIfExists = 1
    }

    rc, _, err := copyFileProc.Call(
        uintptr(unsafe.Pointer(&srcW[0])),
        uintptr(unsafe.Pointer(&dstW[0])),
        failIfExists)
    if rc == 0 {
        return &os.PathError{
            Op:   "CopyFile",
            Path: src,
            Err:  err,
        }
    }
    return nil
}

func main() {
    log.SetFlags(0)

    if len(os.Args) != 3 {
        log.Fatalf("Wrong # args.\nUsage: %s SOURCE DEST\n", os.Args[0])
    }

    err := CopyFile(os.Args[1], os.Args[2], false)
    if err != nil {
        log.Fatal("error copying file: ", err)
    }
}

请尝试一下,看看它是否比io.Copy*更好。