優(yōu)化

系統(tǒng)作的內存方面優(yōu)化

NSString

NSString的類型分為三種:

  • __NSCFConstantString:字符串常量啦逆,存儲在字符串常量區(qū)翎承。引用計數(shù)很大蛉鹿。
  • __NSCFString:運行時類型取劫,存儲在堆上巷帝。引用計數(shù)+1.
  • NSTaggedPointerString:小對象忌卤,存儲在常量區(qū),既包含指針楞泼,也包含值驰徊。小對象指針不再是簡單的地址笤闯,而是地址 + 值.優(yōu)點是占用空間小 節(jié)省內存.

taggedPoint小地址是值和指針地址放在了一起,存儲在常量區(qū)棍厂,不進行retain颗味,release管理,能夠直接釋放回收牺弹,效率更高浦马,創(chuàng)建更快,將近100倍张漂。iOS14之后還對taggedPointer進行了混淆晶默。最高位是taggedPointer的類型。

NSString * te = @“12345678912111”;這種方式不論多長鹃锈,都是__NSCFConstantString類型荤胁,存儲在常量區(qū)。

通過stringWithFormatalloc并且長度小于一定值時才為taggedPoint屎债。

Nonpointer_isa

SideTables即散列表仅政,散列表中主要有引用計數(shù)表弱引用表
Nonpointer_isa為非指針類型的isa盆驹,可以存儲更多類的信息圆丹,包括引用計數(shù)。當引用計數(shù)存儲到一定值時躯喇,并不會再存儲到Nonpointer_isa的位域的extra_rc中辫封,而是會存儲到引用計數(shù)表中。

id objc_retain(id obj)
{
    if (obj->isTaggedPointerOrNil()) return obj;
    return obj->retain();
}

ALWAYS_INLINE id
objc_object::rootRetain(bool tryRetain, objc_object::RRVariant variant) 

通過對retain源碼的分析可以得知:

當引用計數(shù)存儲到一定值時廉丽,并不會再存儲到Nonpointer_isa的位域的extra_rc中倦微,而是除以二(RC_HALF)的部分存儲到SideTables 散列表中。

SideTables是一個真機長度8個元素正压,其他64個長度的hash數(shù)組欣福,本質是一個哈希表,集合了數(shù)組和鏈表的長處焦履,增刪改查都比較方便拓劝,里面存儲了SideTable。SideTables的hash鍵值就是一個對象obj的address嘉裤。為什么sidetables最多有8張呢郑临,而不是一張呢? 因為所有對象的引用技術全放在一張散列表中不安全,假如只訪問一個而可以拿到全部的屑宠,并且每次訪問都要加鎖解鎖厢洞,對于性能和安全性都不高,所以分了8張表。

retain做了什么:簡單回答是計數(shù)值加1犀变,更加底層應該這么回答

  1. 首先判斷是不是taggedpointer妹孙,如果是,就立馬返回获枝。因為taggedpointer不需要內存管理蠢正,taggedPointer存儲在常量區(qū)。
  2. 判斷如果 不是nonpointerisa省店,直接操作散列表sidetable的引用計數(shù)嚣崭,每次操作散列表會開鎖等耗時耗性能,所以表會有多張懦傍,為的是更安全雹舀。
  3. 如果 是nonpointerisa,表示isa聯(lián)合體開啟了指針優(yōu)化粗俱,isa可以存儲更多信息说榆,那么就操作isa.bits中的extra_rc的引用計數(shù)+1。
  4. 如果extra_rc滿了寸认,就和散列表對半開签财,各存一半,以提高性能偏塞。//這么操作的目的在于提高性能唱蒸,因為如果都存在散列表中,當需要release-1時灸叼,需要去訪問散列表神汹,每次都需要開解鎖,比較消耗性能古今。extra_rc存儲一半的話屁魏,可以直接操作extra_rc即可,不需要操作散列表,性能會提高很多捉腥。
  5. alloc創(chuàng)建的nopointerisa對象引用計數(shù)為0蚁堤,包括sideTable, uintptr_t rc = 1 + bits.extra_rc;所以對于alloc來說,是 0+1=1但狭,這也是為什么通過retaincount獲取的引用計數(shù)為1的原因。alloc創(chuàng)建的對象實際的引用計數(shù)為0撬即,其引用計數(shù)打印結果為1立磁,是因為在底層rootRetainCount方法中,引用計數(shù)默認+1了剥槐,但是這里只有對引用計數(shù)的讀取操作唱歧,是沒有寫入操作的,簡單來說就是:為了防止alloc創(chuàng)建的對象被釋放(引用計數(shù)為0會被釋放),所以在編譯階段颅崩,程序底層默認進行了+1操作几于。實際上在extra_rc中的引用計數(shù)仍然為0。
  6. 在dealloc流程匯總會判斷是否有isa沿后、cxx沿彭、關聯(lián)對象、弱引用表尖滚、引用計數(shù)表喉刘。

