第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

為什么要在 Windows 上使用 cgo 來(lái)實(shí)現(xiàn)簡(jiǎn)單的 File.Write?

為什么要在 Windows 上使用 cgo 來(lái)實(shí)現(xiàn)簡(jiǎn)單的 File.Write?

Go
倚天杖 2021-12-20 14:46:03
將一個(gè)簡(jiǎn)單的程序從 C# 重寫(xiě)為 Go,我發(fā)現(xiàn)生成的可執(zhí)行文件慢了 3 到 4 倍。特別是 Go 版本使用 3 到 4 倍的 CPU。令人驚訝的是,該代碼執(zhí)行了許多 I/O,并且不應(yīng)該消耗大量 CPU。我制作了一個(gè)非常簡(jiǎn)單的版本,只進(jìn)行順序?qū)懭?,并制作了基?zhǔn)測(cè)試。我在 Windows 10 和 Linux (Debian Jessie) 上運(yùn)行了相同的基準(zhǔn)測(cè)試。時(shí)間無(wú)法比較(不同的系統(tǒng),磁盤(pán),...)但結(jié)果很有趣。我在兩個(gè)平臺(tái)上使用相同的 Go 版本:1.6在 Windows os.File.Write 上使用 cgo(見(jiàn)runtime.cgocall下文),而不是在 Linux 上。為什么 ?這是 disk.go 程序:    package main    import (        "crypto/rand"        "fmt"        "os"        "time"    )    const (        // size of the test file        fullSize = 268435456        // size of read/write per call        partSize = 128        // path of temporary test file        filePath = "./bigfile.tmp"    )    func main() {        buffer := make([]byte, partSize)        seqWrite := func() error {            return sequentialWrite(filePath, fullSize, buffer)        }        err := fillBuffer(buffer)        panicIfError(err)        duration, err := durationOf(seqWrite)        panicIfError(err)        fmt.Printf("Duration : %v\n", duration)    }    // It's just a test ;)    func panicIfError(err error) {        if err != nil {            panic(err)        }    }    func durationOf(f func() error) (time.Duration, error) {        startTime := time.Now()        err := f()        return time.Since(startTime), err    }    func fillBuffer(buffer []byte) error {        _, err := rand.Read(buffer)        return err    }    func sequentialWrite(filePath string, fullSize int, buffer []byte) error {        desc, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)        if err != nil {            return err        }        defer func() {            desc.Close()            err := os.Remove(filePath)            panicIfError(err)        }()        var totalWrote int        for totalWrote < fullSize {            wrote, err := desc.Write(buffer)            totalWrote += wrote            if err != nil {                return err            }        }        return nil    }
查看完整描述

1 回答

?
浮云間

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超4個(gè)贊

Go 不執(zhí)行文件 I/O,它將任務(wù)委托給操作系統(tǒng)。請(qǐng)參閱 Go 操作系統(tǒng)依賴(lài)syscall包。

Linux 和 Windows 是具有不同 OS ABI 的不同操作系統(tǒng)。例如,Linux 使用系統(tǒng)調(diào)用 viasyscall.Syscall而 Windows 使用 Windows dll。在 Windows 上,dll 調(diào)用是 C 調(diào)用。它不使用cgo. 它不會(huì)去通過(guò)使用相同的動(dòng)態(tài)的C指針檢查cgoruntime.cgocall。沒(méi)有runtime.wincall別名。

綜上所述,不同的操作系統(tǒng)有不同的操作系統(tǒng)調(diào)用機(jī)制。

命令 cgo

傳遞指針

Go 是一種垃圾收集語(yǔ)言,垃圾收集器需要知道每個(gè)指向 Go 內(nèi)存的指針的位置。因此,在 Go 和 C 之間傳遞指針存在限制。

在本節(jié)中,術(shù)語(yǔ) Go 指針表示指向由 Go 分配的內(nèi)存的指針(例如通過(guò)使用 & 運(yùn)算符或調(diào)用預(yù)定義的新函數(shù)),術(shù)語(yǔ) C 指針表示指向由 C 分配的內(nèi)存的指針(例如通過(guò)調(diào)用C.malloc)。一個(gè)指針是 Go 指針還是 C 指針是由內(nèi)存分配方式?jīng)Q定的動(dòng)態(tài)屬性;它與指針的類(lèi)型無(wú)關(guān)。

