Unity內(nèi)存管理你應(yīng)該知道的底層原理

本文首發(fā)公眾號洪流學堂。洪流學堂枪芒,讓你快人幾步筒狠。

本文主要是Unity官方川哥的視頻《淺談Unity內(nèi)存管理》的筆記及相關(guān)知識點補充,如果有時間強烈建議學習原視頻:
https://www.bilibili.com/video/BV1aJ411t7N6

正文

1废恋、什么是內(nèi)存

內(nèi)存分為物理內(nèi)存、虛擬內(nèi)存扒寄。

關(guān)于物理內(nèi)存:

CPU訪問內(nèi)存是一個慢速過程鱼鼓。

CPU在需要訪問內(nèi)存時,先是訪問自己的緩存(L1Cache该编、L2Cache……)迄本,當全部Miss之后,CPU會去主內(nèi)存拿一段完整的指令到CPU的緩存中课竣。因此嘉赎,我們需要盡可能保證CPU的指令是連續(xù)的,防止CPU過多地與主內(nèi)存之間的內(nèi)存交換產(chǎn)生IO于樟。

Unity為了處理上述問題公条,減少Cache Miss ,推出了ECS和DOTS迂曲,把分散的內(nèi)存數(shù)據(jù)變成整塊靶橱、連續(xù)的數(shù)據(jù)。(但DOTS目前20210513還不穩(wěn)定,版本之間的API可能有很大變化且不兼容关霸,產(chǎn)品級項目使用有風險)

關(guān)于虛擬內(nèi)存:

電腦在物理內(nèi)存不夠的時候传黄,操作系統(tǒng)會把一些不用的數(shù)據(jù)(DeadMemory)交換到硬盤上,稱之為內(nèi)存交換队寇。

但是手機是不做內(nèi)存交換的膘掰,一是因為移動設(shè)備的硬盤IO速度比PC慢很多,二是因為移動設(shè)備的硬盤可擦寫次數(shù)更少佳遣;因此手機如果做內(nèi)存交換一是慢识埋,而是減少設(shè)備壽命看,所以Android機上沒有做內(nèi)存交換苍日。IOS可以把不活躍的內(nèi)存進行壓縮,使得實際可用的內(nèi)存更多窗声,而安卓沒有這個能力相恃。

關(guān)于移動設(shè)備和PC:

移動設(shè)備(手機)與PC的區(qū)別在于,手機沒有獨立顯卡笨觅、獨立顯存拦耐。手機上無論是CPU還是GPU都是共用一個緩存,而且手機的內(nèi)存更小见剩、緩存級數(shù)更少杀糯、大小更小。臺式機的三級緩存大約8~16M苍苞,而手機只有2M固翰。

綜上,手機上的內(nèi)存羹呵,不論從哪個角度看骂际,都是比PC要小很多的。所以冈欢,手機上更容易出現(xiàn)內(nèi)存不夠的問題歉铝。

2、Android 內(nèi)存管理

Android是基于Linux開發(fā)的凑耻,所以Android的內(nèi)存管理和Linux很相似太示。

Android的內(nèi)存管理基本單位是Page(頁),一般是4k 一個Page香浩。內(nèi)存的回收和分配都是以 Page為單位進行操作类缤,也就是4k。Android內(nèi)存分用戶態(tài)和內(nèi)核態(tài)兩個部分邻吭,內(nèi)核態(tài)的內(nèi)存是用戶嚴格不能訪問的呀非。

關(guān)于內(nèi)存殺手:Low Memory Killer (LMK)

當手機的內(nèi)存使用量過多時,就會出現(xiàn)LMK,對當前手機的各種App岸裙、服務(wù)進行關(guān)停猖败。安卓的各種應(yīng)用、服務(wù)分為以下一些類別:

0降允、Native:系統(tǒng)內(nèi)核

1恩闻、System:系統(tǒng)服務(wù)

2、Persistent: 用戶服務(wù)剧董,比如電話幢尚、藍牙、Wifi等翅楼。

3尉剩、Foreground:前臺應(yīng)用,當前正在使用的Activity

4毅臊、Perceptible:輔助應(yīng)用理茎,音樂、搜索管嬉、鍵盤等皂林;

5、Service:駐后臺線程的服務(wù)蚯撩,云同步础倍、垃圾回收等;

6胎挎、Home鍵沟启;

7、Previous:上一個使用的應(yīng)用犹菇;

8美浦、Cached:后臺,之前使用過的各種應(yīng)用项栏。

