自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

網(wǎng)絡(luò)架構(gòu)之路(二):性能

網(wǎng)絡(luò)
我們在上一篇博客中設(shè)定了架構(gòu)的目標(biāo),只有一個,就是可維護性。完全沒有提性能,這是故意的。

我們在上一篇博客中設(shè)定了架構(gòu)的目標(biāo),只有一個,就是可維護性。完全沒有提性能,這是故意的。

似乎程序員都是急性子,或許是被windows冗長的開機時間折磨夠了,有可能是因為提升性能的效果是最顯而易見的……總之,我發(fā)現(xiàn),絕大部分程序員對性能的關(guān)注和熱情是無與倫比的!

C#剛剛推出的時候,就有人搖頭晃腦的說,“嗯,自動垃圾回收,性能不行吧?”

DataSet橫空出世,馬上有很多人寫代碼,在DataSet里插入幾百萬條數(shù)據(jù),證明DataSet的性能問題

Linq當(dāng)然更要被罵了,尼瑪用反射?反射是什么,同學(xué)們知道么?性能大老虎呀!更不用說那些自動生成的sql了,有我手寫的高效么?

……

所以直到今天,我仍然看到很多程序員無怨無悔的用存儲過程來構(gòu)建他們的系統(tǒng),一個存儲過程可以有幾千行!然后,他們很無辜的問,“業(yè)務(wù)層有什么用?究竟能干些什么呢?”

在帶團隊的時候,我最怕講的就是性能有關(guān)的問題。你要是不談性能呢,那代碼有時候真心看不下去;你要是強調(diào)性能呢,不知道他會給你整出什么幺蛾子出來。其實這就是一個“度”的掌握,所以非常難以用語言予以表示清楚。所以無數(shù)次挫敗之后,我只好咬牙切齒的說,“你的代碼,只有一個評判標(biāo)準(zhǔn),可維護性。性能的問題先不管!”這個答案似乎并不能服眾——尤其是對有上進心的程序員而言。

所以,我先專篇講性能,希望能幫助大家更清楚的認識這個問題。

一、性能不是不重要,而是他沒有可維護性重要。要理解這一點,首先要理解可維護性的重要(請再讀上一篇我花數(shù)周找bug的段子);然后要明白:解決性能問題,我們可以有很多代碼以外行之有效的方法,而可維護性基本上就只能靠代碼了;最后,還是要牢記:沒有犧牲,就沒有勝利!

二、所以,在絕大多數(shù)情況下,當(dāng)性能和可維護性相沖突的時候,性能讓位于可維護性。我們采用其他辦法來彌補代碼性能不夠高的問題。

空洞的說教沒有意義。我們還是舉例來說明吧!

破壞可讀性

前段時間我review代碼的時候發(fā)現(xiàn),這個程序員用Linq之后老是用First()而不是Single(),我就奇怪了,按業(yè)務(wù)邏輯,返回的值就應(yīng)該是一個,難道可能會是多個,多個應(yīng)報異常,不應(yīng)該取First()就完事了呀?想了一會兒,問這個程序員,他的回答讓我瞬間一種無力感,“First()性能更高呀!”以下為對話實錄:

“你怎么知道First()性能更高呢?”我問。

“First()嘛,取了第一個合格的值就返回,就不會繼續(xù)查下去了;Single()的話,就會一直查,查出所有數(shù)據(jù),然后再取其中的一個。”

“你確定?你知道有一種東西叫做索引不?”

“啊?……”

然后我簡單的告訴他,索引是一種樹狀結(jié)構(gòu),可以讓查詢更快等等。

“但我還是覺得應(yīng)該用First()”,他想了一會兒,還是很堅定。

“為什么?”,我不明白了。

“就算有索引加快了查詢速度,但用First()在加快了速度上更快呀!更快總是沒錯的吧?”

“……”,我真不知道該怎么說了,最后突然靈光一閃,“好吧,那你說說,微軟為什么要搞一個Single()方法出來呢?就為了搞出來誤導(dǎo)你們?讓用First()的產(chǎn)生優(yōu)越感,嘲笑用Single()的?”

他陷入了沉思。

我剛?cè)胄械臅r候,還很是收藏了幾篇文章,比如《高性能編程的十大準(zhǔn)則》之類的,里面的內(nèi)容大致就是,“總是使用StringBuilder,不要使用‘+’;總是使用……,不要使用……”。這類文章下面總是有一堆人叫好,“不錯!”,“謝謝分享!”但慢慢的,我就對這些文章產(chǎn)生了懷疑(也應(yīng)該感謝園子里的老趙,csdn里面的sp1234之類的大神);直到很后來,我才明白為什么這種說法是膚淺的;而只有通過上面的對話,我才能清晰的把我的理解說出來。