引用計數(shù)分別保存在isa.extra_rcsidetable中,當isa.extra_rc溢出時漆弄,將一半計數(shù)轉移至sidetable中睦裳,而當其下溢時,又會將計數(shù)轉回撼唾。當二者都為空時廉邑,會執(zhí)行釋放流程 。


項目可以進行的優(yōu)化

界面優(yōu)化:

  • cell數(shù)據(jù)預加載倒谷,數(shù)據(jù)請求下來后提前計算高度存儲在model中蛛蒙,tableview代理中直接賦值高度。如果cell布局用的是autolayout恨锚,可以開啟tableView的預估高度機制Self-Sizing 宇驾。
  • 按需加載:scrollviewwillEndDragging里判斷加載的是否是前后三行。
  • 圖片渲染:圖片最終能展示的都是bitmap位圖猴伶。不管是 JPEG 還是 PNG 圖片炬称,都是一種壓縮的位圖圖形格式。只不過 PNG 圖片是無損壓縮掰邢,并且支持 alpha 通道界弧,而 JPEG 圖片則是有損壓縮,可以指定 0-100% 的壓縮比办桨。解壓縮后的圖片大小 = 圖片的像素寬 * 圖片的像素高 * 每個像素所占的字節(jié)數(shù) 4筹淫。將壓縮的圖片數(shù)據(jù)解碼成未壓縮的位圖形式,這是一個非常耗時的 CPU 操作呢撞,并且它默認是在主線程中執(zhí)行的损姜。imageView.image = image這一步會做解碼,并且是主線程上殊霞。在將磁盤中的圖片渲染到屏幕之前摧阅,必須先要得到圖片的原始像素數(shù)據(jù),才能執(zhí)行后續(xù)的繪制操作绷蹲,這就是為什么需要對圖片解壓縮的原因棒卷。所以可以用SDWebImage預解碼顾孽,異步在子線程強制解壓縮。強制解壓縮的原理就是對圖片進行重新繪制比规,得到一張新的解壓縮后的位圖若厚。其中,用到的最核心的函數(shù)是 CGBitmapContextCreate蜒什。當頭像要切圓角時测秸,下載下來后,會在后臺線程將頭像預先渲染為圓形并單獨保存到一個 ImageCache 中去吃谣。
  • 復雜界面的渲染可以合成一張圖后然后再進行渲染乞封,具體可以參考美團的Graver框架。
  • main函數(shù)前后階段優(yōu)化

冷啟動:系統(tǒng)里沒有任何進程的緩存信息岗憋,典型的是重啟手機后直接啟動 App
熱啟動:如果把 App 進程殺了肃晚,然后立刻重新啟動,這次啟動就是熱啟動仔戈,因為進程緩存還在关串。

main函數(shù)之前的階段pre-main階段的啟動時間其實就是dyld加載過程的時間。針對main函數(shù)之前的啟動時間监徘,蘋果提供了內建的測量方法晋修,在Edit Scheme -> Run -> Arguments ->Environment Variables添加環(huán)境變量 DYLD_PRINT_STATISTICS 設為 1),然后運行就能看到打印耗時的日志了凰盔。

Total pre-main time: 2.7 seconds (100.0%)
         dylib loading time: 450.07 milliseconds (15.6%)   主要是`加載`動態(tài)庫
        rebase/binding time: 210.8 milliseconds (8.5%)  (偏移修正/符號綁定耗時) ALSR rebase /binding符號 (偏移地址+ALSR = 運行時執(zhí)行地址)   外部`綁定`的動態(tài)庫越多越耗時
            ObjC setup time:  921.22 milliseconds (33.5%)   (OC類注冊的耗時):OC類越多墓卦,越耗時。Swift耗時就會少很多户敬。
           initializer time:  1113.94 milliseconds (45.3%)    執(zhí)行l(wèi)oad和構造函數(shù)的耗時