這個也是Android系統(tǒng)的應(yīng)用優(yōu)先度排序浦辨,編號越小優(yōu)先級越高。當LMK開始工作的時候沼沈,會從優(yōu)先度最低的應(yīng)用開始Kill流酬。即最先中斷各種Cached,最后才會到Native列另。

例如當Cached被殺掉之后芽腾,現(xiàn)象就是當你切換到后臺的那些應(yīng)用時,你會發(fā)現(xiàn)那些應(yīng)用重啟了页衙。

當Home被殺死的時候摊滔,你發(fā)現(xiàn)當你回到桌面時阴绢,桌面會重啟艰躺,你的桌面圖標會重建,或者壁紙沒了腺兴。

到Perceptible的時候,可能你的音樂页响、鍵盤不見了篓足。

再往上進行栈拖,到Foreground時,當前前臺應(yīng)用就會被殺死没陡,這個時候就會出現(xiàn)應(yīng)用閃退涩哟。

在往上手機就開始重啟了诗鸭。

3参滴、Android內(nèi)存指標

RSS:Resident Set Size

你當前的APP所應(yīng)用到的所有內(nèi)存砾赔。除了你自己的APP所使用的內(nèi)存之外,你調(diào)用的各種服務(wù)暴心、共用庫所產(chǎn)生的內(nèi)存都會統(tǒng)計到RSS之中专普。

PSS:Proportional Set Size

與RSS不同的是檀夹,PSS會把公共庫所使用的內(nèi)存平攤到所有調(diào)用這個庫的APP上。(可能你自己的應(yīng)用沒有申請很多內(nèi)存娜亿,但是你的調(diào)用的某個公共庫已經(jīng)有了很大的內(nèi)存分配蚌堵,平攤下來就會導(dǎo)致你自己的APP的PSS虛高。)

USS:Unique Set Size

只有此APP所使用的內(nèi)存嘁灯,剔除掉公共庫的內(nèi)存分配够挂。

我們在實際工作中更多要做的是對USS的優(yōu)化孽糖,有時也會注意一下PSS。

4尘奏、關(guān)于Unity內(nèi)存

Unity內(nèi)存的分類

Unity內(nèi)存分為 Native Memory和 Managed Memory (托管內(nèi)存)炫加。值得注意的是铺然,在Editor下和在Runtime下Unity的內(nèi)存分配是完全不同的魄健。不但分配內(nèi)存的大小會有不同,統(tǒng)計看到的內(nèi)存大小不同革骨,甚至是內(nèi)存分配時機和方式也不同良哲。

比如一個AssetBundle助隧,在編輯器下是你一打開Unity就開始加載進內(nèi)存并村,而在Runtime下則是你使用時才會加載颜及,如果不讀取函匕,是不會進內(nèi)存的潘悼。(Unity2019之后做了一些Asset導(dǎo)入優(yōu)化,不使用的資源就不會導(dǎo)入)挠唆。 因為 Editor 不注重 Runtime 的表現(xiàn)嘱吗,更注重編輯器中編輯時的流暢谒麦。

但如果游戲龐大到幾十個 G绕德,如果第一次打開項目,會消耗很多時間踪蹬,有的大的會幾天跃捣,甚至到一周夺蛇。

Unity的內(nèi)存還可以分為引擎管理的內(nèi)存和用戶管理器的內(nèi)存兩類蚊惯。引擎管理的內(nèi)存一般開發(fā)者是訪問不到的截型,而用戶管理的內(nèi)存才是使用者需要關(guān)系和優(yōu)先考慮的儒溉。

還有一個Unity監(jiān)測不到的內(nèi)存:用戶分配的 Native 內(nèi)存內(nèi)存是Unity的Profile工具監(jiān)測不到顿涣。例如:

  • 自己寫的 Native 插件(C++ 插件)涛碑, Unity 無法分析已經(jīng)編譯過的 C++ 是如何去分配和使用內(nèi)存的。
  • Lua 完全由自己管理內(nèi)存歹篓,Unity 無法統(tǒng)計到內(nèi)部的使用情況庄撮。

5、最佳實踐 Native 內(nèi)存

