偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

帶你了解五種加速Go的特性和如何實(shí)現(xiàn)它們

開發(fā) 后端
我最近被邀請?jiān)?Gocon 發(fā)表演講,這是一個(gè)每半年在日本東京舉行的 Go 的精彩大會(huì)。Gocon 2014 是一個(gè)完全由社區(qū)驅(qū)動(dòng)的為期一天的活動(dòng),由培訓(xùn)和一整個(gè)下午的圍繞著生產(chǎn)環(huán)境中的 Go 這個(gè)主題的演講組成。

Anthony Starks 使用他出色的 Deck 演示工具重構(gòu)了我原來的基于 Google Slides 的幻燈片。你可以在他的博客上查看他重構(gòu)后的幻燈片, 

mindchunk.blogspot.com.au/2014/06/remixing-with-deck。

 

我最近被邀請?jiān)?Gocon 發(fā)表演講,這是一個(gè)每半年在日本東京舉行的 Go 的精彩大會(huì)。Gocon 2014 是一個(gè)完全由社區(qū)驅(qū)動(dòng)的為期一天的活動(dòng),由培訓(xùn)和一整個(gè)下午的圍繞著生產(chǎn)環(huán)境中的 Go 這個(gè)主題的演講組成。(LCTT 譯注:本文發(fā)表于 2014 年)

以下是我的講義。原文的結(jié)構(gòu)能讓我緩慢而清晰的演講,因此我已經(jīng)編輯了它使其更可讀。

我要感謝 Bill Kennedy 和 Minux Ma,特別是 Josh Bleecher Snyder,感謝他們在我準(zhǔn)備這次演講中的幫助。

大家下午好。

我叫 David.

我很高興今天能來到 Gocon。我想?yún)⒓舆@個(gè)會(huì)議已經(jīng)兩年了,我很感謝主辦方能提供給我向你們演講的機(jī)會(huì)。

Gocon 2014

Gocon 2014

我想以一個(gè)問題開始我的演講。

為什么選擇 Go?

當(dāng)大家討論學(xué)習(xí)或在生產(chǎn)環(huán)境中使用 Go 的原因時(shí),答案不一而足,但因?yàn)橐韵氯齻€(gè)原因的最多。

Gocon 2014

Gocon 2014

這就是 TOP3 的原因。

***,并發(fā)。

Go 的 并發(fā)原語Concurrency Primitives 對于來自 Nodejs,Ruby 或 Python 等單線程腳本語言的程序員,或者來自 C++ 或 Java 等重量級線程模型的語言都很有吸引力。

易于部署。

我們今天從經(jīng)驗(yàn)豐富的 Gophers 那里聽說過,他們非常欣賞部署 Go 應(yīng)用的簡單性。

Gocon 2014

Gocon 2014

然后是性能。

我相信人們選擇 Go 的一個(gè)重要原因是它 

Gocon 2014 (4)

Gocon 2014 (4)

在今天的演講中,我想討論五個(gè)有助于提高 Go 性能的特性。

我還將與大家分享 Go 如何實(shí)現(xiàn)這些特性的細(xì)節(jié)。

Gocon 2014 (5)

Gocon 2014 (5)

我要談的***個(gè)特性是 Go 對于值的高效處理和存儲(chǔ)。

Gocon 2014 (6)

Gocon 2014 (6)

這是 Go 中一個(gè)值的例子。編譯時(shí),gocon 正好消耗四個(gè)字節(jié)的內(nèi)存。

讓我們將 Go 與其他一些語言進(jìn)行比較

Gocon 2014 (7)

Gocon 2014 (7)

由于 Python 表示變量的方式的開銷,使用 Python 存儲(chǔ)相同的值會(huì)消耗六倍的內(nèi)存。

Python 使用額外的內(nèi)存來跟蹤類型信息,進(jìn)行 引用計(jì)數(shù)Reference Counting 等。

讓我們看另一個(gè)例子:

Gocon 2014 (8)

Gocon 2014 (8)

與 Go 類似,Java 消耗 4 個(gè)字節(jié)的內(nèi)存來存儲(chǔ) int 型。

但是,要在像 List 或 Map 這樣的集合中使用此值,編譯器必須將其轉(zhuǎn)換為 Integer 對象。

Gocon 2014 (9)

Gocon 2014 (9)