pre-main階段優(yōu)化建議
蘋果官方建議自定義的動態(tài)庫最好不要超過6個落剪。
二進制重排:主要是大項目 二進制重排優(yōu)化都適用,主要目的是將啟動時刻需要調用的方法排列在一起。啟動時刻會出現(xiàn)大量的缺頁異常PageFault尿庐,當進程訪問一個虛擬內存Page而對應的物理內存卻不存在時忠怖,會觸發(fā)一次缺頁中斷(Page Fault),分配物理內存抄瑟,有需要的話會從磁盤mmap讀人數(shù)據(jù)凡泣。發(fā)生Page Fault的時候線程是被blocked。一般項目會有0.5-1s的page fault皮假。導致Page Fault次數(shù)過多的根本原因是啟動時刻需要調用的方法鞋拟,處于不同的Page導致的。因此惹资,我們的優(yōu)化思路就是:將所有啟動時刻需要調用的方法严卖,排列在一起,即放在一個頁中布轿,這樣就從多個Page Fault變成了一個Page Fault。這就是二進制重排的核心原理。

PageFault.png

利用xcode自帶工具Instrument中的SystemTrace就能看到項目的PageFault次數(shù)汰扭,即圖中的File Backed Page In稠肘。

  • 工程Build Setting打開link map,記錄了二進制文件的布局萝毛,可以看到方法的執(zhí)行順序项阴,路徑在.app上一級同級的文件再依次往下找。

  • 打開xcode的Instrument中的system trace笆包,用來展示啟動pageFault次數(shù)环揽。

  • 工程路徑中創(chuàng)建一個.order文件,在這個order文件里排列你想加載的順序庵佣,然后在build setting里搜order file歉胶,把.order路徑加進去就可以了。