Unity 重載了所有分配內(nèi)存的操作符(C++ alloc毡庆、new)么抗,使用這些重載的時候乖坠,會需要一個額外的 memory label (Profiler-shaderlab-object-memory-detail-snapshot刀闷,里面的名字就是 label:指當前內(nèi)存要分配到哪一個類型池里面)

  • 使用重載過的分配符去分配內(nèi)存時甸昏,Allocator 會根據(jù)你的 memory label 分配到不同 Allocator 池里面施蜜,每個 Allocator 池 單獨做自己的跟蹤。因此當我們?nèi)?Runtime get memory label 下面的池時就可以問 Allocator缸沃,里面有多少東西 多少兆趾牧。
  • Allocator 在 NewAsRoot (Memory “island”(沒聽清)) 中生成翘单。在這個 Memory Root 下面會有很多子內(nèi)存:shader:當我們加載一個 Shader 進內(nèi)存的時候蹦渣,會生成一個 Shader 的 root柬唯。Shader 底下有很多數(shù)據(jù):sub shader锄奢、Pass 等會作為 memory “island” (root) 的成員去依次分配。因此當我們最后統(tǒng)計 Runtime 的時候师坎,我們會統(tǒng)計 Root胯陋,而不會統(tǒng)計成員遏乔,因為太多了沒法統(tǒng)計。
  • 因為是 C++ 的凉翻,因此當我們 delete制轰、free 一個內(nèi)存的時候會立刻返回內(nèi)存給系統(tǒng)垃杖,與托管內(nèi)存堆不一樣调俘。

Scene

  • Unity 是一個 C++ 引擎旺垒,所有實體最終都會反映在 C++ 上先蒋,而不是托管堆里面鞭达。因此當我們實例化一個 GameObject 的時候皇忿,在 Unity 底層會構(gòu)建一個或多個 Object 來存儲這個 GameObject 的信息鳍烁,例如很多 Components幔荒。因此當 Scene 有過多 GameObject 的時候,Native 內(nèi)存就會顯著上升提澎。
  • 當我們看 Profiler念链,發(fā)現(xiàn) Native 內(nèi)存大量上升的時候掂墓,應(yīng)先去檢查 Scene君编。

Audio(音頻):

DSP Buffer :相當于音頻的緩沖吃嘿。

  • 當一個聲音要播放的時候兑燥,它需要向 CPU 去發(fā)送指令——我要播放聲音。但如果聲音的數(shù)據(jù)量非常小寺庄,就會造成頻繁地向 CPU 發(fā)送指令斗塘,會造成 I\O馍盟。

  • 當 Unity 用到 FMOD 聲音引擎時(Unity 底層也用到 FMOD)贞岭,會有一個 Buffer搓侄,當 Buffer 填充滿了讶踪,才會向 CPU 發(fā)送“我要播放聲音”的指令。

  • DSP buffer 會導(dǎo)致兩種問題:

    • 如果(設(shè)置的) buffer 過大廓俭,會導(dǎo)致聲音的延遲研乒。要填充滿 buffer 是要很多聲音數(shù)據(jù)的告嘲,但聲音數(shù)據(jù)又沒這么大橄唬,因此會導(dǎo)致一定的聲音延遲参歹。
    • 如果 DSP buffer 太小犬庇,會導(dǎo)致 CPU 負擔上升臭挽,滿了就發(fā)欢峰,消耗增加纽帖。

Foce to Mono : 強制單聲道

當兩個聲道完全相同時可以Force To Mono懊直,可以節(jié)省一半的內(nèi)存。
在導(dǎo)入聲音的時候有一個設(shè)置雕崩,很多音效師為了聲音質(zhì)量盼铁,會把聲音設(shè)為雙聲道捉貌。但 95% 的聲音趁窃,左右聲道放的是完全一樣的數(shù)據(jù)醒陆。這導(dǎo)致了 1M 的聲音會變成 2M刨摩,體現(xiàn)在包體里和內(nèi)存里澡刹。因此一般對于聲音不是很敏感的游戲罢浇,會建議改成 Force to mono嚷闭,強制單聲道赖临。

Format

例如IOS對MP3有硬解支持的兢榨,所以MP3的解析會快很多(Android 沒有)吵聪。

Compressiont Format

聲音文件在內(nèi)存的存在形態(tài)(解壓的暖璧、壓縮的等)澎办。

Code Size

代碼也是需要加載進內(nèi)存的局蚀,使用時要注意減少模板泛型的濫用琅绅。因為模板泛型在編譯成C++時,會把同樣的代碼排列組合都編譯一邊骆捧,導(dǎo)致Code Size 大幅上升敛苇。