因此,Java 中的整數(shù)通常消耗 16 到 24 個(gè)字節(jié)的內(nèi)存。

為什么這很重要? 內(nèi)存便宜且充足,為什么這個(gè)開銷很重要?

Gocon 2014 (10)

Gocon 2014 (10)

這是一張顯示 CPU 時(shí)鐘速度與內(nèi)存總線速度的圖表。

請注意 CPU 時(shí)鐘速度和內(nèi)存總線速度之間的差距如何繼續(xù)擴(kuò)大。

兩者之間的差異實(shí)際上是 CPU 花費(fèi)多少時(shí)間等待內(nèi)存。

Gocon 2014 (11)

Gocon 2014 (11)

自 1960 年代后期以來,CPU 設(shè)計(jì)師已經(jīng)意識(shí)到了這個(gè)問題。

他們的解決方案是一個(gè)緩存,一個(gè)更小、更快的內(nèi)存區(qū)域,介入 CPU 和主存之間。

Gocon 2014 (12)

Gocon 2014 (12)

這是一個(gè) Location 類型,它保存物體在三維空間中的位置。它是用 Go 編寫的,因此每個(gè) Location 只消耗 24 個(gè)字節(jié)的存儲(chǔ)空間。

我們可以使用這種類型來構(gòu)造一個(gè)容納 1000 個(gè) Location 的數(shù)組類型,它只消耗 24000 字節(jié)的內(nèi)存。

在數(shù)組內(nèi)部,Location 結(jié)構(gòu)體是順序存儲(chǔ)的,而不是隨機(jī)存儲(chǔ)的 1000 個(gè) Location 結(jié)構(gòu)體的指針。

這很重要,因?yàn)楝F(xiàn)在所有 1000 個(gè) Location 結(jié)構(gòu)體都按順序放在緩存中,緊密排列在一起。

Gocon 2014 (13)

Gocon 2014 (13)

Go 允許您創(chuàng)建緊湊的數(shù)據(jù)結(jié)構(gòu),避免不必要的填充字節(jié)。

緊湊的數(shù)據(jù)結(jié)構(gòu)能更好地利用緩存。

更好的緩存利用率可帶來更好的性能。

Gocon 2014 (14)

Gocon 2014 (14)

函數(shù)調(diào)用不是無開銷的。

Gocon 2014 (15)

Gocon 2014 (15)

調(diào)用函數(shù)時(shí)會(huì)發(fā)生三件事。

創(chuàng)建一個(gè)新的 棧幀Stack Frame,并記錄調(diào)用者的詳細(xì)信息。

在函數(shù)調(diào)用期間可能被覆蓋的任何寄存器都將保存到棧中。

處理器計(jì)算函數(shù)的地址并執(zhí)行到該新地址的分支。

Gocon 2014 (16)

Gocon 2014 (16)

由于函數(shù)調(diào)用是非常常見的操作,因此 CPU 設(shè)計(jì)師一直在努力優(yōu)化此過程,但他們無法消除開銷。

函調(diào)固有開銷,或重于泰山,或輕于鴻毛,這取決于函數(shù)做了什么。

減少函數(shù)調(diào)用開銷的解決方案是 內(nèi)聯(lián)Inlining。

Gocon 2014 (17)

Gocon 2014 (17)

Go 編譯器通過將函數(shù)體視為調(diào)用者的一部分來內(nèi)聯(lián)函數(shù)。

內(nèi)聯(lián)也有成本,它增加了二進(jìn)制文件大小。

只有當(dāng)調(diào)用開銷與函數(shù)所做工作關(guān)聯(lián)度的很大時(shí)內(nèi)聯(lián)才有意義,因此只有簡單的函數(shù)才能用于內(nèi)聯(lián)。

復(fù)雜的函數(shù)通常不受調(diào)用它們的開銷所支配,因此不會(huì)內(nèi)聯(lián)。

Gocon 2014 (18)

Gocon 2014 (18)

這個(gè)例子顯示函數(shù) Double 調(diào)用 util.Max

為了減少調(diào)用 util.Max 的開銷,編譯器可以將 util.Max 內(nèi)聯(lián)到 Double 中,就象這樣

Gocon 2014 (19)

Gocon 2014 (19)

內(nèi)聯(lián)后不再調(diào)用 util.Max,但是 Double 的行為沒有改變。