那么那么多方法巴粪,哪個方法才算是啟動期間調用的呢通今。在方法的啟動耗時中,需要去 Hook objc_msgSend 來達到監(jiān)控所有 ObjC 方法的目的肛根。
hook objc_msgsend:

  1. 絕大部分Objective C的方法在編譯后會走objc_msgSend辫塌,所以通過[fishhook](https://github.com/facebook/fishhook) hook這一個C函數(shù)即可獲得Objective C符號。由于objc_msgSend是變長參數(shù)派哲,所以hook代碼需要用匯編來實現(xiàn),對開發(fā)人員要求較高臼氨。而且也只能拿到OC 和 swift中@objc 后的方法.
  2. 所以用clang插樁來拿到所有方法,做到100%覆蓋符號芭届。進入clang官網(wǎng)储矩,會有示例代碼.主要是trace_pc_guard追蹤各種方法、函數(shù)喉脖、block等的調用椰苟。需要在Build Settings中的Other C Flags,輸入-fsanitize-coverage=trace-pc-guard树叽,則Clang就在讀代碼時候生成中間代碼IR時插入一行調用自己函數(shù)方法的代碼舆蝴,在xcode中實現(xiàn)對應的函數(shù)方法就可以拿到了。這屬于匯編插樁题诵。
  3. dlfcn.h里的方法dladdr可以根據(jù)上面clang的函數(shù)方法返回的函數(shù)地址來獲取到對應的方法名sname

細節(jié)可以參考抖音 洁仗、 字節(jié)

main階段之后的優(yōu)化建議

  • 多線程加載業(yè)務邏輯,充分利用多線程性锭。能放后臺初始化的放后臺赠潦,盡量不要占用主線程的啟動時間。減少啟動初始化的流程草冈,能懶加載的懶加載她奥,能延遲的延遲瓮增。
  • 不用的代碼和類去除(2w個類大約800毫秒)
  • 盡量主頁面不要用xib等。
  • swift盡量使用struct結構體哩俭,因為結構體是值類型绷跑,保存在棧中,效率比堆上更高凡资。椩夷螅空間地址分配的過程中是從高到低的(先分配0x0010再分配0x0001)

瘦身

官方 App Thinning
  • App Thinning 會專門針對不同的設備來選擇只適用于當前設備的內容以供下載。大部分工作都是由 Xcode 和 App Store 來幫你完成的隙赁,你只需要通過 Xcode 添加 xcassets 目錄垦藏,然后將圖片添加進來即可。
  • Xcode 默認會開啟DEAD_CODE_STRIP選項伞访,C/C++/Swift 等靜態(tài)語言編譯器會在 link 的時候移除未使用的代碼掂骏,但是對于 Objective-C 等動態(tài)語言是無效的,因為動態(tài)語言是建立在運行時上面的。
  • 編譯期優(yōu)化參數(shù):GCC_OPTIMIZATION_LEVEL定義了 clang 用什么優(yōu)化等級進行編譯優(yōu)化咐扭。 Xcode 默認的 Debug 使用 -O0, Release 使用 -Os芭挽。更為激進的-Oz減小相同代碼存在多份問題,但是也會使得的函數(shù)調用存在更深的調用棧蝗肪,會影響性能袜爪。Oz 的核心原理是對重復的連續(xù)機器指令外聯(lián)成函數(shù)進行復用,和“內聯(lián)函數(shù)”的原理正好相反薛闪。因此辛馆,開啟 Oz,能減小二進制的大小豁延,但同時理論上會帶來執(zhí)行效率的額外消耗昙篙。對性能(CPU)敏感的代碼使用需要評估。
  • 鏈接期優(yōu)化參數(shù): LLVM 提供鏈接期編譯優(yōu)化诱咏,通過設置工程中的 Link-Time Optimization 進行控制苔可,其本質是開啟生成LTO等優(yōu)化格式。調試期不建議開啟袋狞,會增加編譯時間焚辅。開啟 LTO 之后對于 Objc Runtime 需要的一些結構 比如方法簽名的 literal string, protocol的結構等有比較大的優(yōu)化苟鸯。
己方
  1. 使用頻率高且小的圖片放到 Asset.car 中同蜻,Asset.car 能保證其加載和渲染的速度最優(yōu)。而大的圖片比如背景圖之類的早处,長寬尺寸就有上千個像素湾蔓,而這種放到 Asset.car 中會大大的增加安裝包的大小。
  2. 無用圖片資源刪除砌梆,推薦庫LSUnusedResources
  3. 有用圖片瘦身:圖片大小超過了 100KB默责,你可以考慮使用 WebP贬循;將圖片轉成 WebP格式,推薦iSparta.在顯示圖片時使用 libwebp 進行解析傻丝。WebP 在 CPU 消耗和解碼時間上會比 PNG 高兩倍甘有。所以需要在性能和體積上做取舍。
  4. 對PNG圖片無損壓縮來優(yōu)化包大小沒有效果的葡缰,因為Xcode 會通過自己的壓縮算法重新對圖片進行處理,只能壓縮其尺寸大小忱反。Xcode 中泛释,構建 Asset Catalog 的工具 actool 會首先對 Asset Catalog 中的 png 圖片進行解碼,得到 Bitmap 數(shù)據(jù)温算,然后再運用 actool 的編碼壓縮算法進行編碼壓縮處理怜校。無損壓縮通過變換圖片的編碼壓縮算法減少大小,但是不會改變 Bitmap 數(shù)據(jù)注竿。對于 actool 來說茄茁,它接收的輸入沒有改變,所以無損壓縮無法優(yōu)化 Assets.car 的大小巩割。對于放入 Asset.car 中的圖片如果圖片沒有半透明效果裙顽,使用 70% 的有損壓縮JPEG是一個不錯的方式,既能保證圖片清晰度的同時獲得更小的大小宣谈。
  5. 代碼瘦身:LinkMap 來獲得所有的代碼類和方法的信息愈犹。Mach-O 文件的 __objc_selrefs、__objc_classrefs 和 __objc_superrefs可以獲取用過的方法闻丑,類漩怎,父類。但是Objective-C 是門動態(tài)語言嗦嗡,方法調用可以寫成在運行時動態(tài)調用勋锤,這樣就無法收集全所有調用的方法和類,還要二次確認侥祭。例如+load方法會被系統(tǒng)調用叁执,但也能檢查為未使用類。推薦Appcode工具卑硫。最簡單的靜態(tài)分析:基于 otool dump 最終產(chǎn)物中的 __objc_class_list & __objc_class_refs 做差集找到未使用的 Objc 類徒恋。
  6. Assets.carMach-O是占用空間最大的兩個文件。目前市場上最低支持的 iOS 系統(tǒng)版本一般為 iOS 9欢伏。然而入挣,大部分 Pod 庫的 Podspec 文件中指定的deployment_target(最低支持版本)由于未及時修改,依然還是 iOS 8硝拧,這就導致了這些 Pod 庫中指定的 resource_bundles 在構建出 Assets.car 時径筏,是以 iOS 8 為最低支持版本的葛假。統(tǒng)一改成iOS 9這樣會多出一些優(yōu)化空間。
  7. 符號裁剪符號解釋滋恬,
  8. 減少 Block 的使用
    我們知道 Block 是一個特殊的 OC 對象聊训。需要占用部分二進制空間來表征一個 Block 對象。所以在非必要使用 Block 的場景恢氯。去掉 Block 實現(xiàn)可以優(yōu)化不少包大小带斑,常見的比如 Masonry 通過 Block 實現(xiàn)的鏈式調用。由此可見越是方便開發(fā)工作量勋拟,對性能就越是一個考驗勋磕。大部分問題都能轉化為空間和時間的取舍問題。
實際用到了但被掃描成無用類:

* 一個類確實沒有被其他地方使用敢靡, 但是本身邏輯依賴 +load 挂滓、+initialize、__attribute__((constructor)) 在啟動時調用
* 通過 string 動態(tài)調用
* 抽象基類啸胧、基類等會被認為是無用類
* 通過運行時動態(tài)生成的代碼引用了某個類
* 一個類專門作為通知處理類
* MTLModel 等赶站,通過運行時消息機制 assign value 的無法通過 classref 統(tǒng)計
* 典型的 DI 場景。如果一個類聲明遵循了某個 Protocol纺念,外部使用的時候使用了這個 Protocol 進行方法調用

實際沒用到但被認為有用到:
* 某個對象被另外一個對象引用贝椿,但是另外一個對象本身未被使用到。這時候會遺漏掉這個對象所屬 Class 的檢查

電量

  • CPU:要避免讓 CPU 做多余的事情柠辞。對于大量數(shù)據(jù)的復雜計算团秽,應該把數(shù)據(jù)傳到服務器去處理,如果必須要在 App 內處理復雜數(shù)據(jù)計算叭首,可以通過 GCD 的 dispatch_block_create_with_qos_class 方法指定隊列的 Qos 為 QOS_CLASS_UTILITY习勤,將計算工作放到這個隊列的 block 里。在 QOS_CLASS_UTILITY 這種 Qos 模式下焙格,系統(tǒng)針對大量數(shù)據(jù)的計算图毕,以及復雜數(shù)據(jù)處理專門做了電量優(yōu)化。
  • I/O:將碎片化的數(shù)據(jù)磁盤存儲操作延后眷唉,先在內存中聚合予颤,然后再進行磁盤存儲。碎片化的數(shù)據(jù)進行聚合冬阳,在內存中進行存儲的機制蛤虐,可以使用系統(tǒng)自帶的 NSCache 來完成。NSCache 是線程安全的肝陪,NSCache 會在到達預設緩存空間值時清理緩存驳庭,這時會觸發(fā) cache:willEvictObject: 方法的回調,在這個回調里就可以對數(shù)據(jù)進行 I/O 操作,達到將聚合的數(shù)據(jù) I/O 延后的目的饲常。I/O 操作的次數(shù)減少了蹲堂,對電量的消耗也就減少了。SDWebImage 圖片加載框架贝淤,在圖片的讀取緩存處理時沒有直接使用 I/O柒竞,而是使用了 NSCache。SDWebImage 將獲取的圖片數(shù)據(jù)都放到了 NSCache 里播聪,利用 NSCache 緩存策略進行圖片緩存內存的管理朽基。每次讀取圖片時,會檢查 NSCache 是否已經(jīng)存在圖片數(shù)據(jù):如果有离陶,就直接從 NSCache 里讀炔染А;如果沒有枕磁,才會通過 I/O 讀取磁盤緩存圖片。
  • 蘋果專門維護了一個電量優(yōu)化指南术吝,分別從 CPU计济、設備喚醒、網(wǎng)絡排苍、圖形沦寂、動畫、視頻淘衙、定位传藏、加速度計、陀螺儀彤守、磁力計毯侦、藍牙等多方面因素提出了電量優(yōu)化方面的建議。大家可以瞅瞅具垫。

卡頓檢測

卡頓檢測原理是通過子線程對主runloop添加runloopObserver監(jiān)控即將休眠喚醒兩個狀態(tài)間的時間間隔大于2s左右則認為卡頓侈离,這里確切的說是執(zhí)行souce和進入休眠兩個狀態(tài)更為精確。這里通過開啟一個子線程筝蚕,用while代碼循環(huán)持續(xù)loop卦碾,用定義一個超時2s左右的信號量,超過這個時間往下執(zhí)行的時候判斷信號量若不等于0則認為卡頓起宽,然后將 BeforeSourcesAfterWaiting這兩個狀態(tài)區(qū)間上傳調用棧洲胖,并像微信卡頓監(jiān)聽方案matrix那樣利用退火算法,保證重復的卡頓調用棧信息不會被上傳坯沪。線程數(shù)超出64 個時會導致主線程卡頓绿映,如果卡頓是由于線程多造成的,那么就沒必要通過獲取主線程堆棧去找卡頓原因了屏箍,根據(jù) matrix-iOS 的實測绘梦,每隔 50 毫秒獲取主線程堆棧會增加 3% 的 CPU 占用橘忱,可以忽略不計。 卡頓的類型有線程過多卸奉、CPU滿負荷钝诚、繪制過度、IO操作榄棵、搶鎖

文件 dump:如果內存 dump 的堆棧跟上次捕捉到的不一樣凝颇,則 dump 到文件中;否則按照斐波那契數(shù)列將檢查時間遞增(1疹鳄,1拧略,2,3瘪弓,5垫蛆,8…)直到?jīng)]有遇到卡頓或卡頓堆棧不一樣。這樣能夠避免同一個卡頓寫入多個文件的情況腺怯,也能避免檢測線程圍著同一個卡頓空轉的情況袱饭。


