有人對著組合語言不夠一屑,認為那已經是古老的低階語言,是當今的非主流語言,學了也不知道有什麼用。是的,我們不得不承認,作為一門古老的語言,彙編已經完成了歷史賦予它的使命,但是我們知道,我們現在所使用的任何高階語言在編譯的時候都是被轉化為組合語言來執行的,也就是說,無論我們在上層做了何種的抽象,引入了多少新鮮的概念,作為乙個程式設計師,我們的程式在最底層仍然是它,或許絕大部分的時間,我們無需關心它的存在,但是,當我們編寫或優化高效能的應用程式時,除了演算法,我們也不得不面對它。下面我們來舉乙個例子來證明這一點,我們用
c/c++
寫兩個簡單巢狀迴圈:
1).for ( i= 0;i < 1000000;i++)
for (j =0; j < 100; j++)
2).for ( i= 0;i < 100;i++)
for (j =0; j < 1000000; j++)
我們知道,當計算表示式相同時,這兩個迴圈所計算得到的結果完全相同,但是你會選擇哪一種寫法呢?或許絕大多數的程式設計師壓根就沒有想過要會有第二種寫法,因為他的程式都來自他的邏輯
(作為人的一種自然邏輯
),而不是「機器」的邏輯,呵呵,是的,我們在寫程式,是執行在機器上的程式,所以我們在寫程式時,就應該盡量遵循「機器」的邏輯,那樣的話,我們就能寫出高效能的程式,為什麼要第
2 種寫法要優於第
1種寫法呢?下面讓我們來看一看他關鍵彙編**描述就明白了(呵呵,終於用到彙編了):
1.
movcx,0
a:
cmp cx, 1000000
jgover
inccx
movbx , 0
b:
cmpbx, 100
jga
incbx
some calculate……
jumpb
over:
2.
movcx,0
a:
cmp cx, 100
jgover
inccx
movbx , 0
b: cmpbx, 1000000
jga
incbx
some calculate……
jumpb
over:
那麼我們怎麼去評估我們的兩個**的效能呢,在這裡我們就去看
jump
指令,在第乙個彙編**中,我們去評估jga指令和jump b
指令,也就是說,正常情況下,jga被執行了
1000000
次,而jump b
指令被執行了
100* 1000000
次,現在讓我們來看看第二個彙編**中的jga指令和jump b
指令分別執行的次數,在正常情況下,我們很容易就得知,jga被執行了
100次,而jump b
指令被執行了
100* 1000000
次,也就是說,在兩個**中,jump b
指令被執行的次數相等,而在第二段**中jga指令執行的次數比第一段**中執行的次數少
1000000
次,假設我們的程式執行在
pentium
機上,那麼乙個jump指令大概執行的乙個時鐘迴圈
(clock cycle),
那麼,很明顯,第二段**的執行效率要高於第一段時鐘的執行效率。
上述只是乙個很常見的例子,有時候,為了使效能達到我們的要求,我們要優化**,關鍵的部分部分通常利用彙編**去實現,因為使用特定的
cpu提供的特殊的指令集通常能大大提高程式的效能(但是,可移植性通常也因此而被犧牲)。
所以,要成為高手,學習彙編是必要的,因為,彙編能讓你在除錯你程式的時候更加游刃有餘,能讓你深入底層,找出很難察覺的
bug,讓你更加懂得「機器思維」。而這一切,都是成為高手的必要條件。
php大陣列迴圈巢狀的效能優化
博主最近在用elasticsearch做專案,查出來的資料都是陣列,在篩選資料組裝資料的時候,難免會碰到迴圈巢狀的問題。如果兩個50000的陣列迴圈巢狀,那實際運算則是50000 50000的運算量,十分影響程式執行速度。這篇文主要記錄博主優化程式的過程。先提供一些測試工具,可以明確知道咱們哪部分程...
php 大陣列 foreach 迴圈巢狀的效能優化
前提 最近在做後台的時候,頁面載入太慢,故第一時間想到的自然是優化sql,優化後sql查詢速度從 2秒變成了零點幾秒,以為就這麼完事了,然並卵,載入竟然花費30秒!這麼慢,然後在 中分塊記錄它的耗時時間,發現是在 foreach 遍歷的問題,巢狀資料量太大了,我還巢狀了三層,資料量大約為 30 20...
for迴圈的巢狀
for迴圈的巢狀 1格式for 表示式1 表示式2 表示式3 語句塊 2執行順序 對表達1進行初始化,然後判斷表示式2,如果返回真,則進入到內層for執行表示式4,再判斷表示式5,如果返回真,則執行語句塊1,然後執行表示式6,再到表示式5判斷,直到返回假為止,再跳出內層迴圈到外層迴圈的表示式2判斷,...