__讀書筆記

Chris Lattner訪談錄 

1,LLVM(Low Level Virtual Machine):node

    先說說什麼是編譯器:編譯器就是把程序員的代碼翻譯成機器能夠理解的語言的工具。python

    再談談LLVM:一個模塊化和可重用的編譯器和工具連接技術的集合,clang是LLVM的子項目,是c,c++,oc編譯器,由於多模塊的複用,因此提供了驚人的快速編譯,比gcc快3倍。其中的 clang static analyzer 主要是進行語法分析,語義分析和生成中間代碼,固然這個過程會對代碼進行檢查,出錯的和須要警告的會標註出來。LLVM 核心庫提供一個優化器,對流行的 CPU 作代碼生成支持。lld 是 Clang / LLVM 的內置連接器,clang 必須調用連接器來產生可執行文件。LLVM 比較有特點的一點是它能提供一種代碼編寫良好的中間表示 IR,這意味着它能夠做爲多種語言的後端,這樣就可以提供語言無關的優化同時還可以方便的針對多種 CPU 的代碼生成。ios

2,LLVM三層結構:c++

      第一層:clang編譯器,負責編譯各類語言;第二層:代碼優化器,經過模塊化操做優化代碼,是bitcode邏輯的主要部分;第三層:代碼翻譯器,針對不一樣平臺和GPU將代碼翻譯成機器語言程序員

3,LLDB:一個有着repl的特性和c++,python插件的開源調試器,LLDB綁定在xcode內部,存在與主窗口底部的控制檯中web

4,libc++,libc++ ABI:高性能c++標準庫實現,支持c++ 11算法

5,compiler -rt:爲LLVM和clang設計的編譯器擴展函數庫。針對__fixunsdfdi和其餘目標機器上沒有一個核心IR(intermediate representation)對應的短原生指令序列時,提供高度調優過的底層代碼生成支持。編程

6, ABI (Application Binary Interface),中文名:應用二進制接口,是app和操做系統、其餘應用之間的二進制接口。它包括如下細節:數據類型的大小、佈局和對齊;調用約定(控制着函數的參數如何傳送以及如何接受返回值),例如,是全部的參數都經過棧傳遞仍是部分參數經過寄存器傳遞,哪一個寄存器用於哪一個函數參數;經過棧傳遞的第一個函數參數是最早push到棧上仍是最後;系統調用的編碼和一個應用如何向操做系統進行系統調用;以及在一個完整的操做系統abi中,目標文件的二進制格式,程序庫等等。swift

7,在xcode的project editor中的Build Setting,Build Phases和Build Rules可以控制編譯的過程。其中,後端

Build Phases:構建可執行文件的規則,指定target的依賴項目,在target build以前須要先build的依賴,在compile source 中指定全部必須編譯的文件,這些文件會根據building setting build rules裏的設置來處理。在Link Binary With Libraries裏會列出全部的靜態庫和動態庫,它們會和編譯生成的目標文件進行連接。build phases 還會把靜態資源拷貝到bundle裏。還能夠經過在build phases裏添加自定義腳原本作些事情,好比像 CocoaPods 所作的那樣。

Build Rules:指定不一樣文件類型如何編譯。每條 build rule 指定了該類型如何處理以及輸出在哪。能夠增長一條新規則對特定文件類型添加處理方法。

Build Settings:在 build 的過程當中各個階段的選項的設置。

8,靜態分析( clang static analyzer):詞法->語法->語義->IR->優化->CodeGen

9,IR 總體結構:一個編譯的單元即一個文件在 IR 裏就是一個 Module,最大的是 Module,裏面包含多個 Function,每一個 Function 包含多個 BasicBlock,BasicBlock 裏含有 Instruction,代碼很是清晰,這樣若是想開發一個新語言只須要完成語法解析後經過 LLVM 提供的豐富接口在內存中生成 IR 就能夠直接運行在各個不一樣的平臺。IR 語言知足靜態單賦值,能夠很好的下降數據流分析和控制流分析的複雜度。及只能在定義時賦值,後面不能更改。可是這樣就無法寫程序了,輸入輸出都無法弄,因此函數式編程纔會有相似 Monad 這樣機制的緣由。

10,dSYM 文件:在每次編譯後都會生成一個 dSYM 文件,程序在執行中經過地址來調用方法函數,而 dSYM 文件裏存儲了函數地址映射,這樣調用棧裏的地址能夠經過 dSYM 這個映射表可以得到具體函數的位置。通常都會用來處理 crash 時獲取到的調用棧 .crash 文件將其符號化。能夠經過 Xcode 進行符號化,將 .crash 文件,.dSYM 和 .app 文件放到同一個目錄下,打開 Xcode 的 Window 菜單下的 organizer,再點擊 Device tab,最後選中左邊的 Device Logs。選擇 import 將 .crash 文件導入就能夠看到 crash 的詳細 log 了。還能夠經過命令行工具 symbolicatecrash 來手動符號化 crash log。一樣先將 .crash 文件,.dSYM 和 .app 文件放到同一個目錄下,而後輸入下面的命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer symbolicatecrash appName.crash appName.app > appName.log