可以參考 Memory Management in Unity:https://learn.unity.com/tutorial/memory-management-in-unity 3.IL2CPP & Mono 的 Generic Sharing 部分枫攀。

AssetBundle

TypeTree

  • Unity 的每一種類型都有很多數(shù)據(jù)結(jié)構(gòu)的改變来涨,為了對此做兼容蹦掐,Unity 會在生成數(shù)據(jù)類型序列化的時候笤闯,順便會生成 TypeTree:當前我這一個版本里用到了哪些變量颗味,對應(yīng)的數(shù)據(jù)類型是什么浦马。在反序列化的時候,會根據(jù) TypeTree 來進行反序列化张漂。
    • 如果上一個版本的類型在這個版本中沒有晶默,TypeTree 就沒有它,因此不會碰到它航攒。
    • 如果要用一個新的類型磺陡,但在這個版本中不存在,會用一個默認值來序列化漠畜,從而保證了不會在不同的版本序列化中出錯币他,這個就是 TypeTree 的作用憔狞。
  • Build AssetBundle 中有開關(guān)可以關(guān)掉 TypeTree蝴悉。當你確認當前 AssetBundle 的使用和 Build Unity 的版本一模一樣,這時候可以把 TypeTree 關(guān)掉瘾敢。
    • 例如如果用同樣的 Unity 打出來的 AssetBundle 和 APP拍冠,TypeTree 則完全可以關(guān)掉尿这。
  • TypeTree 好處:
    • 內(nèi)存減少。TypeTree 本身是數(shù)據(jù)庆杜,也要占內(nèi)存射众。
    • 包大小會減少,因為 TypeTree 會序列化到 AssetBundle 包中欣福,以便讀取责球。
    • Build 和運行時會變快焦履。源代碼中可以看到拓劝,因為每一次 Serialize 東西的時候,如果發(fā)現(xiàn)需要 Serialize TypeTree嘉裤,則會 Serialize 兩次:
      • 第一次先把 TypeTree Serialize 出來
      • 第二次把實際的東西 Serialize 出來
      • 反序列化也會做同樣的事情郑临,1. TypeTree 反序列化,2. 實際的東西反序列化屑宠。
    • 當你確定你當前的AssetBundle和你的Unity是同一個版本的時候厢洞,就可以關(guān)掉TypeTree。關(guān)掉TypeTree之后可以減少內(nèi)存大小典奉、包大小躺翻、加快運行速度。

壓縮方式:使用Lz4卫玖,而不是Lzma

Size & Count

  • AssetBundle 包打多大是很玄學的問題串慰,但每一個 Asset 打一個 Bundle 這樣不太好偏塞。
    • 有一種減圖片大小的方式,把 png 的頭都剔除出來邦鲫。因為頭的色板是通用的灸叼,而數(shù)據(jù)不通用神汹。AssetBundle 也一樣,一部分是它的頭古今,一部分是實際打包的部分屁魏。因此如果每個 Asset 都打 Bundle 會導(dǎo)致 AssetBundle 的頭比數(shù)據(jù)還要大。
  • 官方的建議是每個 AssetBundle 包大概 1M~2M 左右大小捉腥,考慮的是網(wǎng)絡(luò)帶寬氓拼。但現(xiàn)在 5G 的時候,可以考慮適當把包體加大抵碟。還是要看實際用戶的情況桃漾。

Resources文件夾

不要使用,除非在 debug 的時候

  • Resource 和 AssetBundle 一樣拟逮,也有頭來索引撬统。Resource 在打進包的時候會做一個紅黑樹,來幫助 Resource 來檢索資源在什么位置敦迄,
  • 如果 Resource 非常大恋追,那么紅黑樹也會非常大。
  • 紅黑樹是不可卸載的罚屋。在剛開始游戲的時候就會加載進內(nèi)存中苦囱,會持續(xù)對游戲造成內(nèi)存壓力。
  • 會極大拖慢游戲的啟動時間脾猛。因為紅黑樹沒加載完撕彤,游戲不能啟動。

Texture

Upload Buffer:和聲音的DSP Buffer很像尖滚,設(shè)置填充滿多大之后再推向CPU/GPU喉刘。

Read/Write : 不使用就關(guān)閉它。

  • Texture 沒必要就不要開 read and write漆弄。正常 Texture 讀進內(nèi)存睦裳,解析完了,放到 upload buffer 里后撼唾,內(nèi)存里的就會 delete 掉廉邑。
  • 但如果檢測到你開了 r/w 就不會 delete 了,就會在顯存和內(nèi)存中各一份倒谷。

