電話那頭的背景音亂成了一鍋粥。
有人在扯著嗓子喊網管,C區三號機加十塊錢,還有人在拍桌子罵你丟雷啊,閃到我了,夾雜著一連串的咳嗽聲和打火機點菸的聲音。
陳拙把座機的話筒稍微拿遠了一點。
“你等會。”
楚戈在那頭喊了一聲,緊接著是一陣拖拽椅子的摩擦聲,聲音稍微小了些,似乎是換了個角落。
“行了,你說,我找著筆了。”
楚戈咬著根糖,左手死死把話筒夾在肩膀和耳朵之間,右手在一堆亂七八糟的鍵盤線裡摸索出了一根圓珠筆。
桌上冇有紙,他四下看了一眼,順手把旁邊吃剩的康師傅紅燒牛肉麪桶拉過來,把那層沾著幾滴紅油的硬紙蓋撕了下來,翻到背麵。
紙蓋背麵有些潮濕,但不影響寫字。
陳拙站在客廳的窗戶邊,看著玻璃上那層薄薄的霜花,伸手在上麵劃了一道。
“京城那邊的資料庫是怎麼建的?”陳拙問。
“關係型,典型的樹狀結構。”
楚戈使勁咬了兩口糖。
“他們想做一個六度空間的社交網,底層邏輯很簡單,我是A,我認識B,資料庫就建一條邊,查詢我的好友,速度很快,查詢我好友的好友,也勉強能跑。”
楚戈的聲音透著一股熬夜過後的乾澀感。
“但是隻要往下查三度,四度,一旦併發量超過兩百人,資料庫就要做無限的巢狀聯合查詢,一張幾十萬使用者的表,瞬間交叉出幾千萬條冗餘資料。”
“京城那哥們說,剛纔他們做壓力測試,兩百個虛擬賬號同時點開可能認識的人這個功能,伺服器的風扇轉得像直升機,CPU直接飆到百分之百,三秒鐘後資料庫就鎖死了。”
楚戈歎了口氣。
“現在這就成了一個死結,要想快,就得把所有關係提前算好存進快取,但這需要海量的記憶體,他們買不起那麼多伺服器,如果不提前算,實時查,隻要稍微有幾個人同時訪問,資料庫就得崩。”
陳拙聽完,冇有立刻說話。
他走到沙發邊坐下,拿起果盤裡的一顆帶殼花生,在手裡輕輕捏開。
“你們學計算機的,是不是有點軸?”
陳拙把花生衣搓掉,語氣裡帶著一點笑意。
“什麼意思?”
楚戈愣了一下。
“這是個純粹的圖論問題,你們為什麼要用查戶口的辦法去解?”
陳拙把花生扔進嘴裡。
“丟掉你們的巢狀查詢,把所有的使用者,看成高維空間裡的點,使用者之間的關係,是一條線。”
楚戈冇吭聲,筆尖停在泡麪蓋子上。
“建立一個鄰接矩陣。”
陳拙的聲音很平穩,像是在大學自習室裡給人講一道大一的微積分課後題。
“假設有十萬個使用者,就是一個十萬乘十萬的矩陣A,使用者i和使用者j是好友,矩陣中(i,j)的值就是1,否則就是0。”
“等一下。”
楚戈打斷了他。
“十萬乘十萬,那是一百億個資料點,你算過這要占多大記憶體嗎?伺服器當場就得炸。”
“楚戈。”
陳拙在電話這頭輕笑了一聲。
“你在現實裡,有十萬個朋友嗎?”
“冇有,我連十個都冇有。”
楚戈老老實實地回答。
“正常人都冇有。”
陳拙說。
“所以,這個矩陣裡百分之九十九點九九的值,都是0,這是一個極度稀疏的稀疏矩陣。”
楚戈拿著筆的手指猛地一緊。
“在記憶體裡,你不需要存那一百億個點,你隻需要存那些是1的座標就行了。”
陳拙繼續往下說。
“這就是個簡單的座標對映,接下來,你想找好友的好友,也就是二度人脈,在數學上怎麼表達?”
楚戈的腦子轉得飛快,那些大一學過,後來又被他忘得差不多的線性代數知識,突然像閃電一樣劈開了他腦子裡的混沌。
“矩陣乘法。”
楚戈脫口而出。
“A乘以A,A的平方。”
“對。”
陳拙站起身,走到茶幾倒了杯溫水。
“A的平方,矩陣裡值不為零的地方,就是二度人脈,A的立方,就是三度人脈。”
楚戈看著泡麪蓋子,圓珠筆在上麵無意識地畫著圈,呼吸變得急促起來。
“但是矩陣相乘的計算量太大了,尤其是高階乘法,CPU還是吃不消。”
楚戈提出了最核心的問題。
“那是你太貪心了,你想一次性算出所有人的關係網路。”
陳拙喝了口水,潤了潤嗓子。
“伺服器不需要知道所有人認識誰,伺服器隻需要回答當前登入的那個使用者的請求,所以,你不需要做矩陣和矩陣的乘法。”
陳拙的聲音變得有些輕,但在楚戈耳朵裡卻像是一聲炸雷。
“當前登入的使用者,不是一個矩陣,他是一個向量。”
陳拙給出了最後的解法。
“一個隻有他自己那個位置是1,其餘全是0的向量,你拿這個一維向量,去乘那個稀疏矩陣,乘一次,得出他的直接好友向量,再拿結果去乘一次矩陣,得出二度好友。”
陳拙頓了頓,補了一句。
“向量乘稀疏矩陣,時間複雜度是O(N),就算他有一萬度的人脈,計算機做這種一維陣列的乘法,連一毫秒都用不了。”
網咖裡,楚戈嘴裡的糖已經咬乾淨了。
咬到了糖棍被硌了一下牙,他才猛地反應過來,一把將糖棍甩在地上。
他的眼睛死死盯著麵前那張沾著紅油的泡麪紙蓋。
上麵寫著兩行有些淩亂的公式。
困擾了京城那個初創團隊整整半個月,被幾個清華計算機係的高材生視為無解硬體瓶頸的資料庫死鎖問題。
在這個十二歲男孩嘴裡,被幾句最基礎的線性代數概念,直接降維打擊成了碎渣。
“我懂了。”
楚戈的聲音有些發抖。
“拋棄資料庫的關係查詢,把所有的關係表抽出來,在記憶體裡維護一個稀疏矩陣,所有的查詢,全部在記憶體裡做向量相乘,算出結果後,再拿使用者ID去資料庫裡提頭像和名字。”
“對。”
陳拙應了一聲。
“但是有個問題。”
楚戈的程式員思維迅速抓住了漏洞。
“A認識B,B認識C,C又認識A,這在圖論裡是個環,如果向量一直乘下去,會不會無限迴圈,把算力耗死?”
“楚戈。”
陳拙在電話那頭歎了口氣,語氣裡帶著點無奈。
“這是工程問題,不是數學證明題,向量乘出來的結果裡,凡是數值大於0的,你順手用個雜湊表把ID記下來,下次乘的時候遇到已經記過的,直接跳過不就行了。”
陳拙輕輕搖了搖頭。
“你是個寫程式碼的,彆指望數學公式連你拉屎用幾格紙都算清楚,用點你程式員的常識好嗎?”
楚戈聽著電話裡那點調侃,突然咧開嘴樂了。
“行,哥哥我承你這個情了,這回算我欠你的。”
楚戈把那張泡麪蓋子折了兩下,小心翼翼地塞進貼身的口袋裡。
“過完年回科大,我請你吃一個月的食堂小炒,先掛了,我得趕緊把這個底層的記憶體守護程序寫出來。”
冇等陳拙說話,電話裡傳來了嘟嘟嘟的忙音。
陳拙放下話筒,搖了搖頭,嘴角帶著一抹笑意。
他轉過身,走向廚房去拿碗筷,準備吃晚飯。
……
距離澤陽市一千多公裡外的京城。
中關村附近的一棟破舊居民樓裡。
屋子裡冇開燈,隻有三四台顯示器散發著慘白的光,窗外偶爾閃過幾道絢爛的煙花,照亮了滿地的菸頭和吃剩的外賣盒。
汪興裹著一件棉服,整個人窩在電腦椅裡,雙眼佈滿血絲,死死盯著螢幕上的後台日誌。
他們想在這個網際網路的荒蠻時代,做一個真正意義上的實名製校園社交網站,點子是極好的,幾個汪興甚至已經靠著PPT拉到了一筆幾十萬的天使投資。
但是技術瓶頸卡死了他們。
明天就是大年初三,投資人要求看一個承載五百人同時線上的係統Demo。
汪興已經三天冇閤眼了。
隻要併發量一上來,好友的好友這個核心功能的資料庫查詢,就會像雪崩一樣拖垮整個係統。
螢幕右下角的MSN圖示突然跳動了起來。
汪興佈滿血絲的眼睛動了一下,握著滑鼠點開。
是楚戈,那個遠在徽州,被他拉來當免費技術外援的科大變態黑客。
“老楚,彆費勁了。”
汪興敲了一行字發過去,手指有些僵硬。
“我們試了加快取,試了建索引,冇用,關係型資料庫處理不了這種多級網狀查詢,硬體扛不住。”
幾秒鐘後,楚戈發過來一個壓縮包。
隻有不到20KB。
緊接著,楚戈的訊息彈了出來。
“把你們之前的關係查詢程式碼全刪了,把這個C語言寫的守護程序掛在伺服器後台。”
汪興愣了一下。
“這是什麼?”
“一個記憶體級彆的稀疏矩陣相乘工具。”
楚戈的回覆很簡單。
“你隻要把你們的關係表匯出一份純文字塞給它,以後所有的好友查詢,不用過資料庫,直接髮指令給這個程序,它在記憶體裡算完,把好友ID陣列返回給你。”
汪興看著那段話,有些摸不著頭腦。
但他現在已經走投無路了,死馬當活馬醫。
他接收了檔案,解壓,把原始碼拖進編譯器,粗略地掃了一眼。
這一看,汪興的冷汗嘩的一下就下來了。
程式碼極其精簡,冇有任何資料庫連線的庫檔案,全是底層的記憶體指標操作和幾個他看不太懂的一維陣列迴圈相乘。
裡麵冇有一條SQL語句。
汪興深吸了一口氣,把編譯好的執行檔案掛到了測試伺服器的後台,然後把幾萬條測試用的關係資料塞了進去。
程序悄無聲息地啟動了,占用記憶體不到五十兆。
“跑個壓測。”
汪興轉頭,對旁邊另一個已經困得東倒西歪的王惠文喊了一聲。
王惠文迷迷糊糊地揉了揉眼睛,在鍵盤上敲下了一行壓測指令。
“模擬五百個併發請求,三級好友深度查詢。”
王惠文敲完回車。
“興哥,準備重啟伺服器吧,估計還是三秒鐘崩......”
話還冇說完,王惠文的聲音卡在了喉嚨裡。
壓測工具的進度條並冇有像之前那樣死死卡住,而是以一種肉眼幾乎無法捕捉的速度,瞬間刷滿。
滿屏的綠色。
汪興猛地坐直了身體,椅子發出不堪重負的嘎吱聲。
他死死盯著壓測結果的彙總資料。
請求完成數:500。
失敗數:0。
平均響應時間:3毫秒。
汪興覺得自己眼花了,他轉頭看了一眼伺服器的係統資源監控。
在剛纔壓測的一瞬間,CPU的使用率僅僅跳動了一下,到了8%,然後又迅速回落到了1%。
伺服器連風扇都冇來得及加速轉動,查詢就已經結束了。
屋子裡安靜得隻能聽到機箱微弱的蜂鳴聲。
“興哥......”
旁邊的王惠文嚥了口唾沫,指著螢幕的手都在抖。
“這什麼情況?資料庫冇轉?”
“冇有過資料庫。”
汪興的聲音變得沙啞,他死死盯著剛纔那段C程式碼,終於看明白了裡麵那可怕的數學邏輯。
這不是在查資料。
這是在記憶體裡,直接對整個使用者關係網進行數學維度的降維計算。
汪興的手指有些發麻,他切回MSN的聊天視窗,手速極快地敲字,甚至連打了好幾個錯彆字都顧不上改。
“老楚!這底層邏輯是誰寫的?!”
汪興連續發了三個抖動視窗。
“這他媽是純粹的圖論和高階線性代數!直接把資料庫的活兒抽給CPU記憶體做向量計算了!”
汪興的心臟在狂跳。
“你彆告訴我這是你想出來的,你背後是不是有箇中科院的演演算法團隊?還是說你找了矽穀哪個搞搜尋引擎的大牛幫忙?”
小縣城的網咖裡。
楚戈看著螢幕上汪興發來的那一連串感歎號和瘋狂閃爍的視窗,疲憊的臉上露出了一個極其囂張的笑容。
他拿起旁邊那盒自己讓朋友代買的幾十塊的糖,抽出一根,叼在嘴裡。
楚戈把菸灰彈在泡麪碗裡,雙手搭在滿是油汙的鍵盤上,慢條斯理地敲下了一行字,點選回車傳送。
“冇團隊。”
“就我同寢室的一個室友,他剛好在家放寒假,剛纔打電話順手給解的。”
發完這句,楚戈頓了頓,又補了一刀。
“哦對了,他今年十二歲,這會兒估計正被他媽叫去吃餃子呢。”
MSN那頭,汪興的頭像徹底不動了。
過了足足五分鐘。
汪興才發過來一串省略號。
接著是一句話。
“老楚,如果明天投資人那邊的錢到位了,我給你留百分之五的乾股,你那個室友......能不能拉進咱們團隊當技術顧問?什麼條件他隨便開。”
楚戈看著這句話,輕笑了一聲。
“拉倒吧。”
楚戈敲字。
“咱們這破草台班子,你還敢指望人家那種大神來當技術顧問?這幾行程式碼,就當是我送你們的新年禮物了,下了,睡覺。”
楚戈果斷地退出了MSN。
網咖裡的空氣依然渾濁,旁邊包夜的幾個社會青年已經趴在鍵盤上睡著了,發出輕微的鼾聲。
楚戈站起身,伸了個大大的懶腰,骨頭髮出幾聲脆響。
他走到吧檯結了賬,推開網咖的玻璃門。
一股凜冽的寒風迎麵撲來,瞬間吹散了身上沾染上的煙味和網咖特有的頭油味。
天已經矇矇亮了。
大年初三的早晨,街道上冷冷清清,滿地都是昨夜放完的紅色鞭炮碎屑,在殘雪的映襯下顯得格外刺眼。
楚戈把那件舊軍大衣的領子豎起來,雙手插在兜裡。
他走在清冷的街道上,撥出一口白氣。
在這個瘋狂生長的時代前夜。
有人在牌桌上通宵,有人在電腦前熬紅了眼。
而那個真正給他們指了條明路的人,現在在乾什麼呢?
楚戈忍不住笑了笑,踩著地上的碎紙屑,朝著招待所的方向走去。
......
同一時間。
澤陽市,陽光家屬院。
陳家客廳裡的電視機開著,正在重播著昨晚的春節聯歡晚會。
馮鞏那句我想死你們了在屋子裡迴盪。
廚房裡熱氣騰騰。
“小拙!彆在客廳晃悠了,去洗手!”
劉秀英端著兩盤剛出鍋的餃子從廚房走出來,熱氣模糊了她的臉。
“初一餃子初二麵,初三的合子往家轉,今天吃酸菜豬肉餡的餃子,趕緊過來趁熱吃,一會兒坨了就不好吃了!”
陳建國拿著幾瓣大蒜和一瓶陳醋,在餐桌前坐下。
“來了來了。”
陳拙應了一聲,走到衛生間,擰開水龍頭。
腦海裡剛纔那一閃而過的矩陣,向量,高維空間對映,在聽到劉秀英喊吃餃子的那一刻,就像是被清水沖走的肥皂沫一樣,瞬間消失得乾乾淨淨。
什麼網際網路,什麼六度空間。
在這個飄著雪花和醋香味的大年初三早晨,都比不上餐桌上那一盤熱氣騰騰的酸菜餡餃子來得實在。
陳拙擦乾手,走到餐桌前坐下。
“媽,給我倒點醋。”
陳拙把小瓷碟推過去,語氣裡帶著一個十二歲男孩特有的理所當然。
劉秀英拿起醋瓶子,給他倒了半碟。
“吃餃子不吃蒜,香味少一半,自己剝蒜去。”
陳建國把兩瓣大蒜扔到陳拙麵前。
陳拙撿起那兩瓣蒜,拇指和食指用力一捏,蒜皮發出一聲脆響,裂開了。
陽光透過陽台的玻璃照進來,打在陳拙溫潤如玉的臉上。
一切都顯得那麼平靜,那麼理所當然。