所有這些犧牲性能的簡單封裝,都是有其目的的;而其中一個很重要的目的,就是為了提高可讀性。你為了性能,故意不使用這些現(xiàn)成的封裝,通常,喪失的就是可讀性。

想當(dāng)然

繼續(xù)上面這個例子。最開始的時候,這個程序員關(guān)于性能的考慮其實是想當(dāng)然的。這種想當(dāng)然的情形很多,大致有這幾種:

自己的理解完全就是錯的

自己的理解不能算錯,但實際上底層已經(jīng)對該問題做了優(yōu)化

自己的理解沒錯,底層也沒優(yōu)化

第1、2種比較好理解,第3種為什么也說他“想當(dāng)然”呢?因為沒有和硬件環(huán)境相契合。

最簡單的例子就是“緩存”。比如面試的時候,問你一個問題,“緩存能不能提高性能?”請注意,這是一個陷阱。答案應(yīng)該是:“不一定”。幾乎所有的人都認為,緩存可以迅速改善性能,是因為今天計算機的CPU和磁盤運行速度,遠跟不上內(nèi)存的發(fā)展。但即使如此,無節(jié)制的緩存,一樣可以拖垮整個系統(tǒng)。

類似的例子還有很多。你沾沾自喜,我節(jié)約了一次磁盤讀寫的時候,你同時增加了CPU的負荷;你優(yōu)化了算法,減少了CPU的運算,但其實增加了內(nèi)存的壓力……天下沒有免費的午餐。同樣的代碼,隨著數(shù)據(jù)的增加,硬件的改變,會呈現(xiàn)出截然不同的性能表現(xiàn)。

所以,開發(fā)過程中,很多的“優(yōu)化”,其實只是你的想當(dāng)然。與其這樣想當(dāng)然的優(yōu)化,不如在拿到性能測試結(jié)果之后再有的放矢的進行優(yōu)化。這時候,又回到了我們之前說的,是不是代碼的可讀性更重要?這樣你才能迅速的找到該優(yōu)化的瓶頸啊!否則,一堆亂七八糟看都看不懂的代碼,你怎么去優(yōu)化,你連該優(yōu)化的點都找不到。

難以維護

另一個搞笑的例子是關(guān)于我自己的。創(chuàng)業(yè)家園項目里有一個功能:顯示博客正文的同時提供一個上一頁下一頁的鏈接。慣常的做法就是直接在數(shù)據(jù)庫里查就是了,但我總覺得不對,這樣做兩次查詢有必要么?能不能優(yōu)化?于是我想到了一個“絕妙”的點子:為什么不直接在博客里存儲上一篇和下一篇的Id呢?這樣我一次性數(shù)據(jù)往返就能取到所有數(shù)據(jù)了嘛!各位同學(xué)是不是覺得我這個主意很棒?

噩夢由此開始了。

首先,我們是想在發(fā)布博客的時候,設(shè)置他的上一篇和下一篇。但是,上一篇好設(shè)置,下一篇呢?還沒有啊!怎么弄,就只好在博客發(fā)布的時候,設(shè)置他的前一篇,同時設(shè)置他前一篇的后一篇。

然后,我們新添加了一個功能,除了上一篇下一篇以外,還需要在當(dāng)前博客所在分類中的上一篇和下一篇。怎么辦?再加字段唄。所以,博客里就有了Previous, PreviousInCategory, Next, NextInCategory。這時候,就感覺到有點不妥,但還可以接受。

接著,出現(xiàn)了一個問題,上一篇下一篇博客被刪除了,怎么辦?這個過程,就相當(dāng)于從一個雙向鏈表里移出一個節(jié)點一樣麻煩。頭開始有點大了。

再接著,博客除了發(fā)布刪除以外,還有各種其他狀態(tài),比如被屏蔽。而且被屏蔽之后,能否顯示和當(dāng)前用戶又有關(guān)系。當(dāng)前用戶是普通用戶,不能閱讀;當(dāng)前用戶是作者自己,就能夠閱讀。怎么辦?首先,屏蔽的時候,要設(shè)置上一篇下一篇;屏蔽取消的時候,還是要設(shè)置上一篇下一篇。然后,上一篇下一篇得根據(jù)當(dāng)前用戶不同變化的這個問題,基本上就傻眼了……