Mip Map : 像UI這些不需要的就關(guān)閉它蛛蒙,可以省大量內(nèi)存。渤愁。

Mesh:

Read/Write :同上Texture

Compression:雖然寫的是壓縮牵祟,但實際效果并不一定有用,有些版本 Compression 開了不如不開抖格,內(nèi)存占用可能更嚴重诺苹,具體需要自己試咕晋。

6、Unity Managed Memory (托管內(nèi)存):

VM內(nèi)存池

Mono虛擬機的內(nèi)存池收奔,實際上VM是會返回給操作系統(tǒng)掌呜。

  • 返還條件是什么?
    • GC 不會把內(nèi)存直接返還給系統(tǒng)
    • 內(nèi)存也是以 Block 來管理的坪哄。當一個 Block 連續(xù)六次 GC 沒有被訪問到质蕉,這塊內(nèi)存才會被返還到系統(tǒng)。(mono runtime 基本看不到翩肌,IL2cpp runtime 可能會看到多一點)
  • 不會頻繁地分配內(nèi)存模暗,而是一次分配一大塊。

GC機制

Unity的GC機制是Boehm內(nèi)存回收摧阅,是不分代的汰蓉,非壓縮式的绷蹲。(之所以是使用Boehm是因為Unity和Mono的一些歷史原因棒卷,以及目前Unity主要精力放在IL2CPP上面)