內(nèi)聯(lián)并不是 Go 獨(dú)有的。幾乎每種編譯或及時(shí)編譯的語言都執(zhí)行此優(yōu)化。但是 Go 的內(nèi)聯(lián)是如何實(shí)現(xiàn)的?

Go 實(shí)現(xiàn)非常簡單。編譯包時(shí),會(huì)標(biāo)記任何適合內(nèi)聯(lián)的小函數(shù),然后照常編譯。

然后函數(shù)的源代碼和編譯后版本都會(huì)被存儲(chǔ)。

Gocon 2014 (20)

Gocon 2014 (20)

此幻燈片顯示了 util.a 的內(nèi)容。源代碼已經(jīng)過一些轉(zhuǎn)換,以便編譯器更容易快速處理。

當(dāng)編譯器編譯 Double 時(shí),它看到 util.Max 可內(nèi)聯(lián)的,并且 util.Max 的源代碼是可用的。

就會(huì)替換原函數(shù)中的代碼,而不是插入對 util.Max 的編譯版本的調(diào)用。

擁有該函數(shù)的源代碼可以實(shí)現(xiàn)其他優(yōu)化。

Gocon 2014 (21)

Gocon 2014 (21)

在這個(gè)例子中,盡管函數(shù) Test 總是返回 false,但 Expensive 在不執(zhí)行它的情況下無法知道結(jié)果。

當(dāng) Test 被內(nèi)聯(lián)時(shí),我們得到這樣的東西。

Gocon 2014 (22)

Gocon 2014 (22)

編譯器現(xiàn)在知道 Expensive 的代碼無法訪問。

這不僅節(jié)省了調(diào)用 Test 的成本,還節(jié)省了編譯或運(yùn)行任何現(xiàn)在無法訪問的 Expensive 代碼。

Go 編譯器可以跨文件甚至跨包自動(dòng)內(nèi)聯(lián)函數(shù)。還包括從標(biāo)準(zhǔn)庫調(diào)用的可內(nèi)聯(lián)函數(shù)的代碼。

Gocon 2014 (23)

Gocon 2014 (23)

強(qiáng)制垃圾回收Mandatory Garbage Collection 使 Go 成為一種更簡單,更安全的語言。

這并不意味著垃圾回收會(huì)使 Go 變慢,或者垃圾回收是程序速度的瓶頸。

這意味著在堆上分配的內(nèi)存是有代價(jià)的。每次 GC 運(yùn)行時(shí)都會(huì)花費(fèi) CPU 時(shí)間,直到釋放內(nèi)存為止。

Gocon 2014 (24)

Gocon 2014 (24)

然而,有另一個(gè)地方分配內(nèi)存,那就是棧。

與 C 不同,它強(qiáng)制您選擇是否將值通過 malloc 將其存儲(chǔ)在堆上,還是通過在函數(shù)范圍內(nèi)聲明將其儲(chǔ)存在棧上;Go 實(shí)現(xiàn)了一個(gè)名為 逃逸分析Escape Analysis 的優(yōu)化。

Gocon 2014 (25)

Gocon 2014 (25)

逃逸分析決定了對一個(gè)值的任何引用是否會(huì)從被聲明的函數(shù)中逃逸。

如果沒有引用逃逸,則該值可以安全地存儲(chǔ)在棧中。

存儲(chǔ)在棧中的值不需要分配或釋放。

讓我們看一些例子

Gocon 2014 (26)

Gocon 2014 (26)

Sum 返回 1 到 100 的整數(shù)的和。這是一種相當(dāng)不尋常的做法,但它說明了逃逸分析的工作原理。

因?yàn)榍衅?nbsp;numbers 僅在 Sum 內(nèi)引用,所以編譯器將安排到棧上來存儲(chǔ)的 100 個(gè)整數(shù),而不是安排到堆上。

沒有必要回收 numbers,它會(huì)在 Sum 返回時(shí)自動(dòng)釋放。

Gocon 2014 (27)

Gocon 2014 (27)

第二個(gè)例子也有點(diǎn)尬。在 CenterCursor 中,我們創(chuàng)建一個(gè)新的 Cursor 對象并在 c 中存儲(chǔ)指向它的指針。

然后我們將 c 傳遞給 Center() 函數(shù),它將 Cursor 移動(dòng)到屏幕的中心。