如果 Go 代碼指向的 Go 內(nèi)存不包含任何 Go 指針,則 Go 代碼可以將 Go 指針傳遞給 C。C 代碼必須保留這個(gè)屬性:它不能在 Go 內(nèi)存中存儲(chǔ)任何 Go 指針,即使是臨時(shí)的。當(dāng)傳遞指向結(jié)構(gòu)體中字段的指針時(shí),所討論的 Go 內(nèi)存是該字段占用的內(nèi)存,而不是整個(gè)結(jié)構(gòu)體。當(dāng)傳遞指向數(shù)組或切片中元素的指針時(shí),所討論的 Go 內(nèi)存是整個(gè)數(shù)組或切片的整個(gè)后備數(shù)組。

C 代碼可能不會(huì)在調(diào)用返回后保留 Go 指針的副本。

C 代碼調(diào)用的 Go 函數(shù)可能不會(huì)返回 Go 指針。C 代碼調(diào)用的 Go 函數(shù)可能以 C 指針作為參數(shù),它可能通過(guò)這些指針存儲(chǔ)非指針或 C 指針數(shù)據(jù),但它可能不會(huì)在 C 指針指向的內(nèi)存中存儲(chǔ) Go 指針。C 代碼調(diào)用的 Go 函數(shù)可以將 Go 指針作為參數(shù),但它必須保留它所指向的 Go 內(nèi)存不包含任何 Go 指針的屬性。

Go 代碼可能不會(huì)在 C 內(nèi)存中存儲(chǔ) Go 指針。C 代碼可以將 Go 指針存儲(chǔ)在 C 內(nèi)存中,受上述規(guī)則的約束:當(dāng) C 函數(shù)返回時(shí),它必須停止存儲(chǔ) Go 指針。

這些規(guī)則在運(yùn)行時(shí)動(dòng)態(tài)檢查。檢查由 GODEBUG 環(huán)境變量的 cgocheck 設(shè)置控制。默認(rèn)設(shè)置是 GODEBUG=cgocheck=1,它實(shí)現(xiàn)了相當(dāng)便宜的動(dòng)態(tài)檢查??梢允褂?GODEBUG=cgocheck=0 完全禁用這些檢查。通過(guò) GODEBUG=cgocheck=2 可以在運(yùn)行時(shí)以一定的代價(jià)完成指針處理的檢查。

可以通過(guò)使用 unsafe 包來(lái)破壞這種強(qiáng)制執(zhí)行,當(dāng)然沒(méi)有什么可以阻止 C 代碼做任何它喜歡的事情。然而,違反這些規(guī)則的程序很可能會(huì)以意想不到和不可預(yù)測(cè)的方式失敗。

“這些規(guī)則在運(yùn)行時(shí)動(dòng)態(tài)檢查?!?/p>


基準(zhǔn):

換句話(huà)說(shuō),有謊言、該死的謊言和基準(zhǔn)。

為了跨操作系統(tǒng)進(jìn)行有效比較,您需要在相同的硬件上運(yùn)行。例如,CPU、內(nèi)存和 Rust 或硅磁盤(pán) I/O 之間的差異。我在同一臺(tái)機(jī)器上雙引導(dǎo) Linux 和 Windows。

連續(xù)運(yùn)行基準(zhǔn)測(cè)試至少 3 次。操作系統(tǒng)試圖變得智能。例如,緩存 I/O。使用虛擬機(jī)的語(yǔ)言需要預(yù)熱時(shí)間。等等。

知道你在測(cè)量什么。如果您正在執(zhí)行順序 I/O,您幾乎將所有時(shí)間都花在操作系統(tǒng)上。您是否關(guān)閉了惡意軟件保護(hù)?等等。

等等。

以下是disk.go使用雙引導(dǎo) Windows 和 Linux 的同一臺(tái)機(jī)器的一些結(jié)果。

視窗:

>go build disk.go

>/TimeMem disk

Duration : 18.3300322s

Elapsed time   : 18.38

Kernel time    : 13.71 (74.6%)

User time      : 4.62 (25.1%)

Linux:


$ go build disk.go

$ time ./disk

Duration : 18.54350723s

real    0m18.547s

user    0m2.336s

sys     0m16.236s

實(shí)際上,它們是相同的,disk.go持續(xù)時(shí)間為18 秒。操作系統(tǒng)之間只是在計(jì)算用戶(hù)時(shí)間和計(jì)算內(nèi)核或系統(tǒng)時(shí)間方面有所不同。流逝時(shí)間或?qū)崟r(shí)時(shí)間是相同的。


在您的測(cè)試中,內(nèi)核或系統(tǒng)時(shí)間分別為 93.72% runtime.cgocall和 95.49% syscall.Syscall。


查看完整回答
反對(duì) 回復(fù) 2021-12-20
  • 1 回答
  • 0 關(guān)注
  • 162 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)