日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS 瘦身之道

發(fā)布時間:2023/12/20 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS 瘦身之道 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

App 的包大小做優(yōu)化的目的就是為了節(jié)省用戶流量,提高用戶的下載速度,也是為了用戶手機節(jié)省更多的空間。另外 App Store 官方規(guī)定 App 安裝包如果超過 150MB,那么不可以使 OTA(over-the-air)環(huán)境下載,也就是只可以在 WiFi 環(huán)境下載,企業(yè)或者獨立開發(fā)者萬萬不想看到這一點。免得失去大量的用戶。

同時如果你的 App 需要適配 iOS7、iOS8 那么官方規(guī)定主二進制 text 段的大小不能超過 60MB。如果不能滿足這個標準,則無法上架 App Store。

另一種情況是 App 包體積過大,對用戶更新升級率也會有很大影響。

所以應(yīng)用包的瘦身迫在眉睫。

1. App Thinning

App Thinning 是指 iOS9 以后引入的一項優(yōu)化,官方描述如下

The App Store and operating system optimize the installation of iOS, tvOS, and watchOS apps by tailoring app delivery to the capabilities of the user’s particular device, with minimal footprint. This optimization, called app thinning, lets you create apps that use the most device features, occupy minimum disk space, and accommodate future updates that can be applied by Apple. Faster downloads and more space for other apps and content provides a better user experience.

Apple 會盡可能,自動降低分發(fā)到具體用戶時,所需要下載的 App 大小。其中包含三項主要功能:Slicing、Bitcode、On-Demand Resources。

App Thinning 是蘋果公司推出的一項改善 App 下載進程的新技術(shù),主要為了解決用戶下載 App 耗費過高流量的問題,同時還可以節(jié)省用戶設(shè)備存儲空間。

1.1 Slicing

當向 App Store Connect 上傳 .ipa 后,App Store Connect 構(gòu)建過程中,會自動分割該 App,創(chuàng)建特定的變體(variant)以適配不同設(shè)備。然后用戶從 App Store 中下載到的安裝包,即這個特定的變體,這一過程叫做 Slicing。

Slicing 是創(chuàng)建、分發(fā)不同變體以適應(yīng)不同目標設(shè)備的過程

而變體之間的差異,又具體體現(xiàn)在架構(gòu)和資源上。換句話說,App Slicing 僅向設(shè)備傳送與之相關(guān)的資源(取決于屏幕分辨率、系統(tǒng)架構(gòu)等等)

其中,2x 和 3x 的細分,要求圖片在 Assets 中管理。Bundle 內(nèi)的則會同時包含。

1.2 Bitcode

Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the App Store. Including bitcode will allow Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the App Store.

Bitcode 是一種程序中間碼。包含 Bitcode 配置的程序?qū)?App Store Connect 上被重新編譯和鏈接,進而對可執(zhí)行文件做優(yōu)化。這部分都是在服務(wù)端自動完成的。所以假如以后 Apple 新推出了新的 CPU 架構(gòu)或者以后 LLVM 推出了一系列優(yōu)化,我們不需要重新為其發(fā)布新的安裝包了。Apple Store 會為我們自動完成這步。然后提供對應(yīng)的 variant 給具體設(shè)備

對于 iOS 而言,Bitcode 是可選的(Xcode7 以后創(chuàng)建的新項目默認開啟),watchOS、tvOS 則是必須的。

開啟位置:Build Settings -> Enable Bitcode -> 設(shè)置為 YES

開啟 Bitcode,有這么2點需要注意:

  • 全部都要支持。我們所依賴的靜態(tài)庫、動態(tài)庫、Cocoapods 管理的第三方庫,都需要開啟 Bitcode。否則會編譯失敗

  • 奔潰定位。開啟 Bitcode 后最終生成的可執(zhí)行文件是 Apple 自動生成的,同時會產(chǎn)生新的符號表文件,所以我們無法使用自己包生成的 dYSM 符號化文件來進行符號化。

For Bitcode enabled builds that have been released to the iTunes store or submitted to TestFlight, Apple generates new dSYMs. You’ll need to download the regenerated dSYMs from Xcode and then upload them to Crashlytics so that we can symbolicate crashes.For Bitcode enabled apps, ensure that you have checked “Include app symbols for your application…” so that we can provide the most accurate crash reports.

上面是 fabric 中關(guān)于 Downloading Bitcode dYSMs 的描述:

在上傳到 App Store 時需勾選“Includ app symbols for your application...”。勾選之后 Apple 會自動生成對應(yīng)的 dYSM,然后可以在 Xcode -> Window -> Organizer 中,或者在 Apple Store Connect 中下載對應(yīng)的 dYSM 來進行符號化

那么 Bitcode 會對 App Thining 有什么作用?

在 New Features in Xcode7 中有這么一段描述:

Bitcode. When you archive for submission to the App Store, Xcode will compile your app into an intermediate representation. The App Store will then compile the bitcode down into the 64 or 32 bit executables as necessary.

即,App Store 會再按需將這個 bitcode 編譯進 32/64 位的可執(zhí)行文件。 所以網(wǎng)上鋪天蓋地地說 Bitcode 完成了具體架構(gòu)的拆分,從而實現(xiàn)瘦包

1.3 on-Demand Resources

on-Demand Resource 即一部分圖片可以被放置在蘋果的服務(wù)器上,不隨著 App 的下載而下載,直到用戶真正進入到某個頁面時才下載這些資源文件。

應(yīng)用場景:相機應(yīng)用的貼紙或者濾鏡、關(guān)卡游戲等

如需支持 iOS9 以下系統(tǒng),那么無法使用這個功能,否則上傳會失敗

2 包體積

2個概念

  • .ipa (iOS Application Package):iOS 應(yīng)用程序歸檔文件,即提交到 App Store Connect 的文件

  • .app (Application):應(yīng)用的具體描述,即安裝到 iOS 設(shè)備上的文件

當我們拿到 Archive 后的 .ipa,使用解壓軟件打開后,Payload 目錄下存放的就是 .app 文件,二者大小相當

包體積,評判標準是以 App Store 上看到的為準。但是上傳到 App Store Connect 處理完后,會自動幫我們生成具體設(shè)備上看到的大小。如下:

這其中:又可以分為2類: Universal 和具體設(shè)備 Universal 指通用設(shè)備,即未應(yīng)用 App slicing 優(yōu)化,同時包含了所有架構(gòu)、資源。所以包體積會比較大

觀察 .ipa 的大小和 Universal 對應(yīng)的包大小相當,稍微小一點,因為 App Store 對 .ipa 做了加密處理

有時候下載 App 會提示“此項目大于 150MB,除非此項目支持增量下載,否則您必須連接至 WiFi 才能下載”。150MB 針對的是下載大小。

  • 下載大小:通過 WiFi 下載的壓縮 App 大小
  • 安裝大小:此 App 將在用戶設(shè)備上占用磁盤空間的大小

所以我們要瘦包,關(guān)鍵在于減小 .app 文件的大小。

2.1 Architectures

如果不支持32位以及 iOS8 ,去掉 armv7 ,可執(zhí)行文件以及庫會減小,即本地 .ipa 也會減小

2.2 Resources

資源的優(yōu)化也就是平時的細心與審查。

圖片、內(nèi)置素材、Bundle、多語言、Json、字體、腳本、Plist、音頻

圖片:Assets.car Bundle: 非放在 Asset Catlog 中管理的圖片資源。包括 Bundle,散落的 png、jpg 等

瘦包具體的方式:

  • 無用資源的刪除
  • 重復(fù)文件的刪除
  • 大文件壓縮
  • 圖片管理方式規(guī)范
  • on-Demand Resource(游戲的、前置關(guān)卡依賴、濾鏡App 等的依賴資源,建議用這種方式動態(tài)下載圖片資源)

2.2.1 無用文件的刪除

無用文件主要包含:無用圖片、無用非圖片部分。

非圖片部分:資源較少,使用方式固定。比如音頻、字體。需要手動排查 圖片部分:主要使用一個開源的 Mac App LSUnusedResources 進行冗余圖片的排查。