***我們打印出那個(gè) ‘Cursor` 的 X 和 Y 坐標(biāo)。

即使 c 被 new 函數(shù)分配了空間,它也不會(huì)存儲(chǔ)在堆上,因?yàn)闆]有引用 c 的變量逃逸 CenterCursor 函數(shù)。

Gocon 2014 (28)

Gocon 2014 (28)

默認(rèn)情況下,Go 的優(yōu)化始終處于啟用狀態(tài)。可以使用 -gcflags = -m 開關(guān)查看編譯器的逃逸分析和內(nèi)聯(lián)決策。

因?yàn)樘右莘治鍪窃诰幾g時(shí)執(zhí)行的,而不是運(yùn)行時(shí),所以無論垃圾回收的效率如何,棧分配總是比堆分配快。

我將在本演講的其余部分詳細(xì)討論棧。

Gocon 2014 (29)

Gocon 2014 (29)

Go 有 goroutine。 這是 Go 并發(fā)的基石。

我想退一步,探索 goroutine 的歷史。

最初,計(jì)算機(jī)一次運(yùn)行一個(gè)進(jìn)程。在 60 年代,多進(jìn)程或 分時(shí)Time Sharing 的想法變得流行起來。

在分時(shí)系統(tǒng)中,操作系統(tǒng)必須通過保護(hù)當(dāng)前進(jìn)程的現(xiàn)場,然后恢復(fù)另一個(gè)進(jìn)程的現(xiàn)場,不斷地在這些進(jìn)程之間切換 CPU 的注意力。

這稱為 進(jìn)程切換。

Gocon 2014 (30)

Gocon 2014 (30)

進(jìn)程切換有三個(gè)主要開銷。

首先,內(nèi)核需要保護(hù)該進(jìn)程的所有 CPU 寄存器的現(xiàn)場,然后恢復(fù)另一個(gè)進(jìn)程的現(xiàn)場。

內(nèi)核還需要將 CPU 的映射從虛擬內(nèi)存刷新到物理內(nèi)存,因?yàn)檫@些映射僅對當(dāng)前進(jìn)程有效。

***是操作系統(tǒng) 上下文切換Context Switch 的成本,以及 調(diào)度函數(shù)Scheduler Function 選擇占用 CPU 的下一個(gè)進(jìn)程的開銷。

Gocon 2014 (31)

Gocon 2014 (31)

現(xiàn)代處理器中有數(shù)量驚人的寄存器。我很難在一張幻燈片上排開它們,這可以讓你知道保護(hù)和恢復(fù)它們需要多少時(shí)間。

由于進(jìn)程切換可以在進(jìn)程執(zhí)行的任何時(shí)刻發(fā)生,因此操作系統(tǒng)需要存儲(chǔ)所有寄存器的內(nèi)容,因?yàn)樗恢喇?dāng)前正在使用哪些寄存器。

Gocon 2014 (32)

Gocon 2014 (32)

這導(dǎo)致了線程的出生,這些線程在概念上與進(jìn)程相同,但共享相同的內(nèi)存空間。

由于線程共享地址空間,因此它們比進(jìn)程更輕,因此創(chuàng)建速度更快,切換速度更快。

Gocon 2014 (33)

Gocon 2014 (33)

Goroutine 升華了線程的思想。

Goroutine 是 協(xié)作式調(diào)度Cooperative Scheduled
的,而不是依靠內(nèi)核來調(diào)度。

當(dāng)對 Go 運(yùn)行時(shí)調(diào)度器Runtime Scheduler 進(jìn)行顯式調(diào)用時(shí),goroutine 之間的切換僅發(fā)生在明確定義的點(diǎn)上。

編譯器知道正在使用的寄存器并自動(dòng)保存它們。

Gocon 2014 (34)

Gocon 2014 (34)

雖然 goroutine 是協(xié)作式調(diào)度的,但運(yùn)行時(shí)會(huì)為你處理。

Goroutine 可能會(huì)給禪讓給其他協(xié)程時(shí)刻是:

  • 阻塞式通道發(fā)送和接收。
  • Go 聲明,雖然不能保證會(huì)立即調(diào)度新的 goroutine。
  • 文件和網(wǎng)絡(luò)操作式的阻塞式系統(tǒng)調(diào)用。
  • 在被垃圾回收循環(huán)停止后。

Gocon 2014 (35)

Gocon 2014 (35)

這個(gè)例子說明了上一張幻燈片中描述的一些調(diào)度點(diǎn)。

箭頭所示的線程從左側(cè)的 ReadFile 函數(shù)開始。遇到 os.Open,它在等待文件操作完成時(shí)阻塞線程,因此調(diào)度器將線程切換到右側(cè)的 goroutine。

繼續(xù)執(zhí)行直到從通道 c 中讀,并且此時(shí) os.Open 調(diào)用已完成,因此調(diào)度器將線程切換回左側(cè)并繼續(xù)執(zhí)行 file.Read 函數(shù),然后又被文件 IO 阻塞。

調(diào)度器將線程切換回右側(cè)以進(jìn)行另一個(gè)通道操作,該操作在左側(cè)運(yùn)行期間已解鎖,但在通道發(fā)送時(shí)再次阻塞。

***,當(dāng) Read 操作完成并且數(shù)據(jù)可用時(shí),線程切換回左側(cè)。

Gocon 2014 (36)

Gocon 2014 (36)

這張幻燈片顯示了低級語言描述的 runtime.Syscall 函數(shù),它是 os 包中所有函數(shù)的基礎(chǔ)。

只要你的代碼調(diào)用操作系統(tǒng),就會(huì)通過此函數(shù)。

對 entersyscall 的調(diào)用通知運(yùn)行時(shí)該線程即將阻塞。

這允許運(yùn)行時(shí)啟動(dòng)一個(gè)新線程,該線程將在當(dāng)前線程被阻塞時(shí)為其他 goroutine 提供服務(wù)。

這導(dǎo)致每 Go 進(jìn)程的操作系統(tǒng)線程相對較少,Go 運(yùn)行時(shí)負(fù)責(zé)將可運(yùn)行的 Goroutine 分配給空閑的操作系統(tǒng)線程。

Gocon 2014 (37)

Gocon 2014 (37)

在上一節(jié)中,我討論了 goroutine 如何減少管理許多(有時(shí)是數(shù)十萬個(gè)并發(fā)執(zhí)行線程)的開銷。

Goroutine故事還有另一面,那就是棧管理,它引導(dǎo)我進(jìn)入我的***一個(gè)話題。

Gocon 2014 (39)

Gocon 2014 (38)

這是一個(gè)進(jìn)程的內(nèi)存布局圖。我們感興趣的關(guān)鍵是堆和棧的位置。

傳統(tǒng)上,在進(jìn)程的地址空間內(nèi),堆位于內(nèi)存的底部,位于程序(代碼)的上方并向上增長。

棧位于虛擬地址空間的頂部,并向下增長。

Gocon 2014 (40)

Gocon 2014 (39)

因?yàn)槎押蜅O嗷ジ采w的結(jié)果會(huì)是災(zāi)難性的,操作系統(tǒng)通常會(huì)安排在棧和堆之間放置一個(gè)不可寫內(nèi)存區(qū)域,以確保如果它們發(fā)生碰撞,程序?qū)⒅兄埂?/p>

這稱為保護(hù)頁,有效地限制了進(jìn)程的棧大小,通常大約為幾兆字節(jié)。

Gocon 2014 (41)

Gocon 2014 (40)

我們已經(jīng)討論過線程共享相同的地址空間,因此對于每個(gè)線程,它必須有自己的棧。

由于很難預(yù)測特定線程的棧需求,因此為每個(gè)線程的棧和保護(hù)頁面保留了大量內(nèi)存。

希望是這些區(qū)域永遠(yuǎn)不被使用,而且防護(hù)頁永遠(yuǎn)不會(huì)被擊中。

缺點(diǎn)是隨著程序中線程數(shù)的增加,可用地址空間的數(shù)量會(huì)減少。

Gocon 2014 (42)

Gocon 2014 (41)

我們已經(jīng)看到 Go 運(yùn)行時(shí)將大量的 goroutine 調(diào)度到少量線程上,但那些 goroutines 的棧需求呢?

Go 編譯器不使用保護(hù)頁,而是在每個(gè)函數(shù)調(diào)用時(shí)插入一個(gè)檢查,以檢查是否有足夠的棧來運(yùn)行該函數(shù)。如果沒有,運(yùn)行時(shí)可以分配更多的??臻g。

由于這種檢查,goroutines 初始棧可以做得更小,這反過來允許 Go 程序員將 goroutines 視為廉價(jià)資源。

Gocon 2014 (43)

Gocon 2014 (42)

這是一張顯示了 Go 1.2 如何管理?xiàng)5幕脽羝?/p>

當(dāng) G 調(diào)用 H 時(shí),沒有足夠的空間讓 H 運(yùn)行,所以運(yùn)行時(shí)從堆中分配一個(gè)新的棧幀,然后在新的棧段上運(yùn)行 H。當(dāng) H 返回時(shí),棧區(qū)域返回到堆,然后返回到 G

Gocon 2014 (44)

Gocon 2014 (43)

這種管理?xiàng)5姆椒ㄍǔ:芎糜?,但對于某些類型的代碼,通常是遞歸代碼,它可能導(dǎo)致程序的內(nèi)部循環(huán)跨越這些棧邊界之一。

例如,在程序的內(nèi)部循環(huán)中,函數(shù) G 可以在循環(huán)中多次調(diào)用 H,

每次都會(huì)導(dǎo)致棧拆分。 這被稱為 熱分裂Hot Split 問題。

Gocon 2014 (45)

Gocon 2014 (44)

為了解決熱分裂問題,Go 1.3 采用了一種新的棧管理方法。

如果 goroutine 的棧太小,則不會(huì)添加和刪除其他棧段,而是分配新的更大的棧。

舊棧的內(nèi)容被復(fù)制到新棧,然后 goroutine 使用新的更大的棧繼續(xù)運(yùn)行。

在***次調(diào)用 H 之后,棧將足夠大,對可用棧空間的檢查將始終成功。

這解決了熱分裂問題。

Gocon 2014 (46)

Gocon 2014 (45)

值,內(nèi)聯(lián),逃逸分析,Goroutines 和分段/復(fù)制棧。

這些是我今天選擇談?wù)摰奈鍌€(gè)特性,但它們絕不是使 Go 成為快速的語言的唯一因素,就像人們引用他們學(xué)習(xí) Go 的理由的三個(gè)原因一樣。

這五個(gè)特性一樣強(qiáng)大,它們不是孤立存在的。

例如,運(yùn)行時(shí)將 goroutine 復(fù)用到線程上的方式在沒有可擴(kuò)展棧的情況下幾乎沒有效率。

內(nèi)聯(lián)通過將較小的函數(shù)組合成較大的函數(shù)來降低棧大小檢查的成本。

逃逸分析通過自動(dòng)將從實(shí)例從堆移動(dòng)到棧來減少垃圾回收器的壓力。

逃逸分析還提供了更好的 緩存局部性Cache Locality。

如果沒有可增長的棧,逃逸分析可能會(huì)對棧施加太大的壓力。

Gocon 2014 (47)

Gocon 2014 (46)

  • 感謝 Gocon 主辦方允許我今天發(fā)言
  • twitter / web / email details
  • 感謝 @offbymany,@billkennedy_go 和 Minux 在準(zhǔn)備這個(gè)演講的過程中所提供的幫助。

 

 

 

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2022-02-22 23:39:15

JavaScript編程語言Web

2020-07-12 22:09:38

智能工廠物聯(lián)網(wǎng)基礎(chǔ)設(shè)施安全風(fēng)險(xiǎn)

2022-08-01 10:41:51

談判策略CIO

2018-09-11 09:00:50

工具開發(fā)應(yīng)用程序

2021-10-19 07:27:08

HTTP代理網(wǎng)絡(luò)

2021-03-10 08:55:42

Go數(shù)據(jù)語言

2022-02-23 09:36:11

GoRuby編程語言

2018-03-01 16:25:52

Linux內(nèi)核內(nèi)存管理

2024-08-13 11:13:18

2024-07-15 08:00:00

2022-02-02 21:29:39

路由模式Vue-Router

2021-09-27 07:39:52

Go初始化函數(shù)package

2023-01-11 10:29:26

2020-02-19 19:26:27

K8S開源平臺(tái)容器技術(shù)

2022-06-09 10:33:46

欺騙工具網(wǎng)絡(luò)攻擊

2022-01-17 08:56:05

CSS 技巧代碼重構(gòu)

2023-05-16 14:44:07

2019-09-20 08:00:00

開發(fā)技能Web開發(fā) 人工智能

2023-04-28 07:49:13

Javawaitsleep

2020-09-01 15:57:12

云安全云遷移云計(jì)算
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號