最后流著淚把辛辛苦苦折騰了好久的代碼全改回來,就通過數(shù)據(jù)庫查唄,多么清晰簡潔的邏輯啊!性能問題?首先,這樣做造成了性能問題么?然后,就算有問題,用一個緩存能解決不?

合理浪費堆硬件

說了這么多,不知道有沒有引起同學(xué)們的反思??赡艽蠹疫€是過不去心里那道坎:明明有一種性能更高的方法我們?yōu)槭裁床挥?

因為浪費唄!

什么?你有沒有搞錯?我的代碼,至少省了一塊內(nèi)存條!那是你還沒從“窮學(xué)生”的角色里轉(zhuǎn)換過來。你花一周的時間對代碼進行了優(yōu)化(就先不考慮你的優(yōu)化帶來的維護成本增加了),為老板省下了一塊內(nèi)存條的錢。你以為老板會拍著你的肩膀表揚你么?老板打不死你!

兄弟,賬不是你那樣算的。當(dāng)你是學(xué)生的時候,你的時間成本是0;但你進入工作崗位,每一天都是要發(fā)工資的。

通過代碼來調(diào)高性能,是一種無奈——對硬件性能不夠的妥協(xié)(參考:80年代游戲開發(fā)者的辛苦困境。這樣寫性能就高,但為什么現(xiàn)在沒有誰再這么寫代碼了?)。否則,絕大多數(shù)情況下,堆硬件比優(yōu)化代碼的效果好得多,而且便宜得多。硬件的成本按摩爾定律往下降,我們程序員的工資也能按摩爾定律減么?

明明window 10 比window 95更耗性能,為什么今天沒人用window 95?為什么VS 2013要10G的空間我們都還屁顛屁顛的趕緊裝上?為什么現(xiàn)在大家都用C#,沒人用匯編?我們站在人類文明積累的今天,就應(yīng)該理所當(dāng)然的享受這一切成果。有打火機你不用,你要鉆木取火。如果你是因為要學(xué)貝爺荒野求生裝逼,可以理解;如果你說你是因為怕浪費天然氣,我……我……我怎么說你呢?“給做打火機的一條活路,行不?”同樣的,程序員大神同學(xué),你就當(dāng)做好事,給下面寫底層做硬件的一條活路吧!你的代碼都是010001000010000001010101……了,你讓其他人怎么活啊?

最后,我突然想到的一個程序員為什么對性能如此敏感瘋狂,對可維護性毫不在意的一個可能原因:

性能很好理解,卡得要死和跑得飛快;可維護性很不好理解,至少得跑個兩三年才能體現(xiàn),那時候,誰知道爺在哪里偷著樂呢

性能上不來,程序員只有羞愧的低著頭,都是我的錯;需求有變更,開口就罵,“哪個SB又要改……”;

大家覺得是不是這樣的?所以,愿意把代碼百煉成鋼繞指柔的人少。想來,是一種莫名的悲哀和凄涼。

最后最后,有一些我能想到的名言警句供大家參詳:

過早的優(yōu)化是萬惡之源

優(yōu)化首先需要找到性能“瓶頸”。否則,任何人都可以隨手一指,“這段代碼需要優(yōu)化”。

可讀性更強的代碼總是更好優(yōu)化

硬件永遠比軟件便宜

責(zé)任編輯:何妍 來源: 博客園
相關(guān)推薦

2015-09-28 14:20:30

2023-11-01 18:06:46

彩虹橋架構(gòu)性能

2015-09-28 15:03:38

網(wǎng)絡(luò)架構(gòu)測試

2013-04-15 11:08:00

架構(gòu)師Web

2021-07-12 23:43:46

AppAndroid優(yōu)化

2024-05-17 08:38:22

2009-03-09 10:10:17

2017-02-17 07:12:24

2010-10-28 13:24:10

聯(lián)想網(wǎng)御MIPS信息安全

2011-02-18 16:51:19

2023-03-08 18:43:50

GPU模型隔離

2012-12-28 13:35:37

網(wǎng)絡(luò)無線網(wǎng)絡(luò)

2022-05-23 14:33:26

集群架構(gòu)元宇宙

2012-04-09 09:42:00

網(wǎng)絡(luò)虛擬化

2020-08-05 08:23:19

架構(gòu)Java微服務(wù)

2022-05-09 11:29:42

架構(gòu)數(shù)據(jù)

2019-12-23 08:00:00

虛擬機容器VNF

2024-01-17 15:53:41

2016-04-21 10:10:31

Java應(yīng)用架構(gòu)

2017-06-16 10:54:08

服務(wù)器陣列網(wǎng)絡(luò)架構(gòu)
點贊
收藏

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