GC機制考量

  • Throughput((回收能力)
    • 一次回收,會回收多少內(nèi)存
  • Pause times(暫停時長)
    • 進行回收的時候祝钢,對主線程的影響有多大
  • Fragmentation(碎片化)
    • 回收內(nèi)存后比规,會對整體回收內(nèi)存池的貢獻有多少
  • Mutator overhead(額外消耗)
    • 回收本身有 overhead,要做很多統(tǒng)計拦英、標記的工作
  • Scalability(可擴展性)
    • 擴展到多核蜒什、多線程會不會有 bug
  • Protability(可移植性)
    • 不同平臺是否可以使用

BOEHM

  • Non-generational(不分代的)
image.png

分代是指:大塊內(nèi)存、小內(nèi)存疤估、超小內(nèi)存是分在不同內(nèi)存區(qū)域來進行管理的灾常。還有長久內(nèi)存,當有一個內(nèi)存很久沒動的時候會移到長久內(nèi)存區(qū)域中铃拇,從而省出內(nèi)存給更頻繁分配的內(nèi)存钞瀑。

  • Non-compacting(非壓縮式)
image.png
  • 當有內(nèi)存被回收的時候,壓縮內(nèi)存會把上圖空的地方重新排布慷荔。
  • 但 Unity 的 BOEHM 不會雕什!它是非壓縮式的∠跃В空著就空著贷岸,下次要用了再填進去。
    • 歷史原因:Unity 和 Mono 合作上磷雇,Mono 并不是一直開源免費的偿警,因此 Unity 選擇不升級 Mono,與實際 Mono 版本有差距唯笙。
    • 下一代 GC
      • Incremental GC(漸進式 GC)
        • 現(xiàn)在如果我們要進行一次 GC螟蒸,主線程被迫要停下來落剪,遍歷所有 GC Memory “island”(沒聽清),來決定哪些 GC 可以回收尿庐。
        • Incremental GC 把暫停主線程的事分幀做了忠怖。一點一點分析,主線程不會有峰值抄瑟》财總體 GC 時間不變,但會改善 GC 對主線程的卡頓影響皮假。
      • SGen 或者升級 Boehm鞋拟?
        • SGen 是分代的,能避免內(nèi)存碎片化問題惹资,調(diào)動策略贺纲,速度較快
      • IL2CPP
        • 現(xiàn)在 IL2CPP 的 GC 機制是 Unity 自己重新寫的,是升級版的 Boehm

Memory fragmentation 內(nèi)存碎片化

為了防止內(nèi)存碎片化(Memory Fragmentation)褪测,在做加載的時候猴誊,應(yīng)先加載大內(nèi)存的資源,再加載小內(nèi)存的資源(因為Bohem沒有內(nèi)存壓縮)侮措,這樣可以保證最大限度地利用內(nèi)存懈叹。

image.png
  • 為什么內(nèi)存下降了,但總體內(nèi)存池還是上升了分扎?
    • 因為內(nèi)存太大了澄成,內(nèi)存池沒地方放它,雖然有很多內(nèi)存可用畏吓。(內(nèi)存已被嚴重碎片化)
  • 當開發(fā)者大量加載小內(nèi)存墨状,使用釋放*N,例如配置表菲饼、巨大數(shù)組肾砂,GC 會漲一大截。
    • 建議先操作大內(nèi)存巴粪,再操作小內(nèi)存通今,以保證內(nèi)存以最大效率被重復(fù)利用。

Zombie Memory(僵尸內(nèi)存)

  • 內(nèi)存泄露說法是不對的肛根,內(nèi)存只是沒有任何人能夠管理到辫塌,但實際上內(nèi)存沒有被泄露,一直在內(nèi)存池中派哲,被 zombie 掉了臼氨,這種叫 Zombie 內(nèi)存。
  • 無用內(nèi)容
    • Coding 時候或者團隊配合的時候有問題芭届,加載了一個東西進來储矩,結(jié)果從頭到尾只用了一次感耙。
    • 有些開發(fā)者寫了隊列調(diào)度策略,但是策略寫的不好持隧,導(dǎo)致一些他覺得會被釋放的東西即硼,沒有被釋放掉。
    • 找是否有活躍度實際上并不高的內(nèi)存屡拨。
  • 沒有釋放
  • 通過代碼管理和性能工具分析只酥,查看各個資源的引用

最佳實踐

1、用Destory而不是NULL 呀狼。

2裂允、多使用Struct。

3哥艇、使用內(nèi)存池:VM 本身有內(nèi)存池绝编,但建議開發(fā)者對高頻使用的小部件,自己建一個內(nèi)存池貌踏。例如UI十饥、粒子系統(tǒng)、子彈等哩俭。

4绷跑、閉包和匿名函數(shù):減少使用。所有的閉包和匿名函數(shù)最后都會變成一個Class凡资。

5、協(xié)程:只要不被釋放谬运,里面所有引用的所有內(nèi)存都會存在隙赁。(用的時候生產(chǎn)一個,不用的時候扔掉)梆暖。

6伞访、配置表:減少一次性使用的配置表數(shù)量;不要把整個配置表都扔進去轰驳,是否能切分下配置表厚掷。

7、單例:慎用级解,游戲一開始到游戲死掉冒黑,一直在內(nèi)存中。

8勤哗、Unity性能分析工具UPR:https://mp.weixin.qq.com/s/n0ERE93QQZ499Xz79eTqKA

后記:

建議各位Unity開發(fā)者去看看原視頻抡爹,會收獲更多更詳細~
https://www.bilibili.com/video/BV1aJ411t7N6

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芒划,隨后出現(xiàn)的幾起案子冬竟,更是在濱河造成了極大的恐慌欧穴,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泵殴,死亡現(xiàn)場離奇詭異涮帘,居然都是意外死亡,警方通過查閱死者的電腦和手機笑诅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門焚辅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人苟鸯,你說我怎么就攤上這事同蜻。” “怎么了早处?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵湾蔓,是天一觀的道長。 經(jīng)常有香客問我砌梆,道長默责,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任咸包,我火速辦了婚禮桃序,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烂瘫。我一直安慰自己媒熊,他們只是感情好,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布坟比。 她就那樣靜靜地躺著芦鳍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪葛账。 梳的紋絲不亂的頭發(fā)上柠衅,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音籍琳,去河邊找鬼菲宴。 笑死,一個胖子當著我的面吹牛趋急,可吹牛的內(nèi)容都是我干的喝峦。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼宣谈,長吁一口氣:“原來是場噩夢啊……” “哼愈犹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤漩怎,失蹤者是張志新(化名)和其女友劉穎勋颖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勋锤,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡饭玲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叁执。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茄厘。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谈宛,靈堂內(nèi)的尸體忽然破棺而出次哈,到底是詐尸還是另有隱情,我是刑警寧澤吆录,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布窑滞,位于F島的核電站,受9級特大地震影響恢筝,放射性物質(zhì)發(fā)生泄漏哀卫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一撬槽、第九天 我趴在偏房一處隱蔽的房頂上張望此改。 院中可真熱鬧,春花似錦侄柔、人聲如沸共啃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勋磕。三九已至,卻和暖如春敢靡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苦银。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工啸胧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人幔虏。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓纺念,卻偏偏與公主長得像,于是被迫代替她去往敵國和親想括。 傳聞我的和親對象是個殘疾皇子陷谱,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容