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

Openresty的開發(fā)閉環(huán)初探

開發(fā) 開發(fā)工具
Nginx 作為現(xiàn)在使用最廣泛的高性能后端服務(wù)器,Openresty 為之提供了動態(tài)預(yù)言的靈活,當(dāng)性能與靈活走在了一起,無疑對于被之前陷于臃腫架構(gòu),苦于提升性能的工程師來說是重大的利好消息。

1. 為什么值得入手?

Nginx 作為現(xiàn)在使用最廣泛的高性能后端服務(wù)器,Openresty 為之提供了動態(tài)預(yù)言的靈活,當(dāng)性能與靈活走在了一起,無疑對于被之前陷于臃腫架構(gòu),苦于提升性能的工程師來說是重大的利好消息,本文就是在這種背景下,將初入這一未知的領(lǐng)域之后的一些經(jīng)驗(yàn)與大家分享一下,若有失言之處,歡迎指教。

Openresty的開發(fā)閉環(huán)初探

2. 安裝

現(xiàn)在除了能在 [Download](http://openresty.org/en/download.html )里面下載源碼來自己編譯安裝,現(xiàn)在連預(yù)編譯好的[包](http://openresty.org/en/linux-packages.html)都有了, 安裝也就分分鐘的事了。

3. hello world

/path/to/nginx.conf`, `conftent_by_lua_file 里面的路徑請根據(jù) lua_package_path 調(diào)整一下。

  1. ``` 
  2.    location / { 
  3.        content_by_lua_file ../luablib/hello_world.lua; 
  4.    } 
  5.    ``` 
  6.  
  7. /path/to/openresty/lualib/hello_world.lua` 
  8.    ``` 
  9.    ngx.say("Hello World") 
  10.    ``` 

訪問一下, Hello World~.

  1. ``` 
  2.   HTTP/1.1 200 OK 
  3.   Connection: keep-alive 
  4.   Content-Type: application/octet-stream 
  5.   Date: Wed, 11 Jan 2017 07:52:15 GMT 
  6.   Server: openresty/1.11.2.2 
  7.   Transfer-Encoding: chunked 
  8.   Hello World 
  9.   ``` 

基本上早期的 Openresty 相關(guān)的開發(fā)的路數(shù)也就大抵如此了, 將 lua 庫發(fā)布到 lualib 之下,將對應(yīng)的 nginx 的配置文件發(fā)布到 nginx/conf 底下,然后 reload 已有的 Openresty 進(jìn)程(少數(shù)需要清空 Openresty shared_dict 數(shù)據(jù)的情況需要重啟 )。

如果是測試環(huán)境的話,那更是簡單了,在 http 段將 lua_code_cache 設(shè)為 off , Openresty 不會緩存 lua 腳本,每次執(zhí)行都會去磁盤上讀取 lua 腳本文件的內(nèi)容,發(fā)布之后就可以直接看效果了(當(dāng)然如果配置文件修改了,reload 是免不了了)。是不是找到一點(diǎn)當(dāng)初 apache 寫 php 的感覺呢:)

4. 開發(fā)語言 Lua 的大致介紹

環(huán)境搭建完畢之后,接下來就是各種試錯了。關(guān)于 Lua 的介紹,網(wǎng)上的資料比如:Openresty ***實(shí)踐(版本比較多,這里就不放了)寫的都會比較詳細(xì),本文就不在這里過多解釋了,只展示部分基礎(chǔ)的Lua的模樣。

下面對 lua 一些個性有趣的地方做一下分享,可能不會涉及到 lua 語言比較全面或者細(xì)節(jié)的一些部分,作為補(bǔ)充,讀者可以翻閱官方的< >。

  1. ```lua 
  2.    -- 單行注釋以兩個連字符開頭 
  3.    --[[ 
  4. 行注釋 
  5.    --]] 
  6.    -- 變量賦值 
  7.    num = 13  -- 所有的數(shù)字都是雙精度浮點(diǎn)型。 
  8.    s = '單引號字符串' 
  9.    t = "也可以用雙引號" 
  10.    u = [[ 多行的字符串 
  11.           ]] 
  12.    -- 控制流程,和python最明顯的差別可能就是冒號變成了do, ***還得數(shù)end的對應(yīng) 
  13.    -- while 
  14.    while n < 10 do 
  15.      nn = n + 1  -- 不支持 ++ 或 += 運(yùn)算符。 
  16.    end 
  17.    -- for 
  18.    for i = 0, 9 do 
  19.      print(i) 
  20.    end 
  21.    -- if語句: 
  22.    f n == 0 then 
  23.      print("no hits") 
  24.    elseif n == 1 then 
  25.      print("one hit") 
  26.    else 
  27.      print(n .. " hits") 
  28.    end 
  29.    --只有nil和false為假; 0和 ''均為真! 
  30.    if not aBoolValue then print('false') end 
  31.    -- 循環(huán)的另一種結(jié)構(gòu): 
  32.    repeat 
  33.      print('the way of the future') 
  34.      numnum = num - 1 
  35.    until num == 0 
  36.    -- 函數(shù)定義: 
  37.    function add(x, y) 
  38.      return x + y 
  39.    end 
  40.    -- table 用作鍵值對 
  41.    t = {key1 = 'value1'key2 = false
  42.    print(t.key1)  -- 打印 'value1'. 
  43.    -- 使用任何非nil的值作為key: 
  44.    u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} 
  45.    print(u[6.28])  -- 打印 "tau" 
  46.    -- table用作列表、數(shù)組 
  47.    v = {'value1', 'value2', 1.21, 'gigawatts'} 
  48.    for i = 1, #v do  -- #v 是列表的大小 
  49.      print(v[i]) 
  50.    end 
  51.    -- 元表 
  52.    f1 = {a = 1b = 2}  -- 表示一個分?jǐn)?shù) a/b. 
  53.    f2 = {a = 2b = 3
  54.    -- 這會失敗: 
  55.    -- s = f1 + f2 
  56.    metafraction = {} 
  57.    function metafraction.__add(f1, f2) 
  58.      local sum = {} 
  59.      sum.b = f1.b * f2.b 
  60.      sum.a = f1.a * f2.b + f2.a * f1.b 
  61.      return sum 
  62.    end 
  63.    setmetatable(f1, metafraction) 
  64.    setmetatable(f2, metafraction) 
  65.    s = f1 + f2  -- 調(diào)用在f1的元表上的__add(f1, f2) 方法 
  66.    -- __index、__add等的值,被稱為元方法。 
  67.    -- 這里是一個table元方法的清單: 
  68.    -- __add(a, b)                     for a + b 
  69.    -- __sub(a, b)                     for a - b 
  70.    -- __mul(a, b)                     for a * b 
  71.    -- __div(a, b)                     for a / b 
  72.    -- __mod(a, b)                     for a % b 
  73.    -- __pow(a, b)                     for a ^ b 
  74.    -- __unm(a)                        for -a 
  75.    -- __concat(a, b)                  for a .. b 
  76.    -- __len(a)                        for #a 
  77.    -- __eq(a, b)                      for a == b 
  78.    -- __lt(a, b)                      for a < b 
  79.    -- __le(a, b)                      for a <= b 
  80.    -- __index(a, b)  <fn or a table>  for a.b 
  81.    -- __newindex(a, b, c)             for a.b = c 
  82.    -- __call(a, ...)                  for a(...) 
  83.    ``` 

以上參考了

[learn lua in y minute](https://learnxinyminutes.com/docs/zh-cn/lua-cn/ ) ,做了適當(dāng)?shù)牟眉魜碜稣f明。

4.1 Lua 語言個性的一面

4.1.1 ***道墻: 打印 table

作為 lua 里面唯一標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu), 直接打印居然只有一個 id 狀的東西,這里說這一點(diǎn)沒有抱怨的意思,只是讓讀者做好倒騰的心理準(zhǔn)備,畢竟倒騰一個簡潔語言終歸是有代價的。

了解決定背后的原因,有時候比現(xiàn)成的一步到位的現(xiàn)成方案這也是倒騰的另一面好處吧,這里給出社區(qū)里面的[討論](http://luausers.org/wiki/TableSerialization)

舉個例子:

lua 里面一般使用 #table 來獲取 table 的長度,究其原因,lua 對于未定義的變量、table 的鍵,總是返回 nil,而不像 python 里面肯定是拋出異常, 所以 # 來計算 table 長度的時候只會遍歷到***個值為 nil 的地方,畢竟他不能一直嘗試下去,這時候就需要使用 table.maxn 的方式來獲取了。

4.1.2 Good or Bad ? 自動類型轉(zhuǎn)換

如果你在 python 里面去把一個字符串和數(shù)字相加,python 必定以異?;貞?yīng)。

  1. ```python 
  2. >>> "a" + 1 
  3. Traceback (most recent call last): 
  4.   File "<stdin>", line 1, in <module> 
  5. TypeError: cannot concatenate 'str' and 'int' objects 
  6. ``` 

但是 Lua 覺得他能搞定。

  1. ```lua 
  2. > = "20" + 10 
  3. 30 
  4. ``` 

如果你覺得 Lua 選擇轉(zhuǎn)換加號操作符的操作數(shù)成數(shù)字類型去進(jìn)行求值顯得不可思議的,下面這種情況下,這種轉(zhuǎn)換又貌似是可以有點(diǎn)用的了 print("hello" .. 123) ,這時你不用手動去將所有參數(shù)手工轉(zhuǎn)換成字符串類型。

尚沒有定論說這項(xiàng)特性就是一無是處,但是這種依賴語言本身不明顯的特性的代碼筆者是不希望在項(xiàng)目里面去踩雷的。

4.1.3 多返回值

Lua 開始變得越來越與眾不同了:允許函數(shù)返回多個結(jié)果。

  1. ``` 
  2.     function foo0() end --無返回值 
  3.     function foo1() return 'a' end -- 返回一個結(jié)果 
  4.     function foo2() return 'a','b' end -- 返回兩個結(jié)果 
  5.     -- 多重賦值時, 函數(shù)調(diào)用是***一個表達(dá)式時 
  6.     -- 保留盡可能多的返回值 
  7.     x, y = foo2()     -- x='a'y='b' 
  8.     x = foo2()        -- x='a', 'b'被丟棄 
  9.     x,y,z = 10,foo2()    -- x=10y='a'z='b' 
  10.     -- 如果多重賦值時,函數(shù)調(diào)用不是***一個表達(dá)式時 
  11.     -- 只產(chǎn)生一個值 
  12.     x, y = foo2(),20   -- x='a'y=20    
  13.     x,y = foo0(), 20, 30 -- x=nily20,30被丟棄,這種情況當(dāng)函數(shù)沒有返回值時,會用nil來補(bǔ)充。 
  14.     x,y,z = foo2() -- x='a'y='b'z=nil, 這種情況函數(shù)沒有足夠的返回值時也會用nil來補(bǔ)充。 
  15.     -- 同樣在函數(shù)調(diào)用、table聲明中 函數(shù)調(diào)用作為***的表達(dá)式,都會竟可能多的填充返回值,如果不是***,則只返回一個 
  16.     print(foo2(), 1)    --> a  1 
  17.     print(1, foo2())    --> 1  a  b 
  18.     t = {foo2(), 1}     --> {'a', 1} 
  19.     t = {1, foo2()}     --> {1, 'a', 'b'} 
  20.     -- 阻止這種參數(shù)順序搞事: 
  21.     print(1, (foo2())) -- 1 a 加一層括號,強(qiáng)制只返回一個值 
  22.     ``` 

4.1.4 真?zhèn)€性: 模式匹配

簡潔的 Lua 容不下行數(shù)比自己實(shí)現(xiàn)語言行數(shù)還多的正則表達(dá)式實(shí)現(xiàn)(無論是 POSIX ,還是 Perl 正則表達(dá)式),于是乎有了獨(dú)樹一幟的模式與匹配,下面只用模式匹配來做 URL 解碼、編碼功能實(shí)現(xiàn)的演示。

  1. ``` 
  2.   -- 解碼 
  3.   function unescape(s) 
  4.     s = string.gsub(s, "+", " ") 
  5.     s = string.gsub(s, "%%(%x%x)", function (h) 
  6.           return string.char(tonumber(h, 16)) 
  7.         end) 
  8.     return s   
  9.   end 
  10.   print(unescape("a%2Bb+%3D+c")) ---> a+b =c 
  11.   cgi = {} 
  12.   function decode(s) 
  13.     for name,value in string.gmatch(s, "([^&=]+)=([^&=]+)") do 
  14.       name = unescape(name) 
  15.       value = unescape(value) 
  16.       cgi[name] = value 
  17.     end 
  18.   end 
  19.   -- 編碼 
  20.   function escape(s) 
  21.     s = string.gsub(s, "[&=+%%%c]", function(c) 
  22.         return string.format("%%%02X", string.byte(c)) 
  23.       end) 
  24.     s = string.gsub(s, " ", "+") 
  25.     return s 
  26.   end   
  27.   function encode(t) 
  28.     local b = {} 
  29.     for k,v in pairs(t) do 
  30.       b[#b+1] = (escape(k) .. "=" .. escape(v)) 
  31.     end 
  32.     return table.concat(b,'&') 
  33.   end 
  34.   ``` 

模式匹配實(shí)現(xiàn)的功能是足夠強(qiáng)大,但是工程上是否值得投入還值得商榷,沒有通用性,只此 lua 一家用。

雖然正則表達(dá)式也是不好調(diào)試,但是至少知道了解的人多,可能到***筆者也不會多深入 lua 的模式匹配,但是如此單純?yōu)榱藴p少代碼而放棄正則表達(dá)式現(xiàn)成的庫,自己又玩了一套,這也是沒誰了。

4.1.5 與 c 的天然親密

一言不合,就拿 c 寫一個庫給 lua 用,由此可見兩門語言是多么哥倆好了。如果舉個例子的話就是 lua5.1 里面的位操作符,luajit 就是這樣提供的解決方案 [Lua Bit Operations Module](http://bitop.luajit.org ),有興趣的讀者可以下載源碼看一下,完全就是用 lua 的 c api 包裝了 c 里面的位操作符出來用。

除了加了些限制的話(ex. 位移出來的必然是 32 位有符)。lua 除了數(shù)據(jù)結(jié)構(gòu)上面的過于簡潔外,其他的控制結(jié)構(gòu)、操作符這些語言特性基本該有的都有了,唯獨(dú)缺了位操作符。

5.1 為什么當(dāng)時選擇了不實(shí)現(xiàn)位操作符呢?有知道出處或者原因的讀者歡迎留言告知。(順帶一提,lua5.2 里面有官方的 bit32 庫可以用,lua5.3 已經(jīng)補(bǔ)上了位操作符,另外 Openresty 在 lua 版本的選擇上是選擇停留在 5.1,這點(diǎn)在 github 的 Issue 里面有回答過,且沒有升級的打算)。

4.1.6 雜

  • 只有 nil 、false 為布爾假。
  • lua 中的索引習(xí)慣以 1 開始。
  • 沒有整型,所有數(shù)字都是浮點(diǎn)數(shù)。
  • 當(dāng)函數(shù)的參數(shù)是單引號或者雙引號的字符串或者 table 定義的時候,可以省略外面的 () , 所以 require "cookie" 并不是代表 require 是個關(guān)鍵字。
  • table[index] 等價于 table [index] 。

5. 構(gòu)建公司層面完整的 Openresty 生態(tài)

5.1 開發(fā)助手:成長中的 resty 命令

習(xí)慣了動態(tài)語言的解釋器的立即反饋,哪怕是熟悉 lua 的同學(xué),初入 Openresty 的時候似乎又想起了編譯->執(zhí)行->修改的***循環(huán)的記憶,因?yàn)槊看味夹枰薷呐渲梦募eload 、測試再如此重復(fù)個幾次才能寫對一段函數(shù),resty 命令無疑期待,筆者也希望 resty 命令能夠更加完善、易用。

另外提一個小遺憾,現(xiàn)在 resty 命令不能玩 Openresty 里面的 shared_dict 共享內(nèi)存, 這可能跟目前 resty 使用的 nginx 配置的模板是固定有關(guān)吧。

5.2 環(huán)境:可能不再需要重新編譯 Nginx

有過 Nginx 維護(hù)開發(fā)經(jīng)驗(yàn)的同學(xué)可能都熟悉這么一個過程,因?yàn)槎喟霑鰳I(yè)務(wù)的拆分,除了小公司外,基本都不會把一個 Nginx 的所有可選模塊都編譯進(jìn)去,每次有新的 Nginx 相關(guān)的功能的增減,都免不了重新編譯,重新部署上線。

Openresty 是基于 Nginx 的,如果是新增 Nginx 本身的功能,重新編譯增加功能沒什么好說的,如何優(yōu)雅的更新 Nginx 服務(wù)進(jìn)程,Nginx 有提供方案、各家也有各家的服務(wù)可靠性要求,具體怎么辦這里就不贅述了。

5.3 發(fā)布部署

Openresty 本身的發(fā)布部署跟 Nginx 本身沒有太大的不同,Openresty 本身的發(fā)布部署官方也推出了 linux 平臺的預(yù)編譯好的包,在這樣的基礎(chǔ)上構(gòu)建環(huán)境就更加便捷。

環(huán)境之上,首先是 lua 腳本和 nginx 配置文件的發(fā)布,在版本管理之下,加上自動構(gòu)建的發(fā)布平臺,Openresty 的應(yīng)用分分鐘就可以上線了:)

這個流程本身無關(guān) Openresty ,但是簡而言之一句話,當(dāng)重復(fù)性的東西自動化之后,我們才有精力去解決更有趣的問題,不是么?

5.4 第三方庫的安裝、管理

(1)以前:自己找個第三方庫編譯之后扔到 Openresty 的 lualib 目錄,luajit 是否兼容、是否 lua5.1 兼容都得自己來測試一遍。

(2)之前:對于解決前一個問題,Openresty 是通過給出 lua 里面 Luarocks 的安裝使用來解決的,但是這種方式不能解決上面所說的第二個問題,所以現(xiàn)在這種方式已經(jīng)不推薦使用了,下面貼一下官網(wǎng)的說明,只做內(nèi)容收集、展示用, ***的具體說明參見[using luarocks](http://openresty.org/en/using-luarocks.html)。

  1. ``` 
  2. wget http://luarocks.org/releases/luarocks-2.0.13.tar.gz 
  3. tar -xzvf luarocks-2.0.13.tar.gz 
  4. cd luarocks-2.0.13/ 
  5. ./configure --prefix=/usr/local/openresty/luajit \ 
  6.     --with-lua=/usr/local/openresty/luajit/ \ 
  7.     --lua-suffix=jit \ 
  8.     --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 
  9. make 
  10. sudo make install 
  11. ``` 

安裝第三方庫示例:

  1. sudo /usr/local/openresty/luajit/luarocks install md5。 

(3)現(xiàn)在:Openresty 提供了解決這兩個問題的完整方案,自己的包管理的規(guī)范和倉庫[opm](https://opm.openresty.org/)。

詳細(xì)的標(biāo)準(zhǔn)說明, 請移步:https://github.com/openresty/opm#readme, 這里就不多做介紹了。

關(guān)于第三方庫的質(zhì)量,Openresty 官網(wǎng)上也有了專門的[QA頁面](http://qa.openresty.org/),至少保證了第三方庫一些實(shí)現(xiàn)的下限,不像 python 里面安裝某些第三方包,比如 aerospike 的,里面安裝 python 客戶端,每次要去網(wǎng)上拉個 c 的客戶端下來之類的稀奇古怪的玩法,期待 opm 未來更加完善。

5.5 關(guān)于單元測試

關(guān)于自動化測試的話,就筆者的試用經(jīng)驗(yàn)而言,感覺還不是特別的順手,官方提供的 Test:Nginx 工具已經(jīng)提供簡潔強(qiáng)大的功能,但是如果作為 TDD 開發(fā)中的測試驅(qū)動的工具而言,筆者覺得報錯信息的有效性上面可能是唯一讓人有點(diǎn)覺得有點(diǎn)捉雞的地方,尚不清楚是否是筆者用的有誤——

一般 Test:Nginx 的報錯多半無法幫助調(diào)試代碼,還是要走調(diào)試、修改的老路子。但是 Test:Nginx 的真正價值筆者覺得是講實(shí)例代碼和測試***的結(jié)合,由此養(yǎng)成了看每個 Openresty 相關(guān)的項(xiàng)目代碼都必先閱讀里面的 Test:Nginx 的測試,當(dāng)然最多最豐富的還是 Openresty 本身的測試。

舉個實(shí)際的例子:

在使用 Test:Nginx 之前,之前對于 Nginx 的日志輸出,一切的測試依據(jù),對于外面的運(yùn)行環(huán)境跑的測試只能通過 http 的請求和返回來做測試的判斷條件,這時候?qū)τ谝恍┣闆r就束手無策了, 比如處理某種錯誤情況可能需要在 log 里面記錄一下,這種測試就無法保證。

另外也有類似[lua-resty-test](https://github.com/membphis/lua-resty-test)這樣通過提供組件的方式來進(jìn)行,但是我們一旦接觸的了 Test:Nginx 的測試方法之后,這些就顯得相形見絀了,我們舉個實(shí)際的例子。

  1. ``` 
  2.    # vim:set ftts=4 sw=4 et fdm=marker
  3.    use Test::Nginx::Socket::Lua; 
  4.    #worker_connections(1014); 
  5.    #master_process_enabled(1); 
  6.    #log_level('warn'); 
  7.    #repeat_each(2); 
  8.    plan tests => repeat_each() * (blocks() * 3 + 0); 
  9.    #no_diff(); 
  10.    no_long_string(); 
  11.    #master_on(); 
  12.    #workers(2); 
  13.    run_tests(); 
  14.    __DATA__ 
  15.    === TEST 1: lpush & lpop 
  16.    --- http_config 
  17.        lua_shared_dict dogs 1m; 
  18.    --- config 
  19.        location = /test { 
  20.            content_by_lua_block { 
  21.                local dogs = ngx.shared.dogs 
  22.                local len, err = dogs:lpush("foo", "bar") 
  23.                if len then 
  24.                    ngx.say("push success") 
  25.                else 
  26.                    ngx.say("push err: ", err) 
  27.                end 
  28.                local val, err = dogs:llen("foo") 
  29.                ngx.say(val, " ", err) 
  30.                local val, err = dogs:lpop("foo") 
  31.                ngx.say(val, " ", err) 
  32.                local val, err = dogs:llen("foo") 
  33.                ngx.say(val, " ", err) 
  34.                local val, err = dogs:lpop("foo") 
  35.                ngx.say(val, " ", err) 
  36.            } 
  37.        } 
  38.    --- request 
  39.    GET /test 
  40.    --- response_body 
  41.    push success 
  42.    1 nil 
  43.    bar nil 
  44.    0 nil 
  45.    nil nil 
  46.    --- no_error_log 
  47.    [error] 
  48.    ``` 

以上是隨便選取的lua-nginx-module的測試文件145-shdict-list.t中的一段做說明,測試文件分為3個部分:

  • __DATA__以上的部分編排測試如何運(yùn)行,
  • __DATA__作為分隔符,
  • __DATA__以下的是各個測試的說明部分。

測試部分如果具體細(xì)分的話,

  • 一般由 ====TEST 1: name 開始到下一個測試的聲明;
  • 然后是配置 nginx 配置的 http_config、config、... 的部分;
  • 接著是模擬請求的部分,基本就是 http 請求報文的設(shè)定,功能不限于這里的 request 部分;
  • ***是輸出部分,這時候不僅是 http 報文的 body 部分之類的 http 響應(yīng)、還有 nginx 的日志的輸出這樣的測試條件。

對于這樣清晰可讀、還能順帶把使用例子寫的清楚的單元測試的框架, pythoner 真的難道不羨慕么?

5.6 關(guān)于調(diào)試、性能調(diào)優(yōu)

這一塊筆者還沒有深入研究過,所以這里就不多說了,這里就做一下相關(guān)知識的鏈接歸納,方便大家整理資料吧。lua 語言本身提供的調(diào)試就比較簡潔、加上 Openresty 是嵌入 Nginx 內(nèi)部的,這就更給排查工作帶來了困難。

(1)[官方的調(diào)試頁面]

(http://openresty.org/en/debugging.html )

(2)[官方的性能調(diào)優(yōu)頁面]

(http://openresty.org/en/profiling.html )

(3)[通過systemtap探查在線的Nginx work進(jìn)程]

(https://github.com/agentzh/nginx-systemtap-toolkit)

(4)[額外的工具庫stap++]

(https://github.com/agentzh/stapxx )

(5)[工具火焰圖Flame Graphs的介紹]

(http://dtrace.org/blogs/brendan/2011/12/16/flame-graphs/ )

(6)[Linux Kernel Performance: Flame Graphs]

(http://dtrace.org/blogs/brendan/2012/03/17/linux-kernel-performance-flame-graphs/ )

【本文是51CTO專欄機(jī)構(gòu)“豈安科技”的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(bigsec)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2011-06-16 10:25:29

AndroidAIR

2009-07-08 09:44:54

TDDViual Studi

2012-03-16 13:43:29

2010-10-09 15:01:27

PhoneGapiPhoneAndroid

2014-06-05 14:12:05

SwiftUI學(xué)習(xí)iOS

2024-06-05 09:22:43

2009-10-30 10:45:45

ScalaEclipseAndroid

2011-08-23 17:52:39

LUAWeb 開發(fā)

2016-08-23 14:37:21

2023-12-18 10:15:30

自動駕駛自然語言

2010-08-18 09:23:19

Flash Lite移動應(yīng)用程序開發(fā)

2014-12-17 11:09:39

Hybrid AppWebView裝載頁面

2016-11-28 09:19:27

2010-08-03 10:32:42

Android 3.0Android 3.0Android開發(fā)

2024-12-06 09:47:13

2010-08-11 10:58:06

AndroidAndroid NDK

2009-10-15 15:12:39

Equinox服務(wù)器端Equinox

2011-01-11 11:35:17

jQueryAndroidgoogle

2009-11-03 10:04:06

VS.PHPVisual StudPHP

2010-06-03 12:57:06

Hadoop
點(diǎn)贊
收藏

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