離屏渲染

只要裁剪(透明度/陰影)的內容需要畫家算法未完成之前的內容參與就會觸發(fā)offscreenrendering

正常的顯示是從幀緩存區(qū)FrameBuffer去取呛占,而當我們設置了 cornerRadius 以及 masksToBounds 進行圓角 + 裁剪+陰影+高斯模糊時虑乖,如前文所述,masksToBounds 裁剪屬性會應用到所有的 sublayer 上晾虑。這也就意味著所有的 sublayer 必須要重新被應用一次圓角+裁剪疹味,這也就意味著所有的 sublayer 在第一次被繪制完之后,并不能立刻被丟棄帜篇,而必須要被保存在 Offscreen buffer 中等待下一輪圓角+裁剪糙捺,注意這時候并沒有顯示到屏幕上,多個圖層都在離屏緩存區(qū)等待被一一裁剪圓角(這里是每個圖層都要被裁剪坠狡,并不只是某個)继找,這也就誘發(fā)了離屏渲染。幀緩存區(qū)是展示完了就丟棄的逃沿。離屏渲染并不都是壞的婴渡,因為對于頻繁顯示的復雜的,離屏會提高性能效率凯亮。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
禁止轉載边臼,如需轉載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末假消,一起剝皮案震驚了整個濱河市柠并,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖臼予,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸣戴,死亡現(xiàn)場離奇詭異,居然都是意外死亡粘拾,警方通過查閱死者的電腦和手機窄锅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缰雇,“玉大人入偷,你說我怎么就攤上這事⌒涤矗” “怎么了疏之?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長暇咆。 經(jīng)常有香客問我锋爪,道長,這世上最難降的妖魔是什么爸业? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任几缭,我火速辦了婚禮,結果婚禮上沃呢,老公的妹妹穿的比我還像新娘。我一直安慰自己拆挥,他們只是感情好薄霜,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纸兔,像睡著了一般惰瓜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汉矿,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天崎坊,我揣著相機與錄音,去河邊找鬼洲拇。 笑死奈揍,一個胖子當著我的面吹牛,可吹牛的內容都是我干的赋续。 我是一名探鬼主播男翰,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纽乱!你這毒婦竟也來了蛾绎?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎租冠,沒想到半個月后鹏倘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡顽爹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年纤泵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片话原。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡夕吻,死狀恐怖,靈堂內的尸體忽然破棺而出繁仁,到底是詐尸還是另有隱情涉馅,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布黄虱,位于F島的核電站稚矿,受9級特大地震影響,放射性物質發(fā)生泄漏捻浦。R本人自食惡果不足惜晤揣,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朱灿。 院中可真熱鬧昧识,春花似錦、人聲如沸盗扒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侣灶。三九已至甸祭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間褥影,已是汗流浹背池户。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凡怎,地道東北人校焦。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像统倒,于是被迫代替她去往敵國和親斟湃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容