11,Mach-O 文件:記錄編譯後的可執行文件,對象代碼,共享庫,動態加載代碼和內存轉儲的文件格式。不一樣於 xml 這樣的文件,它只是二進制字節流,裏面有不一樣的包含元信息的數據塊,好比字節順序,cpu 類型,塊大小等。文件內容是不能夠修改的,由於在 .app 目錄中有個 _CodeSignature 的目錄,裏面包含了程序代碼的簽名,這個簽名的做用就是保證簽名後 .app 裏的文件,包括資源文件,Mach-O 文件都不可以更改。

Mach-O 文件包含三個區域:

     Mach-O Header:包含字節順序,magic,cpu 類型,加載指令的數量等

     Load Commands:包含不少內容的表,包括區域的位置,符號表,動態符號表等。每一個加載指令包含一個元信息,好比指令類型,名稱,在二進制中的位置等。

     Data:最大的部分,包含了代碼,數據,好比符號表,動態符號表等。

12,dyld動態連接:生成可執行文件後就是在啓動時進行動態連接了,進行符號和地址的綁定。首先會加載所依賴的 dylibs,修正地址偏移,由於 iOS 會用 ASLR 來作地址偏移避免攻擊,肯定 Non-Lazy Pointer 地址進行符號地址綁定,加載全部類,最後執行 load 方法和 clang attribute 的 constructor 修飾函數。

13,dylib 這種格式的表示是動態連接的,編譯的時候不會被編譯到執行文件中,在程序執行的時候才 link,這樣就不用算到包的大小裏,並且也可以不更新執行程序就可以更新庫。

HTTP 2.0的那些事 

1,HTTP站在TCP之上:HTTP是創建在TCP協議之上的,TCP協議做爲傳輸層協議其實離應用層並不遠。HTTP協議的瓶頸及其優化技巧都是基於tcp協議自己的特性,好比tcp創建連接時三次握手有1.5個RTT (round-trip time)的延遲,爲了不每次請求都經歷握手帶來的延遲,應用層會選擇不一樣策略的http長連接方案,又好比tcp在創建鏈接時的初期有慢啓動,(slow start)的特性,因此鏈接的重用總比新建鏈接性能要好。

2,影響一個網絡請求有2個因素:帶寬和延遲。隨着基礎建設的完善,帶寬已經有了很大的改善,因此如今延遲就變成了影響網絡請求最主要的緣由。

3,客戶端是依據域名來向服務器創建鏈接的,通常pc端瀏覽器會針對單個域名的server同時創建6-8個鏈接,而手機端則控制在4-6個,顯然鏈接數並非越多越好,由於鏈接數越多帶來的資源開銷和總體延遲都會變大。

4,http1.0的主要面臨的問題有2個:第一就是鏈接沒法複用,這樣就致使每次請求都會經歷三次握手和慢啓動,三次握手在高延遲的場景下更明顯,若是某次握手過程當中,某一次發生了延遲,這就致使整個過程都會延遲,慢啓動則對文件類請求影響較大;第二就是head of line blocking,這個會致使帶寬沒法充分被利用,以及後續健康請求被阻塞。多個請求一塊兒發生時,請求也是一個接着一個進行的,至關於串行隊列,後面的須要等到前面的返回了纔開始,若是一個有延遲或者不回來,後面的就都有問題了。

5,針對http1.0的鏈接沒法複用的問題,有如下四種方案:(僅app端)

      a:基於tcp的長鏈接,其實就是基於socket的編程,本身制定協議。

      b:http long-polling,就是開始就發出鏈接,可是不立刻返回,等到有新數據才返回,始終有一個鏈接保持着,返回後用立刻發出新的鏈接,如此往復。(單向)

      c:http streaming,跟b相似,不過初始的streaming不會結束,一直經過這個通道返回數據。(單向)

      d:web socket,基於tcp協議,提供雙向數據通道,且提供了message的概念,比基於字節流的tcp socket更簡單,並且也有長鏈接功能,不過比較新,有些不支持。

6,head of line blocking:是http2.0以前網絡體驗的最大禍源,健康的請求會被不健康的請求影響,並且這種體驗的損耗受網絡環境的影響,出現隨機而難以控制。爲了解決延遲這個問題,協議的設計者們設計了一種全新的pipelining,可是其實也沒有什麼卵用,區別把幾個請求一次發送過去,不過回來的時候仍是要等的,本質上仍是沒有解決問題。

7,致使網絡請求延遲的有:tcp初期的slow start,tcp的三次握手,dns查詢的延遲等。

8,http2.0是以SPDY爲原型進行討論和標準化的。SPDY基礎功能包括:多路複用,請求優先級,header壓縮;高級功能包括:server高級推送,server暗示。

