一名程序員的時空觀

這篇文字講述時間和空間,但肯定不是去理解牛頓的絕對時空觀,也不會去理解愛因斯坦狹義相對論的理論。

我們今天說的是,程序世界的兩句話 “時間換空間,空間換時間”,這兩句詞語在我們的工作中經常會被提及。

那麼這中間的【換】我的理解是“被動的犧牲,然後再去爭取”,有點置之死地而後生的氣魄。

比如犧牲時間,多“浪費”一些時間換取空間的延伸;犧牲空間,多“浪費”一些空間節省時間上的消耗。

空間換時間

空間換時間,比如增加數據庫的索引提高查詢性能,爲數據庫表的列字段增加索引就會佔用一定的物理空間,如果是創建聚族索引還會需要更多的空間。

再比如利用緩存,數據庫裏面本來有一份卻要再另外申請緩存空間,將耗時的操作放入到remote緩存或者內存中也可以提升性能。

這些都是空間換時間的例子,無論是索引還是緩存都額外增加了存儲空間,然後換來查詢性能的提升,查詢的耗時減少了。

時間換空間

時間換空間,比如分頁查詢顯示,本來可以一次查詢數千條記錄一次顯示出來,但這樣如果每條數據字節過大,會對應用程序內存造成威脅。

這個時候,就可以犧牲時間,本來可以一次全部看完,我們卻一頁數十條或者百條記錄,分成好幾次展示給最終用戶。

再比如,按照一定規則對要處理的數據進行加密算法處理,然後將加密的數據直接返回給用戶,這中間增加了加密的時間開銷。

程序運行中的時間和空間

時間,代表的是性能,空間,代表的是存儲。

我們日常的程序運行中總是跟這兩塊分不開的。程序被編譯好一開始就存於磁盤,運行時繼而被加入內存,都用到了空間。

CPU從內存讀取程序和將結果寫入內存,此時過程中更是關注讀寫的性能,讀取磁盤也是。如下圖所示。

上圖選自《架構修煉之道》第一章

算法的時間複雜度

在計算一個算法的時間複雜度的時候,可以通過總的執行次數T(n)是關於問題規模n的函數來表示。

通過分析T(n)隨n的變化情況確定T(n)的數量級。因此,算法的時間複雜度,也可以用公式 T(n)= O(f(n)) 來表示。

代表着隨問題規模n的增大,算法執行時間的增長率和f(n)的增長率相同。f(n)是問題規模n的某個函數。

算法的空間複雜度

我們寫一個算法來判斷某年是不是閏年,老土的辦法就是我通過程序開闢一個好多年數值大小的數組,比如2080個元素的數組。

隨後我們對所有的年份下標的數字做對應,如果是閏年,年份下標對應的數組元素的值就是1,否則是0。

這樣我們通過索引的方式能很快獲取輸入的年份是否閏年。

當然,上述方法是利用了增加數組空間存儲的方式。

如果不這樣做,就需要我們寫那麼一個算法,當程序接收到一個年份的時候,就可以通過這個算法計算出所給年份是否是閏年。

當然,這樣做就要耗費CPU計算性能。到底採取哪一種,就需要看使用這種增加空間的開銷能否足夠換來減小計算時間的開銷了。

算法的空間複雜度計算公式爲,S(n)=O(f(n)),其中,n是問題的規模,f(n)是這個公式關於n所佔存儲空間的函數。

摩爾定律

上面提到的時間,多指性能的成分偏多,或者說就是純粹的性能。

現在要說的時間就是偏向純粹的時間一面了。摩爾定律講的是集成電路上可容納的元器件數目,大約每隔18-24個月便會增加一倍,性能也會提升一倍。

那麼,有了這個定義,此時的時間和性能又對應上了。只不過他們之間不像上面提到時間和空間那樣有交換關係,這裏沒有交換關係。

起初的時候電腦的CPU都是單核,各大廠商都是拼CPU的頻率,多少多少赫茲。隨着這種技術發展遇到了瓶頸,於是大家開始橫向擴展,拼CPU的核數,多少多少核。

這是不是也是一種空間換時間呢,核數增加了勢必要積壓原本狹小的計算內部硬件空間,但同時確實換來了計算機整體計算性能的提升。

時間、空間的跨越發展

在2000年初我們訪問一個頁面,我們可以一直等,直到頁面有內容返回,呈現在我們面前。如今,我們訪問一個網站,使用一個APP,如果超過2S,甚至1S沒有內容返回,我們都會有放棄繼續使用的衝動。

在2000年初我們寫一個程序要存儲到一張只有幾KB的軟盤裏面,當時的學生上下計算機課都隨身攜帶。如今,我們不僅可以在本機存儲幾TB的數據,而且我們還可以申請到上百G的雲存儲空間。

回到代碼

返回到代碼層面,我們再來看一個空間和時間交換的兩段程序代碼,我們大學時代上C語言課程的時候,常用的例子。

下面兩段程序的目的都是讓都整形數值的a和b做個交換,但卻分別是犧牲了空間和犧牲了時間。

程序片段-1

void swap(int a, int b)
{
int c;
 c=a;
 a=b;
 b=c;
}

在這段程序裏面,我們新開闢了一塊空間c,然後我們利用這個新開闢的空間,做了三次賦值運算,最終的結果是a和b的值之間互換。

程序片段-2

void swap(int a, int b)
{
a=a+b;
 b=a-b;
 a=a-b;
}

在這段程序裏面,我們就沒有新創建任何的空間,那是怎麼做的呢,我們分別做了三次加減運算和三次賦值運算,最終將a和b的值互換。

顯然第2段程序運算要比第1段程序複雜,計算耗時肯定也要比新開闢空間多。

那麼程序片段-1是用空間換了時間,程序片段-2是用時間換了空間。

程序片段-1時間效率就比較高,空間效率低;程序片段-2時間效率低,空間效率高。

寫在最後

這樣看,作爲一名程序員,我們經常跟時空打交道,從常見的應用場景到摩爾定律的規則,再到考慮一段程序設計,我們往往都要在時空間取一個平衡。

因爲,時間上的性能考慮和空間上的利用是我們每次設計程序以及程序將來運行在生產環境下,都是我們要重點對待的兩件事情。

發佈了87 篇原創文章 · 獲贊 30 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章