刪除無用的圖片過程,可以概括為下面6步:

  • 通過 find 命令獲取 App 安裝包中的所有資源文件
  • 設(shè)置用到的資源類型。比如 gif、jpg、jpeg、png、webp
  • 使用正則匹配出在源碼中使用到的資源名,比如 pattern = @"@"(.+?)""
  • 使用 find 命令找到篇所有資源文件,再去源碼中找到使用到的資源文件,2個集合的差集就是無用資源了。
  • 確認無用資源后可以使用 NSFileManager 進行文件的刪除。
  • 如果不想重新寫一個工具,那么可以直接使用開源的工具 LSUnusedResources

    但是存在一點問題。會出現(xiàn)誤報,因為不同的項目,圖片使用方式不一樣。

    - (BOOL)containsSimilarResourceName:(NSString *)name {NSString *regexStr = @"([-_]?\\d+)";NSRegularExpression* regexExpression = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:nil];NSArray* matchs = [regexExpression matchesInString:name options:0 range:NSMakeRange(0, name.length)];//... } 復(fù)制代碼

    源碼中的正則表達式處理的情況并不是很準確。可以根據(jù)自己的情況修改正則即可

    2.2.2 圖片資源的壓縮

    刪除了無用的資源,那么對于資源這塊還是有操作的空間的,比如圖片資源的壓縮。目前壓縮比較好的方案就是 WebP,它是谷歌公司的一個開源項目。

    WebP 的優(yōu)勢:

    • 壓縮率高。支持有損和無損2種方式,比如將 Gif 圖可以轉(zhuǎn)換為 Animated WebP,有損模式下可以減小 64%,無損模式下可以減小 19%
    • WebP 支持 Alpha 透明和 24-bit 顏色數(shù),不會像 PNG8 那樣因為色彩不夠出現(xiàn)毛邊。

    Google 公司在開源 WebP 的同時,還提供了一個圖片壓縮工具 cwebp。 壓縮完之后使用 WebP 格式的圖片還需使用 libwebp 進行解析,參考這個Demo。

    缺點:WebP 在 CUP 消耗和解碼時間上會比 PNG 高2倍,所以我們做選擇的時候需要取舍。

    2.2.3 重復(fù)文件刪除

    重復(fù)文件,即兩個內(nèi)容完全一致的文件。但是文件命名不一樣。

    借助 fdupes 這個開源工具,校驗各資源的 MD5。

    fdupes 是 Linux 下的一個工具,它由 Adrian Lopez 用 C 語言編寫并基于 MIT 許可證發(fā)行,該應(yīng)用程序可以在指定的目錄及子目錄中查找重復(fù)的文件。fdupes 通過對比文件的 MD5 簽名,以及逐字節(jié)比較文件來識別重復(fù)內(nèi)容,fdupes 有各種選項,可以實現(xiàn)對文件的列出、刪除、替換為文件副本的硬鏈接等操作。

    文件對比從以下順序開始: 大小對比 > 部分 MD5 簽名對比 > 完整 MD5 簽名對比 > 逐字節(jié)對比

    執(zhí)行結(jié)束后會在命令行展示出來,所以需要我們?nèi)斯⑦@些文件確認對比后刪除掉。

    2.2.4 大文件壓縮

    圖片本身的壓縮,建議使用 ImageOptim。它整合了 Win、Linux 上諸多著名圖片處理工具的特色,比如 PNGOUT、AdvPNG、Pngcrush、OptiPNG、JpegOptim、Gifsicle 等。 Bundle 內(nèi)的圖片資源必須壓縮,因為 Xcode 并不會對其進行壓縮。所以做好將圖片都用 Assets 管理。

    Xcode 提供給我們2個編譯選項來幫助壓縮圖像:

    • Compress PNG Files: 打包的時候自動對圖片進行無損壓縮。使用的工具為 pngcrush,壓縮比蠻高。
    • Remove Text Medadata From PNG Files:移除 PNG 資源的文本字符,比如圖像名稱、作者、版權(quán)、創(chuàng)作時間、注釋等信息

    2.2.5 圖片管理方式規(guī)范

    2.2.5.1 主工程中的圖片管理

    工程中所有使用的 Asset Catlog 管理的圖片(在 .xcassets 文件夾下)最終都會輸出到 Asset.car 內(nèi)。不在 Asset.car 內(nèi)的都歸為 Bundle 管理。

    • xcassets 里面的圖片。只能通過 imageNamed 加載。 Bundle 里面的圖片還可以通過 imageWithContentsOfFile 等方式
    • xcassets 里面的 @2x、@3x 會根據(jù)具體設(shè)備分發(fā),不會同時包含。Bundle 都包含(不進行 App Slicing)
    • xcassets 內(nèi)可以對圖片進行 Slicing,即裁剪和拉伸、Bundle 不支持
    • Bundle 內(nèi)支持多語言,Images.xcassets 不支持

    使用 imageNamed 創(chuàng)建的 UIImage 會被立即加入到 NSCache 中(解碼后的 Image Buffer),直到收到內(nèi)存警告的時候才會釋放不使用的 UIImage。而 imageWithContentsOfFile 會每次重新申請內(nèi)存,相同圖片不會緩存,所以 xcassets 內(nèi)的圖片,加載后會產(chǎn)生緩存

    綜上:常用的、較小的圖建議存放在 Images.xcassets 內(nèi)管理。大圖放在 Bundle 內(nèi)管理。

    這里講一個插曲了,曾經(jīng)很多文章都在談一個結(jié)論,那就是「圖片放在 Images.xcassets 里面更加快速且節(jié)省空間,直接放在 bundle 里面會比較慢」。我做過實驗,實驗環(huán)境和結(jié)論如下。使用 Instruments 測量耗時。

    點擊展開//實驗1 NSMutableArray *images = [NSMutableArray array]; for (NSInteger index = 0; index < 10; index++) {UIImage *image = [UIImage imageNamed:@"icon-iOS"];[images addObject:image]; } self.imageView.image = images.lastObject; //實驗2 NSMutableArray *images = [NSMutableArray array]; for (NSInteger index = 0; index < 10; index++) {NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"iOS" ofType:@"png"];[UIImage imageNamed:@"icon-iOS"];UIImage *image = [UIImage imageWithContentsOfFile:imagePath];[images addObject:image]; } self.imageView.image = images.lastObject; 復(fù)制代碼

    Timeprofile-imageNamedFromAssets

    TimeProfile-imageWithContentsOfFile

    Timeprofile-UIImageNamedFromFolder

    Images.xcassets :

    • 圖片大小要精確,不要出現(xiàn)圖片太大的情況
    • 不要存放大圖,不然會產(chǎn)生緩存
    • 不要存 jpg 圖片,打包會變大
    • 圖片不需要額外壓縮(有人做過實驗,對放入 assets 里面的圖片進行壓縮后打包發(fā)現(xiàn)包體積反而增大,懷疑是 Xcode 的編譯選項 Compress PNG Files 自動對圖片進行壓縮,2種壓縮起了沖突反而增大)
    2.2.5.2 各個 pod 庫中的圖片管理

    CocoPods 中兩種資源引用方式介紹下:

    • resource_bundles

      We strongly recommend library developers to adopt resource bundles as there can be name collisions using the resources attribute. 允許定義當前的 pod 庫的最遠包的名稱和文件。用 hash 形式聲明,key 是 bundle 的名稱,value 是需要包含文件的通配 patterns CocoPods 官方強烈推薦該方法引用資源,因為 key-value 可以避免相同資源的名稱沖突

    • resources

      We strongly recommend library developers to adopt resource bundles as there can be name collisions using the resources attribute. Moreover, resources specified with this attribute are copied directly to the client target and therefore they are not optimised by Xcode. 使用該方法引用資源,被指定的資源會被拷貝進 target 工程的 main bundle 中。

    說說項目中的情況吧:在工程中之前是通過 resource_bundles 引用資源的。資源是放在 Resources 目錄下的圖片引用。查詢資料后說「如果圖片資源放到 .xcasset 里面 Xcode 會幫我們自動優(yōu)化、可以使用 Slicing 等(這里不僅僅指的是 resource_bundle 下的 xcassets」。所以動手將各個 Pod 庫里面的圖片全都通過 Assets Catalog 的方式進行處理。

    步驟:

    • 在各個 Pod 組件庫里面的 Resources 目錄下新建 Asset Catalog 文件,命名為 Images.xcassets

    • 將 Resources 里面零散的圖片資源拖進 Images.xcassets 里面

    • 修改每個組件庫的 podspec 文件

      點擊展開s.resource_bundles = {'XQ_UI' => ['XQ_UI/Assets/*.xcassets'] } </details> 復(fù)制代碼
    • 主工程執(zhí)行 pod install

    話說 resources 和 resource_bundles 都可以使用 Asset Catalog,那么有何區(qū)別?

    • resources 只會將資源文件 copy 到 target 工程,最后和 target 工程的圖片資源以及同樣使用該方式的 Pod 庫的圖片資源共同打包到一個 Assets.car 中。因此圖片資源會有混亂的可能。
    • resource_bundles 會生成一個你在 podspec 中指定名稱的 bundle,且在 bundle 中也會生成一個 Assets.car。所以圖片是肯定不會混亂的,但是圖片的訪問方式需要注意。

    解決方法:為每個 pod 新建一個圖片的分類,比如 UIImage+XQUIModule。然后訪問圖片的時候通過 [UIImage xquiModuleImageNamed:@"pull"] 訪問。

    點擊展開#import "UIImage+XQUIModule.h" #import <SDGBase/UIImage+Bundle.h>@implementation UIImage (XQUIModule)+ (nonnull UIImage *)xquiModuleImageNamed:(nonnull NSString *)name {return [UIImage imageNamed:name inBundleName:@"XQ_UI"]; } @end//UIImage+Bundle.m #import "UIImage+Bundle.h"@implementation UIImage (Bundle)+ (nullable UIImage *)imageNamed:(NSString *)name inBundleName:(nullable NSString *)bundleName {NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:bundleName withExtension:@"bundle"]];return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil]; } @end 復(fù)制代碼

    2.2.6 矢量圖的使用

    事實上,對于 App 里面的單色圖標,比如左上角的返回按鈕、底部的 tabBar等,只要是單色的純色圖標都是可以使用矢量圖代替的,比如 PDF、ttf 字體圖標等。這樣就不需要添加 @2x、@3x 圖標,節(jié)省了空間。

    iOS 中如何使用 ttf 矢量圖,可以查看這個 Repo

    3. Executable file

    3.1 編譯選項優(yōu)化

    3.1.1 Generate Debug Symbols

    Enables or disables generation of debug symbos. When debug symbols are enabled, the level of detail can be controller by the build 'Level of Debug Symbols' Setting.

    調(diào)試符號是在編譯時形成的。當 Generate Debug Symbols 選項為 YES 的時,每個源文件在編譯成 .o 文件時,編譯參數(shù)多了 -g 和 -gmodules 兩項。打包會生成 symbols 文件。設(shè)置為 NO 則 ipa 中不會生成 symbol 文件,可以減少 ipa 大小。但會影響到崩潰的定位。保持默認的開啟,不做修改。

    3.1.2 Asset Catalog Compiler

    optimization 選項設(shè)置為 space 可以減少包大小 默認選項,不做修改。

    3.1.3 Dead Code Stripping

    For statically linked executables, dead-code stripping is the process of removing unreferenced code from the executable file. If the code is unreferenced, it must not be used and therefore is not needed in the executable file. Removing dead code reduces the size of your executable and can help reduce paging.

    刪除靜態(tài)鏈接的可執(zhí)行文件中未引用的代碼

    Debug 設(shè)置為 NO, Release 設(shè)置為 YES 可減少可執(zhí)行文件大小。

    Xcode 默認會開啟此選項,C/C++/Swift 等靜態(tài)語言編譯器會在 link 的時候移除未使用的代碼,但是對于 Objective-C 等動態(tài)語言是無效的。因為 Objective-C 是建立在運行時上面的,底層暴露給編譯器的都是 Runtime 源碼編譯結(jié)果,所有的部分應(yīng)該都是會被判別為有效代碼。

    默認選項,不做修改。

    3.1.4 Apple Clang - Code Generation

    Optimization Level 編譯參數(shù)決定了程序在編譯過程中的兩個指標:編譯速度和內(nèi)存的占用,也決定了編譯之后可執(zhí)行結(jié)果的兩個指標:速度和文件大小。 Build Settings -> code Generation -> Optimization Level 默認情況下,Debug 設(shè)定為 None[-O0] ,Release 設(shè)定為 Fastest,Smallest[-Os]。

    • None[-O0]。 Debug 默認級別。不進行任何優(yōu)化,直接將源代碼編譯到執(zhí)行文件中,結(jié)果不進行任何重排,編譯時比較長。主要用于調(diào)試程序,可以進行設(shè)置斷點、改變變量 、計算表達式等調(diào)試工作。

    • Fast[-O,O1]。最常用的優(yōu)化級別,不考慮速度和文件大小權(quán)衡問題。與-O0級別相比,它生成的文件更小,可執(zhí)行的速度更快,編譯時間更少。

    • Faster[-O2]。在-O1級別基礎(chǔ)上再進行優(yōu)化,增加指令調(diào)度的優(yōu)化。與-O1級別相,它生成的文件大小沒有變大,編譯時間變長了,編譯期間占用的內(nèi)存更多了,但程序的運行速度有所提高。

    • Fastest[-O3]。在-O2和-O1級別上進行優(yōu)化,該級別可能會提高程序的運行速度,但是也會增加文件的大小。

    • Fastest Smallest[-Os]。Release 默認級別。這種級別用于在有限的內(nèi)存和磁盤空間下生成盡可能小的文件。由于使用了很好的緩存技術(shù),它在某些情況下也會有很快的運行速度。

    • Fastest, Aggressive Optimization[-Ofast]。 它是一種更為激進的編譯參數(shù), 它以點浮點數(shù)的精度為代價。

    默認選項,不做修改。

    3.1.5 Swift Compiler - Code Generation

    Xcode 9.3 版本之后 Swift 編譯器提供了新的 Optimization Level 選項來幫助減少 Swift 可執(zhí)行文件的大小:

    • No optimization[-Onone]:不進行優(yōu)化,能保證較快的編譯速度。
    • Optimize for Speed[-O]:編譯器將會對代碼的執(zhí)行效率進行優(yōu)化,一定程度上會增加包大小。
    • Optimize for Size[-Osize]:編譯器會盡可能減少包的大小并且最小限度影響代碼的執(zhí)行效率。

    We have seen that using -Osize reduces code size from 5% to even 30% for some projects. But what about performance? This completely depends on the project. For most applications the performance hit with -Osize will be negligible, i.e. below 5%. But for performance sensitive code -O might still be the better choice.

    官方提到,-Osize 根據(jù)項目不同,大致可以優(yōu)化掉 5% - 30% 的代碼空間占用。 相比 -0 來說,會損失大概 5% 的運行時性能。 如果你的項目對運行速度不是特別敏感,并且可以接受輕微的性能損失,那么 -Osize 是首選。

    除了 -O 和 -Osize, 還有另外一個概念也值得說一下。 就是 Single File 和 Whole Module 。 在之前的 XCode 版本,這兩個選項和 -O 是連在一起設(shè)置的,Xcode 9.3 中,將他們分離出來,可以獨立設(shè)置:

    Single File 和 Whole Module 這兩個模式分別對應(yīng)編譯器以什么方式處理優(yōu)化操作。

    • Single File:逐個文件進行優(yōu)化,它的好處是對于增量編譯的項目來說,它可以減少編譯時間,對沒有更改的源文件,不用每次都重新編譯。并且可以充分利用多核 CPU,并行優(yōu)化多個文件,提高編譯速度。但它的缺點就是對于一些需要跨文件的優(yōu)化操作,它沒辦法處理。如果某個文件被多次引用,那么對這些引用方文件進行優(yōu)化的時候,會反復(fù)的重新處理這個被引用的文件,如果你項目中類似的交叉引用比較多,就會影響性能。

    • Whole Module: 將項目所有的文件看做一個整體,不會產(chǎn)生 Single File 模式對同一個文件反復(fù)處理的問題,并且可以進行最大限度的優(yōu)化,包括跨文件的優(yōu)化操作。缺點是,不能充分利用多核處理器的性能,并且對于增量編譯,每次也都需要重新編譯整個項目。

    如果沒有特殊情況,使用默認的 Whole Module 優(yōu)化即可。 它會犧牲部分編譯性能,但的優(yōu)化結(jié)果是最好的。

    故,在 Relese 模式下 -Osize 和 Whole Module 同時開啟效果會最好!

    3.1.6 Strip Symbol Information

    1、Deployment Postprocessing 2、Strip Linked Product 3、Strip Debug Symbols During Copy 4、Symbols hidden by default

    設(shè)置為 YES 可以去掉不必要的符號信息,可以減少可執(zhí)行文件大小。但去除了符號信息之后我們就只能使用 dSYM 來進行符號化了,所以需要將 Debug Information Format 修改為 DWARF with dSYM file。

    Symbols Hidden by Default 會把所有符號都定義成”private extern”,詳細信息見官方文檔。

    故,Release 設(shè)置為 YES,Debug 設(shè)置為 NO。

    3.1.7 Exceptions

    在 iOS微信安裝包瘦身 一文中,有提到:

    去掉異常支持,Enable C++ Exceptions和Enable Objective-C Exceptions設(shè)為NO,并且Other C Flags添加-fno-exceptions,可執(zhí)行文件減少了27M,其中__gcc_except_tab段減少了17.3M,__text減少了9.7M,效果特別明顯。可以對某些文件單獨支持異常,編譯選項加上-fexceptions即可。但有個問題,假如ABC三個文件,AC文件支持了異常,B不支持,如果C拋了異常,在模擬器下A還是能捕獲異常不至于Crash,但真機下捕獲不了(有知道原因可以在下面留言:)。去掉異常后,Appstore 后續(xù)幾個版本 Crash 率沒有明顯上升。

    個人認為關(guān)鍵路徑支持異常處理就好,像啟動時NSCoder讀取setting配置文件得要支持捕獲異常,等等

    看這個優(yōu)化效果,感覺發(fā)現(xiàn)了新大陸。關(guān)閉后驗證.. 毫無感知,基本沒什么變化。

    可能和項目中用到比較少有關(guān)系。故保持開啟狀態(tài)。

    3.1.8 Link-Time Optimization

    Link-Time Optimization 是 LLVM 編譯器的一個特性,用于在 link 中間代碼時,對全局代碼進行優(yōu)化。這個優(yōu)化是自動完成的,因此不需要修改現(xiàn)有的代碼;這個優(yōu)化也是高效的,因為可以在全局視角下優(yōu)化代碼。

    蘋果在 WWDC 2016 中,明確提出了這個優(yōu)化的概念,What’s New in LLVM。并且說在蘋果內(nèi)部已經(jīng)廣泛地使用這個優(yōu)化方法進行編譯。

    它的優(yōu)化主要體現(xiàn)在如下幾個方面:

  • 多余代碼去除(Dead code elimination):如果一段代碼分布在多個文件中,但是從來沒有被使用,普通的 -O3 優(yōu)化方法不能發(fā)現(xiàn)跨中間代碼文件的多余代碼,因此是一個“局部優(yōu)化”。但是Link-Time Optimization 技術(shù)可以在 link 時發(fā)現(xiàn)跨中間代碼文件的多余代碼。

  • 跨過程優(yōu)化(Interprocedural analysis and optimization):這是一個相對廣泛的概念。舉個例子來說,如果一個 if 方法的某個分支永不可能執(zhí)行,那么在最后生成的二進制文件中就不應(yīng)該有這個分支的代碼。

  • 內(nèi)聯(lián)優(yōu)化(Inlining optimization):內(nèi)聯(lián)優(yōu)化形象來說,就是在匯編中不使用 “call func_name” 語句,直接將外部方法內(nèi)的語句“復(fù)制”到調(diào)用者的代碼段內(nèi)。這樣做的好處是不用進行調(diào)用函數(shù)前的壓棧、調(diào)用函數(shù)后的出棧操作,提高運行效率與棧空間利用率。

  • 在新的版本中,蘋果使用了新的優(yōu)化方式 Incremental,大大減少了鏈接的時間。建議開啟。

    總結(jié),開啟這個優(yōu)化后,一方面減少了匯編代碼的體積,一方面提高了代碼的運行效率。

    3.2 代碼瘦身

    代碼的優(yōu)化,即通過刪除無用類、無用方法、重復(fù)方法等,來達到可執(zhí)行文件大小的減小。 而如何篩選出符合條件的無用類、方法,則需要通過一些工具來完成(fui)

    掃描無用代碼的基本思路都是查找已經(jīng)使用的方法/類和所有的類/方法,然后從所有的類/方法當中剔除已經(jīng)使用的方法/類剩下的基本都是無用的類/方法,但是由于 Objective-C 是動態(tài)語言,可以使用字符串來調(diào)用類和方法,所以檢查結(jié)果一般都不是特別準確,需要二次確認。目前市面上的掃描的思路大致可以分為 3 種:

    • 基于 Clang 掃描
    • 基于可執(zhí)行文件掃描
    • 基于源碼掃描

    先談幾個概念。

    可執(zhí)行文件就是 Mach-O 文件,其大小是油代碼量決定的,通常情況下,對可執(zhí)行文件進行瘦身,就是找到并刪除無用代碼的過程。找到無用代碼的過程類比找到無用圖片的思路。

    • 找到類和方法的全集
    • 找到使用過的類和方法集合
    • 取2者差集得到無用代碼集合
    • 工程師確認后,刪除即可

    LinkMap 文件分為3部分:Object File、Section、Symbols。

    • Object File:包含了代碼工程的所有文件
    • Section:描述了代碼段在生成的 Mach-O 里的偏移位置和大小
    • Symbols:會列出每個方法、類、Block,以及它們的大小

    先說說如何快速找到方法和類的全集?

    我們可以通過 LinkMap 來獲得所有的代碼類和方法的信息。獲取 LinkMap 可以通過將 Build Setting 里面的 Write Link Map File 設(shè)置為 YES,然后指定 Path to Link Map File 的路徑就可以得到每次編譯后的 LinkMap 文件了。

    3.2.1 基于 clang 掃描

    基本思路是基于 clang AST。追溯到函數(shù)的調(diào)用層級,記錄所有定義的方法/類和所有調(diào)用的方法/類,再取差集。具體原理參考 如何使用 Clang Plugin 找到項目中的無用代碼,目前只有思路沒有現(xiàn)成的工具。

    3.2.2 基于可執(zhí)行文件掃描(LinkMap 結(jié)合 Mach-O 找無用代碼)

    上面我們得知可以通過 LinkMap 統(tǒng)計出所有的類和方法,還可以清晰地看到代碼所占包大小的具體分布,進而有針對性地進行代碼優(yōu)化。

    得到了代碼的全集信息后,我們還需要找到已經(jīng)使用過的方法和類,這樣才可以獲取差集,找到無用代碼。所以接下來就談?wù)勅绾瓮ㄟ^ Mach-O 取到使用過的類和方法。

    Objective-C 中的方法都會通過 objc_msgSend 來調(diào)用,而 objc_msgSend 在 Mach-O 文件里是通過 _objc_selrefs 這個 section 來獲取 selector 這個參數(shù)的。

    所以,_objc_selrefs 里的方法一定是被調(diào)用了的。_objc_classrefs 里是被調(diào)用過的類, objc_superrefs 是調(diào)用過 super 的類(繼承關(guān)系)。通過 _objc_classrefs 和 _objc_superrefs,我們就可以找出使用過的類和子類。

    那么,Mach-O 文件中的 _objc_selrefs、_objc_classrefs、_objc_superrefs 如何查看呢?

  • 使用 otool 等命令逆向可執(zhí)行文件中引用到的類/方法和所有定義的類/方法,然后計算差集。具體參考iOS微信安裝包瘦身,目前只有思路沒有現(xiàn)成的工具。
  • 使用 MachOView 查看。但是這個項目運行不起來,這個新的 Repo 可以運行起來。
  • 下面舉例說明:

    前置條件:先運行項目,在生成的 Products 目錄下的 BridgeLabiPhone.app 解壓,取出對應(yīng)的和工程同名的 BridgeLabiPhone。然后運行上面的 Github 項目。可以看到運行了一個 Mac App。點擊頂部的菜單欄里面的 File->Open。選擇電腦上的 BridgeLabiPhone.app 選擇里面的 BridgeLabiPhone。見下圖

    由于 Objective-C 是一門動態(tài)語言,所以檢測出的結(jié)果仍舊需要我們2次確認。

    3.2.3 基于源碼掃描

    一般都是對源碼文件進行字符串匹配。例如將 A *a、[A xxx]、NSStringFromClass("A")、objc_getClass("A") 等歸類為使用的類,@interface A : B 歸類為定義的類,然后計算差集。

    基于源碼掃描 有個已經(jīng)實現(xiàn)的工具 - fui,但是它的實現(xiàn)原理是查找所有 #import "A" 和所有的文件進行比對,所以結(jié)果相對于上面的思路來說可能更不準確。

    3.2.4 通過 AppCode 查找無用代碼

    AppCode 提供了 Inspect Code 來診斷代碼,其中含有查找無用代碼的功能。它可以幫助我們查找出 AppCode 中無用的類、無用的方法甚至是無用的 import ,但是無法掃描通過字符串拼接方式來創(chuàng)建的類和調(diào)用的方法,所以說還是上面所說的 基于源碼掃描 更加準確和安全。

    說明:AppCode檢測出了實際上需要的大部分場景的問題,但是由于 Objective-C 是一門動態(tài)性語言,所以 AppCode 檢測出無用的方法等都需要工程師自己再次確認后刪除。(在我們的工程中有一些和 H5 交互的橋接方法,因此 AppCode 視為 Unused Method,但是你刪除的話,那就自己哭去吧 ?)。實際經(jīng)驗告訴我,使用 AppCode 的時候如果工程比較大,則整個 code inspect 會非常耗時(給你打個預(yù)防針哦,筆芯)

    • 無用類:Unused class 是無用類,Unused import statement 是無用類引入聲明,Unused property 是無用的屬性;
    • 無用方法:Unused method 是無用的方法,Unused parameter 是無用參數(shù),Unused instance variable 是無用的實例變量,Unused local variable 是無用的局部變量,Unused value 是無用的值;
    • 無用宏:Unused macro 是無用的宏。
    • 無用全局:Unused global declaration 是無用全局聲明。

    3.2.5 運行時真正檢測類是否用過

    通過上述手段找到并刪除了無用代碼。App 不斷上線迭代蠻多代碼都不會被調(diào)用了(業(yè)務(wù)被砍掉了)。這種方式下這些無用的代碼也是可以被刪除的。

    通過 Objective-C 的 runtime 源碼,我們可以找到如何判斷一個類是否初始化過的函數(shù)。

    #define RW_INITIALIZED (1<<29) bool isInitialized() {return getMeta()->data()->flags & RW_INITIALIZED; } 復(fù)制代碼

    isInitialized 的結(jié)果會保存到元類的 class_rw_t 結(jié)構(gòu)體的 flags 信息里, flags 的 1<<29 位記錄的就是這個類是否初始化了的信息,而 flags 的其他位記錄的信息,可以查看 rumtime 的源碼

    // 類的方法列表已修復(fù) #define RW_METHODIZED (1<<30)// 類已經(jīng)初始化了 #define RW_INITIALIZED (1<<29)// 類在初始化過程中 #define RW_INITIALIZING (1<<28)// class_rw_t->ro 是 class_ro_t 的堆副本 #define RW_COPIED_RO (1<<27)// 類分配了內(nèi)存,但沒有注冊 #define RW_CONSTRUCTING (1<<26)// 類分配了內(nèi)存也注冊了 #define RW_CONSTRUCTED (1<<25)// GC:class 有不安全的 finalize 方法 #define RW_FINALIZE_ON_MAIN_THREAD (1<<24)// 類的 +load 被調(diào)用了 #define RW_LOADED (1<<23) 復(fù)制代碼

    既然可以在運行的期間知道類是否初始化了,那么就可以找出哪些類未初始化,即可以找到在真實環(huán)境里面沒有用到的類并刪除掉。

    4. App Extension

    App Extension 的占用,都放在 Plugin 文件夾內(nèi)。它是獨立打包簽名,然后再拷貝進 Target App Bundle 的。 關(guān)于 Extension,有兩個點要注意:

    靜態(tài)庫最終會打包進可執(zhí)行文件內(nèi)部,所以如果 App Extension 依賴了三方靜態(tài)庫,同時主工程也引用了相同的靜態(tài)庫的話,最終 App 包中可能會包含兩份三方靜態(tài)庫的體積。

    動態(tài)庫是在運行的時候才進行加載鏈接的,所以 Plugin 的動態(tài)庫是可以和主工程共享的,把動態(tài)庫的加載路徑 Runpath Search Paths 修改為跟主工程一致就可以共享主工程引入的動態(tài)庫。

    所以,如果可能的話,把相關(guān)的依賴改成動態(tài)庫方式,達到共享。

    5. 靜態(tài)庫瘦身

    項目中都會引入第三方靜態(tài)庫。通過 lipo 工具可以查看支持的指令集,比如查看微博 SDK 終端切換到微博 SDK 的目錄下執(zhí)行下面命令

    • 靜態(tài)庫指令集信息查看:lipo -info libname.a(或者libname.framework/libname)
    lipo -info libWeiboSDK.a //Architectures in the fat file: libWeiboSDK.a are: armv7 arm64 i386 x86_64 復(fù)制代碼

    我們知道 i386、x86_64 是模擬器的指令集。所以我們可以模擬器版本的指令集。因為 armv7 也可以兼容 armv7s。所以 armv7s 也可以刪除了。只保留 armv7 和 arm64

    • 靜態(tài)庫拆分:lipo 靜態(tài)庫文件路徑 -thin CPU架構(gòu) -output 拆分后的靜態(tài)庫文件路徑
    • 靜態(tài)庫合并:lipo -create 靜態(tài)庫1文件路徑 靜態(tài)庫2文件路徑... 靜態(tài)庫n文件路徑 -output 合并后的靜態(tài)庫文件徑
    lipo libWeiboSDK.a -thin armv7 -output libWeiboSDK-armv7.a lipo libWeiboSDK.a -thin arm64 -output libWeiboSDK-arm64.a lipo create libWeiboSDK-armv7.a libWeiboSDK-arm64.a -output libWeiboSDK.device.a 復(fù)制代碼

    通過上面的操作我們將靜態(tài)庫里面支持模擬器的指令集給去掉了,所以模擬器是無法跑代碼的,如何解決?

  • 平時使用包含模擬器指令集的靜態(tài)庫,在 App 發(fā)布的時候去掉
  • 如果使用 Cocoapods 管理可以使用2份 Podfile 文件。一份包含指令集一份不包含,發(fā)布的時候切換 Podfile 文件即可。或者一份 Podfile 文件,但是配置不同的環(huán)境設(shè)置
  • 補充2個說明:

  • dSYM 文件 符號表文件 .dSYM 文件是從 Mach-O 文件中抽取調(diào)試信息而得到的文件目錄,實際用于保存調(diào)試信息的是 DWARF 文件
    • 自動生成。Xcode 會在工程編譯或者歸檔的時候自動生成 .dSYM 文件,在 Buld setting 設(shè)置中有開關(guān)可以設(shè)置去關(guān)掉 .dSYM 文件
    • 手動生成。通過腳本從 Mach-O 文件中提取出來。
    $ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/wangzz/Library/Developer/Xcode/DerivedData/YourApp-cqvijavqbptjyhbwewgpdmzbmwzk/Build/Products/Debug-iphonesimulator/YourApp.app/YourApp -o YourApp.dSYM 復(fù)制代碼

    該方式通過 dsymutil 工具,從項目編譯結(jié)果 .app 目錄下的 Mach-O 文件中提取出調(diào)試符號表文件。Xcode 在歸檔的時候是通過它生辰的 .dSYM 文件

  • DWARF 文件 DebuggingWith Arbitrary Record Formats 是 ELF 和 Mach-O 等文件格式中用來存儲和處理調(diào)試信息的標準格式,.dSYM 文件中真正保存符號表數(shù)據(jù)的是 DWARF 文件。DWARF 文件中不同的數(shù)據(jù)都保存在相應(yīng)的 section 中。
  • 最后的一個對比效果圖:

    總結(jié):瘦身技術(shù)常見操作就這些,但是維持應(yīng)用包體積的瘦身卻是一個觀念,從日常開發(fā)到線上發(fā)布都需要有這個意識。這樣當你在寫代碼的時候就會考慮同樣一個效果,你的具體實現(xiàn)手段是怎么樣的。比如為了一個稍微炫酷的效果就要引入一個很大的三方庫,有了“瘦身”的意識,你很大可能就是自己動手擼一個代碼。比如一些無用資源的管理方式、有用的圖片資源的高效管理方式等等。有了意識,行動自然會往這個方面去靠。(?大道理一套一套的。我也不想的,畢竟是playboy)

    其中遇到了一個神奇的問題。lint 的時候看到一些未使用的依賴庫。見 問題

    By the way: 如果在應(yīng)用包瘦身方面有其他的做法,請告知,完善文章。

    參考文章:

    • Humble Assets Catalog
    • 關(guān)于 Pod 庫的資源引用 resource_bundles or resources
    • 部分圖片或者文字內(nèi)容引用來自網(wǎng)絡(luò)(若有引用到,請告訴我地址,及時補充)

    轉(zhuǎn)載于:https://juejin.im/post/5cdd27d4f265da036902bda5

    總結(jié)

    以上是生活随笔為你收集整理的iOS 瘦身之道的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    看片黄网站 | 99热精品免费观看 | 欧美最猛性xxx | 久久精品国产99国产 | 亚洲一区日韩在线 | 国产精品夜夜夜一区二区三区尤 | 国产亚洲精品久久久久久电影 | 国内成人精品视频 | 播五月婷婷 | 天天干天天干天天干天天干天天干天天干 | 超碰97在线资源站 | 免费av免费观看 | www.婷婷com| 香蕉国产91 | 久草视频资源 | 久久99影院 | 成人在线播放免费观看 | 久久久久久久久久久久av | 精品免费久久久久 | 久久久久久免费网 | 免费日韩一区二区三区 | 女人高潮一级片 | 天天操天天干天天爱 | av观看在线观看 | 免费精品国产va自在自线 | 久久99精品久久久久久 | av永久网址| 欧美十八 | 国产精品网红福利 | av中文国产| 97av超碰| 九九视频这里只有精品 | 亚洲黄网站 | 91在线视频免费播放 | 最新av在线网站 | 亚洲一区精品二人人爽久久 | 久艹视频在线观看 | 麻豆传媒在线免费看 | 日韩精品专区在线影院重磅 | 国产99久久久国产精品免费二区 | 蜜臀av夜夜澡人人爽人人桃色 | 亚洲国产精品成人精品 | 免费午夜在线视频 | 日韩在线视频网址 | 狠狠色狠狠色终合网 | 久久久久国产精品免费免费搜索 | 99亚洲精品| www.狠狠操 | 99久久婷婷国产综合亚洲 | 日韩在线一二三区 | 四虎4hu永久免费 | 91爱看片| 中文字幕乱在线伦视频中文字幕乱码在线 | 欧美福利精品 | 日韩欧美精品在线视频 | 黄网av在线 | 免费在线视频一区二区 | 三级在线视频观看 | 欧美最猛性xxxx | 日韩精品视频免费 | av黄免费看| 激情视频网页 | 国产在线观看免 | 日韩久久久久久久 | 毛片99| 一级片免费视频 | 欧美不卡在线 | 亚洲精品视频在线播放 | 久久久免费电影 | 国内成人综合 | 色资源二区在线视频 | 国产一区二区三区在线免费观看 | 成人在线视频免费看 | 日日天天狠狠 | 日韩精品免费在线观看 | 狠狠操天天射 | 国产一区二区视频在线播放 | 91大神dom调教在线观看 | 国产一线二线三线性视频 | 91理论片午午伦夜理片久久 | 欧美日高清视频 | 成年人免费av | 青青久草在线 | 成人在线免费视频观看 | 六月婷婷色 | 国产精品自拍av | 日韩在线观看免费 | 国产视频美女 | 波多野结衣精品 | 久精品一区| 亚洲精品乱码久久久久久蜜桃91 | 久久久久久久久久网 | 最新国产精品亚洲 | 日韩免费在线看 | 久久久 激情 | 欧美日韩中文另类 | 麻豆影视网 | 亚洲最新av网站 | 在线免费中文字幕 | 日韩电影在线观看一区二区三区 | 免费高清影视 | 97综合视频| 人人爽爽人人 | 日本最新中文字幕 | 天天插日日插 | 97av免费视频| 91成人蝌蚪 | 免费看搞黄视频网站 | 精品国产一区二区三区日日嗨 | 四虎国产精品成人免费影视 | 久久99精品波多结衣一区 | 久久综合中文色婷婷 | 一本—道久久a久久精品蜜桃 | 91成版人在线观看入口 | 免费热情视频 | 午夜免费久久看 | 日韩在线观看高清 | 色网站视频 | 免费观看av网站 | 精品国产一区在线观看 | 日韩精品一区不卡 | av免费观看在线 | 国产精品毛片一区视频播 | 日本成人中文字幕在线观看 | 国产一区二区三区高清播放 | 国产小视频免费观看 | 日本在线免费看 | 99精品久久99久久久久 | 综合av在线 | 在线色资源 | 一区二区三区日韩在线 | 在线免费91 | 97精品国产手机 | 天天综合色天天综合 | 国产亚洲精品久久久久久电影 | 国产成人av一区二区三区在线观看 | 久久婷婷影视 | 在线观看一区二区视频 | 日本中文字幕在线播放 | 国产精品99久久99久久久二8 | 黄色在线观看免费 | 97在线观看免费高清完整版在线观看 | 婷婷爱五月天 | 91精品国自产在线偷拍蜜桃 | 欧美日韩一区二区久久 | 久久久久久免费毛片精品 | 亚洲,国产成人av | 国产乱对白刺激视频不卡 | 国产精品久久久久久妇 | 国产精品黄色 | 五月婷婷中文网 | 在线免费观看黄色小说 | 天天躁日日躁狠狠躁av中文 | 色吊丝av中文字幕 | 友田真希x88av| 国产精品福利久久久 | 亚洲第一成网站 | 五月婷婷狠狠 | av久久久久久| 国产精品一区在线观看 | 日日夜夜网站 | 99久久一区 | 成人欧美一区二区三区黑人麻豆 | 精品视频一区在线 | 天天干天天操天天做 | 在线观看成人网 | 成人精品999 | 欧美久久久久久久久久久久 | 91视频免费播放 | 国产亚洲午夜高清国产拍精品 | 91久久国产综合精品女同国语 | 丁香色天天 | 日本91在线| 亚洲在线网址 | 天天天天爱天天躁 | 久久久久北条麻妃免费看 | 亚洲一级黄色av | 国产中文字幕av | 天天综合狠狠精品 | 色婷婷国产精品一区在线观看 | 干亚洲少妇 | 99精品视频观看 | 久久黄色片子 | 99久久精品电影 | 日韩精品免费在线观看视频 | 成人在线播放视频 | 91精品网站在线观看 | 久久国产精品一区二区三区 | 2023av在线| 在线观看国产成人av片 | 五月婷婷免费 | 中文字幕在线观看日本 | 天堂av最新网址 | 国产精品18久久久久久vr | 国产小视频91| 伊人婷婷 | 亚洲第一av在线 | 91九色在线 | 日韩欧美在线高清 | 97精品一区二区三区 | 91精品天码美女少妇 | 黄色网大全 | 超碰在线公开免费 | 97成人精品视频在线播放 | 午夜视频免费播放 | 国产精选在线 | 久久免费国产视频 | 日韩欧美高清一区二区 | 久久任你操 | 69久久久 | 国产一级电影网 | 精品在线视频一区 | 欧美成人a在线 | 日精品| www.com久久久 | 亚洲国产网站 | 国产无套精品久久久久久 | 久久99最新地址 | 美女国内精品自产拍在线播放 | 中文字幕人成人 | 国产精品免费久久久久影院仙踪林 | 国产对白av | 日韩高清不卡一区二区三区 | 久久久www成人免费毛片 | 黄色软件在线看 | 在线免费观看国产黄色 | 国产成人精品亚洲精品 | 黄色中文字幕在线 | 在线观看av的网站 | 精品欧美一区二区精品久久 | 一本一本久久a久久精品牛牛影视 | 天堂资源在线观看视频 | 99精品在这里 | 日韩成年视频 | 国产精品综合av一区二区国产馆 | 日韩精品一区二区不卡 | 99视频在线免费看 | 日本久久久久久久久久 | 中文字幕在线网址 | 久操中文字幕在线观看 | 久久精品一二三区白丝高潮 | 亚洲视频播放 | 日韩精品中文字幕在线播放 | 99免费| 特级毛片在线免费观看 | 国产 日韩 欧美 自拍 | 久久99国产综合精品免费 | 欧美大片在线观看一区 | 免费观看一区二区 | 最新国产精品亚洲 | 精品高清视频 | 精品国内| va视频在线| 天天艹天天 | www.五月婷婷 | 亚洲精品美女久久17c | 日本中文字幕观看 | av无限看 | 国产精品 中文字幕 亚洲 欧美 | 成人黄色大片在线免费观看 | 这里只有精品视频在线 | 亚洲精品美女久久 | 国产视频一区二区在线观看 | 久久精品免费 | 婷婷在线不卡 | 免费色视频在线 | 97韩国电影 | 91久久黄色 | 免费av观看网站 | 91精品久 | 免费三级a | 久久超碰免费 | 成年美女黄网站色大片免费看 | 福利精品在线 | 中文网丁香综合网 | 五月婷香蕉久色在线看 | 国产四虎在线 | 日韩精品在线免费播放 | 激情 一区二区 | 在线免费性生活片 | 国产在线a | 91av播放| www久草 | www.久热| 丁香激情综合久久伊人久久 | 亚洲精品系列 | 精品视频在线免费 | 中文字幕在线专区 | 少妇搡bbbb搡bbb搡忠贞 | 久草在线中文视频 | 国产精品成人在线 | 日韩字幕| 97在线观看免费高清完整版在线观看 | 日本中文字幕在线免费观看 | 在线观看国产一区二区 | 怡红院成人在线 | 久久免费视频这里只有精品 | 日日夜夜精品 | 99热精品国产一区二区在线观看 | 久久公开视频 | 欧美福利视频一区 | 午夜精品久久久久久久99水蜜桃 | 久久久九九 | 在线成人一区二区 | 欧美日韩精品免费观看 | 亚洲黄色免费观看 | 在线 国产 日韩 | 日韩精品电影在线播放 | 99r在线观看| 久久欧美在线电影 | 美女在线免费观看视频 | 成年人黄色免费视频 | 狠狠插天天干 | 亚洲精品国产精品国自产在线 | 婷婷综合导航 | 天天插狠狠插 | adn—256中文在线观看 | 免费三级大片 | 亚洲黄色成人av | 激情网婷婷 | 亚州免费视频 | 欧美天堂视频在线 | 中文字幕在线观看完整 | www.狠狠色 | 国产亚洲精品久久久久秋 | 久久伦理视频 | 国产精品一区二区吃奶在线观看 | av天天澡天天爽天天av | 中文字幕传媒 | 成人av在线播放网站 | 93久久精品日日躁夜夜躁欧美 | 国产福利一区二区三区在线观看 | 中文在线亚洲 | 欧美日韩不卡一区二区 | 91污视频在线 | 欧美a级在线免费观看 | 在线综合 亚洲 欧美在线视频 | 亚洲精品午夜久久久久久久 | 国产日韩三级 | 亚洲精品免费观看 | 亚洲激情网站免费观看 | 免费观看av网站 | 日韩一区在线免费观看 | 国产精品情侣视频 | 五月天婷婷丁香花 | 丁香婷婷基地 | 亚洲免费成人av电影 | 国产精品免费观看国产网曝瓜 | 在线观看视频国产一区 | 国产一级精品绿帽视频 | 成人一级黄色片 | 日韩电影在线一区 | 久草在线一免费新视频 | 亚洲天堂毛片 | 中文字幕一区二区三区久久 | 中文字幕在线看视频国产中文版 | 中文字幕亚洲综合久久五月天色无吗'' | 九色最新网址 | 激情综合网五月婷婷 | 免费看片网址 | 在线91播放 | 超碰国产97| 午夜精品福利一区二区三区蜜桃 | 五月婷婷六月丁香激情 | 黄污在线观看 | 成人h视频在线播放 | 日韩中文字幕在线不卡 | 久久国产精品二国产精品中国洋人 | 精品高清视频 | 超碰大片 | 人人搞人人干 | 99成人在线视频 | 天天操天天操天天操天天操天天操 | 精品一区二区免费 | 992tv人人网tv亚洲精品 | 亚洲一区二区精品视频 | 久久精品小视频 | 91精品视频网站 | 欧美最新大片在线看 | 成人久久精品视频 | 国产精品久久久久久久久久免费 | 91成人天堂久久成人 | 五月天狠狠操 | 色黄www小说 | 日本免费一二三区 | 亚洲免费视频观看 | 欧美日韩一区二区视频在线观看 | 国产成人久久av免费高清密臂 | 欧美日韩精品在线观看视频 | 亚洲一区二区观看 | 黄污在线看| 视频在线一区 | 久草免费在线视频观看 | 亚洲视频www| 香蕉久久国产 | 最新av免费 | 一区二区免费不卡在线 | av在线观| 黄色av三级在线 | 日韩精品久久久久久久电影竹菊 | 日日夜色 | 久久国产精品免费一区 | 精品在线观看一区二区三区 | 91传媒免费观看 | 国产高清区 | 久久精品一区二区 | 国产视频69 | 日韩欧美在线综合网 | 在线视频 你懂得 | 米奇四色影视 | 日韩欧美一区二区三区黑寡妇 | 亚洲丝袜一区二区 | 色综合久久久久综合99 | 国产一区欧美在线 | 亚洲国产精品成人精品 | 久久国产欧美日韩 | 久久国产电影院 | 国产精品国产三级国产专区53 | 99久久婷婷国产一区二区三区 | 激情视频免费在线 | 永久免费毛片在线观看 | 激情综合六月 | 久久综合9988久久爱 | 国产精品久久久久久久久久久久冷 | 午夜精品在线看 | 中文字幕人成人 | 国产成人在线综合 | 狠狠做深爱婷婷综合一区 | 成 人 黄 色 免费播放 | 亚洲v欧美v国产v在线观看 | 久久99国产精品自在自在app | 日韩免费一二三区 | 五月婷婷黄色 | 91久久奴性调教 | 99这里只有 | 国产色区 | 日韩天天综合 | 久久免费看a级毛毛片 | 国产一二区精品 | 中文字幕在线观看网 | 国产精品毛片一区二区 | 久久久久成人精品免费播放动漫 | 国产亚洲视频中文字幕视频 | 久久激情五月婷婷 | 六月丁香婷| 国产精品久久免费看 | 国产区免费 | 久久一及片 | 亚洲成人黄 | 91精品国产一区二区在线观看 | 超碰成人av | 六月丁香社区 | 国产免费作爱视频 | 日韩精品第1页 | 69精品在线观看 | 美女福利视频在线 | 亚洲国产中文字幕在线 | 久热久草在线 | 免费a视频在线观看 | av免费网页 | 亚洲精品国产区 | 亚洲视频一 | 亚洲黄色片 | 久久人人爽人人爽人人片av软件 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 日韩av中文字幕在线免费观看 | 日本资源中文字幕在线 | 久久免费精品一区二区三区 | 久久精品女人毛片国产 | 国产日韩欧美在线观看视频 | 亚洲成人av免费 | 免费在线视频一区二区 | 夜夜操天天干 | 狠狠色伊人亚洲综合成人 | 蜜臀久久99静品久久久久久 | 少妇做爰k8经典 | 国产区精品在线观看 | 正在播放一区 | 国产精品婷婷午夜在线观看 | 日韩在线短视频 | 日韩高清国产精品 | 日韩精品视频第一页 | 91精品国自产在线观看 | 中文字幕免费一区 | 亚洲在线日韩 | 日韩专区一区二区 | 日韩资源在线观看 | 成人午夜精品福利免费 | 免费国产亚洲视频 | 97超碰国产在线 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 日韩三级不卡 | 国产精品美女久久久 | 日韩欧美视频在线播放 | 天天干人人插 | 2019中文最近的2019中文在线 | 久久久免费播放 | 日韩特级毛片 | 五月天六月婷婷 | 手机av在线网站 | 免费观看的av | 亚洲综合视频在线播放 | 91视频免费网址 | 亚洲妇女av | 欧美性春潮 | 麻豆视频91 | 欧美亚洲成人xxx | 亚洲专区视频在线观看 | 久久综合狠狠 | 婷婷色在线观看 | 久久久精品在线观看 | 久久国产福利 | 国产女人免费看a级丨片 | 国产精品欧美久久久久三级 | 亚洲免费资源 | 麻豆va一区二区三区久久浪 | 黄色一级在线免费观看 | 黄色一级免费 | 欧美亚洲另类在线视频 | 天天操操操操操 | 2024国产精品视频 | 亚洲国产成人在线 | 激情五月婷婷激情 | 久久精品一二区 | 国产亚洲精品久久久久久久久久久久 | 久草在线视频免费资源观看 | 久久久国产网站 | 在线观看中文字幕第一页 | 在线免费观看黄色小说 | 69精品人人人人 | 国产成人精品一区二区三区免费 | 久久久久免费网站 | 日韩在线观看你懂得 | 美女久久久久 | 91麻豆精品国产91久久久更新时间 | 久久99国产精品二区护士 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 久久av影视 | av网站在线观看播放 | 99精品视频在线观看视频 | 国产中文字幕视频在线观看 | 国产在线一卡 | 日本久久综合网 | 国产香蕉视频在线播放 | 久久久午夜精品福利内容 | 国产美女视频免费观看的网站 | 国产精品免费久久久久久久久久中文 | 一区二区三区国产精品 | 色婷婷激婷婷情综天天 | 日日夜夜天天 | 激情五月色播五月 | 国产又粗又硬又爽视频 | 国产精品视频在线观看 | 成年人视频在线观看免费 | 成年人毛片在线观看 | 国产成人在线观看免费 | www黄在线 | 最新精品国产 | 精品久久久久国产免费第一页 | 亚洲国内精品视频 | 成人免费视频网站在线观看 | 日韩精品一区二区三区在线视频 | 久久午夜精品 | 在线亚洲小视频 | 黄色软件在线观看视频 | 深爱激情亚洲 | 中文字幕在线免费看线人 | 狠狠色丁香婷婷综合久久片 | 亚洲精品视频免费观看 | 欧美不卡视频在线 | 久久久首页 | 日韩理论影院 | 伊人射 | 国产精品一区二区av麻豆 | 天天艹天天爽 | 欧美日韩不卡一区 | 99re6热在线精品视频 | 国产精品淫片 | av软件在线观看 | 日本高清xxxx| www夜夜操com| www.日日操.com | 天操夜夜操 | 五月天婷婷丁香花 | 中文字幕麻豆 | 操操碰 | 日韩欧美99| 狠狠搞,com | 欧美精品xx | 干干日日| 亚洲精品国产欧美在线观看 | 91av在线免费视频 | 久久高清av | av+在线播放在线播放 | 在线观看av网站 | 丁香综合网 | 欧美精品国产综合久久 | 欧美日韩高清 | 天天操欧美 | 中文视频在线 | 亚洲精品乱码久久久久久高潮 | 91精品视频一区二区三区 | 在线视频18在线视频4k | 狠狠躁日日躁夜夜躁av | 黄色小说视频网站 | 欧美日韩国产精品一区二区三区 | 国产精品亚 | 麻豆传媒在线免费看 | 一区二区激情视频 | 亚洲一级久久 | 亚洲国产精品久久久久婷婷884 | 日韩午夜在线观看 | 日韩午夜精品 | 91色网址| 亚洲精品在线视频 | 国产午夜精品免费一区二区三区视频 | 久久久久久久久久久免费视频 | 香蕉在线视频播放网站 | 日本夜夜草视频网站 | .国产精品成人自产拍在线观看6 | 精品国内自产拍在线观看视频 | 五月婷婷黄色 | 久草视频观看 | 婷婷天天色 | 国产免费中文字幕 | 色com| 色综合久 | 在线观看成人毛片 | 久久精品国产亚洲精品 | 免费观看91 | 国内精品久久久久久久久久久 | 精品国产一区二区三区四区在线观看 | 黄色网址av | 日韩一区在线免费观看 | 粉嫩一区二区三区粉嫩91 | 日韩在线免费看 | 欧美在线视频一区二区三区 | 五月婷婷视频在线 | 97偷拍在线视频 | 一区二区理论片 | 日韩在线观看视频在线 | 中文字幕日韩在线播放 | 婷婷五情天综123 | 色黄久久久久久 | 毛片在线播放网址 | 成年人免费看片网站 | 91大神精品视频 | 天天综合婷婷 | 精品久久美女 | 91精品国产三级a在线观看 | 人人爽人人香蕉 | 在线免费成人 | 免费毛片一区二区三区久久久 | 久久久久久久久久免费视频 | 五月天亚洲综合 | 精品亚洲一区二区 | 久久观看| 国产又粗又猛又黄又爽视频 | 国产剧情久久 | 国产一区私人高清影院 | 91亚洲成人| 欧美有色 | 深夜免费小视频 | www久草| 五月婷婷色综合 | 亚洲天堂社区 | 免费久久99精品国产婷婷六月 | 精品特级毛片 | 国产一级电影免费观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 国产超碰在线 | 在线观看的a站 | 久久午夜网 | 欧美精品久久99 | 在线观看国产亚洲 | 91精品对白一区国产伦 | 十八岁以下禁止观看的1000个网站 | 久久在线 | 特级西西444www大精品视频免费看 | 天天爱天天舔 | 国产va精品免费观看 | 97免费| 91精品麻豆 | 久久这里只有精品1 | 天天射天天爱天天干 | aⅴ视频在线 | 国产成人精品国内自产拍免费看 | 蜜臀久久99精品久久久无需会员 | 亚洲国产理论片 | 国产专区免费 | 日韩av免费一区二区 | 99色在线观看视频 | 日韩欧美国产成人 | 狠狠狠色丁香婷婷综合激情 | 中日韩欧美精彩视频 | 91在线视频免费播放 | 黄色软件视频大全免费下载 | 日韩精品久久久久 | 在线精品视频免费播放 | www.久久婷婷 | 狠狠干夜夜操 | av免费网页 | 黄色午夜| 久热超碰 | 国产亚洲精品久久久久久久久久久久 | 国产精品久久99综合免费观看尤物 | 日韩欧美综合视频 | 99在线国产| 成人一级黄色片 | 天天插夜夜操 | 在线 欧美 日韩 | 黄色一级免费电影 | 中文字幕免费在线看 | 亚洲欧美日韩在线看 | 在线观看亚洲免费视频 | 黄色网www| japanesefreesexvideo高潮| 视频1区2区 | 免费看片网站91 | 成人av高清在线 | 五月婷婷丁香在线观看 | 欧美日韩免费看 | 99一级片 | 五月婷婷综合在线视频 | 日日夜夜精品免费观看 | 午夜美女wwww | 欧美色图30p | 999视频精品 | 国产无套一区二区三区久久 | 久久婷婷久久 | 在线观看视频日韩 | 成人资源在线播放 | 成人羞羞视频在线观看免费 | 日韩在线观看不卡 | 亚洲激情视频 | 美女在线观看网站 | www.亚洲精品在线 | 97超碰人人在线 | 激情网色| 国产精品嫩草55av | 久久99国产综合精品免费 | 99r在线精品 | 亚洲美女精品区人人人人 | 麻豆影视网 | 国产 日韩 欧美 自拍 | 9797在线看片亚洲精品 | 久久国产露脸精品国产 | 香蕉视频网址 | 亚洲精品大全 | 精品国产一区二区三区蜜臀 | 成人aⅴ视频 | 亚洲影视资源 | 91在线精品秘密一区二区 | 欧美视频在线观看免费网址 | 久久综合久久久久88 | 欧美一区二区三区在线播放 | 亚洲一区美女视频在线观看免费 | 免费成人黄色 | 精品欧美一区二区精品久久 | 久久天天躁狠狠躁亚洲综合公司 | 日韩网站在线看片你懂的 | av中文资源在线 | 亚洲成人xxx | 亚洲国产精品推荐 | 久久久久综合精品福利啪啪 | 成人免费观看大片 | 97超碰中文 | 日韩国产精品久久 | 国产免费午夜 | 日韩欧美网站 | 干狠狠| 国产不卡在线 | 亚洲欧美视频在线播放 | 在线观看成年人 | 色综合天天综合网国产成人网 | 成人亚洲精品国产www | 欧美日韩在线视频一区二区 | 久久久精品欧美一区二区免费 | 日韩精品高清不卡 | 五月婷婷伊人网 | 久久再线视频 | 天天操综合网站 | 亚洲精品午夜视频 | а天堂中文最新一区二区三区 | 久久永久免费视频 | 国产精品毛片 | 不卡av免费在线观看 | 国产手机av | 日韩精品五月天 | 天天伊人狠狠 | 国产在线观看一区 | 亚洲国产一区二区精品专区 | 久久成人国产精品一区二区 | 天天操天天干天天爱 | 亚洲激情视频在线观看 | 一区二区在线影院 | 成年人免费在线看 | 人人玩人人添人人澡97 | 伊人网综合在线观看 | 天天干天天碰 | 四虎国产精品免费 | 天天天天干 | 欧美性黑人 | 国产黄色av| 在线观看你懂的网址 | 免费高清影视 | 人人干天天干 | 国产96在线 | 国产日韩亚洲 | 香蕉91视频 | .国产精品成人自产拍在线观看6 | 国产精品第一 | 91麻豆精品久久久久久 | 亚洲欧美国产精品 | 色天天久久 | 国产精品久久久久久婷婷天堂 | av网址在线播放 | 色视频国产直接看 | 韩国三级一区 | 六月丁香综合 | 91精品福利在线 | 激情网色 | 人人爽人人爽av | 国产做a爱一级久久 | 中文字幕在线观看网址 | 日本性久久 | 免费在线色电影 | 天堂av在线免费 | 在线观看精品视频 | 久久在线一区 | 国产精品18久久久久久首页狼 | 91大神精品视频在线观看 | 黄色一级动作片 | 国产亚洲片 | 亚洲区色 | 九九九热 | a天堂免费 | 国产999| 91av中文字幕 | 久久精品aaa | 五月天网站在线 | 欧美狠狠色 | 精品久久91 | 91欧美视频网站 | 在线观看中文字幕第一页 | 激情丁香综合五月 | 一区二区三区中文字幕在线观看 | 精品国产久 | 国产原创在线 | 国产精品 国产精品 | 九九热国产视频 | 日韩理论电影在线 | 国产精品青草综合久久久久99 | 九九精品在线观看 | 日韩精品一区二区三区丰满 | av中文在线观看 | 成人永久在线 | 国产91全国探花系列在线播放 | 成人免费视频a | 激情婷婷久久 | 日韩中文字幕在线不卡 | 综合色中色 | 91精品在线观看入口 | 国产亚洲婷婷免费 | 天天操天天色天天射 | 在线观看视频在线观看 | 国产视频1 | 日韩精品一区二区三区高清免费 | 午夜丁香网 | 国产69久久精品成人看 | 国产成人精品一区二区在线 | 五月婷婷电影网 | 国产精品区二区三区日本 | 中文字幕一区二区三区乱码不卡 | av不卡免费看 | 亚洲国产精品人久久电影 | av超碰在线 | 国产精品嫩草影院123 | 国产香蕉97碰碰久久人人 | 精品视频国产一区 | 黄色软件视频网站 | 97免费视频在线 | 成人av网站在线 | 中文字幕综合在线 | 久久人人爽人人人人片 | 夜色资源站wwwcom | 国产精品日韩久久久久 | 欧美久久成人 | 97色婷婷人人爽人人 | www国产亚洲精品久久网站 | 欧美肥妇free | 999视频网站 | 婷婷av电影 | 日韩电影在线观看中文字幕 | 天天干夜夜夜 | 97超碰人人澡 | 久久99久久99精品免费看小说 | 国产麻豆视频免费观看 | 久久a免费视频 | 成人小视频在线 | 欧美一区二区三区不卡 | 麻豆果冻剧传媒在线播放 | 欧美精品久久久 | 免费av试看 | 激情婷婷 | 国产一区二区视频在线 | 国产美女视频免费观看的网站 | 日韩中文字 | 激情婷婷六月 | 狠狠插狠狠干 | av在线一二三区 | 亚洲六月丁香色婷婷综合久久 | 色综合天天在线 | 国产精品自产拍在线观看蜜 | 成av在线| 五月天婷亚洲天综合网精品偷 | 国产视频 久久久 | 欧美日韩一区二区在线 | 中文字幕日韩有码 | 91av成人| 成人黄色国产 | 精品视频久久久 | 9幺看片| 成人免费视频播放 | 亚洲人人爱 | 国产青春久久久国产毛片 | 免费日韩 精品中文字幕视频在线 | 日本成人中文字幕在线观看 | .国产精品成人自产拍在线观看6 | 久久国产品| 日日躁夜夜躁aaaaxxxx | 蜜臀av性久久久久av蜜臀妖精 | 日韩精品一区二区三区中文字幕 | 成人免费中文字幕 | 最近日韩中文字幕中文 | 久久久av电影 | 日韩二区在线观看 | 免费热情视频 | 99精品热 | 国产精品久久久久久影院 | 国产精品婷婷午夜在线观看 | 久草免费福利在线观看 | 偷拍久久久 | 国产视频久 | 欧美成人高清 | 国产免费av一区二区三区 | 亚洲精品久久久久中文字幕m男 | ww亚洲ww亚在线观看 | 久久成人亚洲欧美电影 | 国产成人精品在线播放 | 国产中文字幕国产 | 狠狠操欧美| 99精品欧美一区二区 | 一区二区三区四区在线 | 久久久久国产a免费观看rela | 亚洲天堂香蕉 | 色先锋av资源中文字幕 | 九月婷婷色 | 超碰97网站 | 天堂av免费观看 | 国产一级一片免费播放放 | 天天做天天爱天天爽综合网 | 2024国产精品视频 | 日韩欧美有码在线 | 在线播放91 | 人人精品| 国产精品麻 | 久久久激情网 | 久久天天躁夜夜躁狠狠躁2022 | 黄p网站在线观看 | 天天做天天射 | 午夜久久美女 | 美女av电影 | 看毛片网站 | 亚洲国产精品99久久久久久久久 | 777久久久 | 久草网视频 | 国产精品 视频 | 成人sm另类专区 | 亚洲狠狠| 国产精品久久久久久久久蜜臀 | 操操操操网 | 午夜久久视频 | 韩国av不卡 | 91人人澡人人爽 | 久久综合给合久久狠狠色 | 亚洲欧美视频在线播放 | 国产成人亚洲在线电影 | 91在线精品视频 | 99热在线看 | 久久久久亚洲精品 | 久久久久久久久久久久久久av | av看片在线| a爱爱视频| 91成人在线视频观看 | 一区二区视频电影在线观看 | 国产亚洲精品久久久久久久久久久久 | 久久精品aaa |