9,HTTP2.0針對HTTP1.x的主要改動以下:

       1,新的二進制格式:HTTP1.x使用的是明文協議,而HTTP2.0使用的是binary格式

       2,鏈接共享:多路複用,同時還能夠設置優先級和依賴

       3,header壓縮:高效的壓縮算法很大的壓縮header,減小發送包的數量從而下降延遲

       4,HPACK壓縮算法的使用

       5,重置鏈接表現更好

       6,server push

       7,用相似tcp的receive window作流量控制

       8,更安全的ssl

10,iOS http現狀:iOS系統是從iOS8開始經過NSURLSession來支持SPDY的,iOS9+開始自動支持http2.0;怎麼配置最佳的http方案這個因app而異,一是app自己http流量是否大並且密集,二是團隊自己的技術條件。http2.0的部署相對容易,客戶端開發者甚至不用作什麼改動,只須要使用iOS9的sdk編譯便可,可是缺點是http2.0只適用於iOS9的設備;SPDY的部署相對麻煩一些,不過能夠兼容iOS6+的設備,因此這個具體本身看吧。

Auto Layout :Snapkit源碼剖析

1,Snapkit是目前Swift中經過代碼進行Auto Layout佈局時最流行的開源庫。與OC中最主流的Auto Layout開源庫Masonry是同一個團隊維護,有着類似的API風格。

2,Snapkit因爲是swift寫的,我之前看過,不過好久沒有再看,項目也沒有用到,因此這個源碼解析我基本沒看懂,哈哈。

3,fastlane是一套自動化打包的工具集,用ruby寫的,用於ios和Android的自動化打包和發佈等工做。

CFArray的歷史淵源以及實現原理 

1,在ObjC的初期(2011年以前),CFArray是使用deque雙端隊列實現的,因此會呈現出頭尾操做高效,而中間操做成線性的特色,在容量超過300000左右時,時間複雜度發生陡變。當數據超出閥值的時候,會將數據結構從CFArray轉換成CFStorage,CFStorage是一個平衡二叉樹結構,爲了維護數組的順序訪問,將node的權值使用下標完成插入和旋轉操做。不過在2011年之後,CFArray取消了數據結構轉換這一功能,或許是爲了防止大數據時候二叉樹建樹的時間抖動問題從而取消的這個特性。其實從它數據結構描述看來,CFArray就是由單一的雙端隊列進行實現,並且還記錄了一些容量信息。

2,C中數組最顯著的缺點就是在下標0處插入時,須要移動全部的元素,相似的,當刪除第一個元素,在第一個元素前插入一個元素也會形成O(n)複雜度的操做,然而數組是常讀寫容器,因此O(n)的操做會形成很嚴重的時間開銷。

load 方法的調用時機

1,dyld(The Dynamic Link Editor)是蘋果的動態連接庫,系統內核作好啓動程序的初始準備後,將其餘事務交給dyld負責。

2,鏡像(images)表示的是二進制文件(可執行文件或者動態連接庫的.so文件)編譯後的符號,代碼等。

3,+ load 方法:做爲 Objective-C 中的一個方法,與其它方法有很大的不一樣。它只是一個在整個文件被加載到運行時,在 main 函數調用以前被 ObjC 運行時調用的鉤子方法。關鍵字有那麼幾個:文件剛加載,main 函數以前,鉤子方法;

4,load 方法是如何被調用的?當 Objective-C 運行時初始化的時候,會經過 dyld_register_image_state_change_handler 在每次有新的鏡像加入運行時的時候,進行回調。執行 load_images 將全部包含 load 方法的文件加入列表 loadable_classes ,而後從這個列表中找到對應的 load 方法的實現,調用 load 方法。

5,對於 load 方法的調用順序有兩條規則:父類先於子類調用,類先於分類調用;爲何會這樣呢,那是由於若是你看過源碼你就會發如今把它們添加進能夠加載的列表以前就把順序定好了,好比加進列表的時候會先添加父類再添加子類,先添加類,再添加分類,這樣就能確保調用的順序是正確的。

6,load 的應用:load 能夠說咱們在平常開發中能夠接觸到的調用時間最靠前的方法,在主函數運行以前,load 方法就會調用。因爲它的調用不是惰性的,且其只會在程序調用期間調用一次,最最重要的是,若是在類與分類中都實現了 load 方法,它們都會被調用,不像其它的在分類中實現的方法會被覆蓋,這就使 load 方法成爲了方法調劑(Method swizzling)的絕佳時機。可是因爲 load 方法的運行時間過早,因此這裏可能不是一個理想的環境,由於某些類可能須要在在其它類以前加載,可是這是咱們沒法保證的。不過在這個時間點,全部的 framework 都已經加載到了運行時中,因此調用 framework 中的方法都是安全的。

7,Load 方法做用:load方法是咱們在開發中最接近app啓動的可控方法,即在app啓動之後,入口函數main以前,因爲調用有着non-lazy屬性,而且運行期只調用一次,因而咱們可使用load獨有的特性和調用時機來嘗試Method Swizzling,固然由於load調用時機過早,而且當多個class沒有關聯(繼承與派生),咱們沒法知道class中load方法的優先調用關係,因此通常不會在load方法中引入其餘的類,這是在開發中要注意的。

相關文章
相關標籤/搜索