APP 性能優(yōu)化與分析CPU篇(二)- Systrace

前言

編寫本文時(shí)使用的操作系統(tǒng)環(huán)境為 Ubuntu 20.04.3 LTS ,使用的 Android Studio 為最新版的 Arctic Fox量没。

1. Systrace 簡(jiǎn)介

1.1 簡(jiǎn)介

Systrace 就是 System Trace 的簡(jiǎn)稱玉转,可以記錄一段時(shí)間內(nèi)系統(tǒng)的活動(dòng)狀態(tài),并可以生成HTML格式的報(bào)告殴蹄。開發(fā)者可以通過分析這份報(bào)告究抓,發(fā)現(xiàn)應(yīng)用和系統(tǒng)的性能瓶頸。

1.2 原理

Systrace 的原理很簡(jiǎn)單袭灯,Google 的開發(fā)人員在 Android 系統(tǒng)的一些關(guān)鍵組件(System Server漩蟆、虛擬機(jī)等)已經(jīng)預(yù)先做了埋點(diǎn),Java 層使用 TraceCompat 進(jìn)行埋點(diǎn)妓蛮, Native 層可以使用使用 ATrace 怠李。通過這些埋點(diǎn)就可以得到核心方法的執(zhí)行開始和結(jié)束時(shí)間。

2. 啟動(dòng) Systrace

在 Systrace 推出之初有以下兩種啟動(dòng)方式:

2.1 使用 Android Device Monitor 啟動(dòng) Systrace (過時(shí))

在以往的Android Studio 版本中我們可以通過Android Device Monitor 來捕獲System trace蛤克。但是這種方式已經(jīng)過時(shí)了捺癞,捕獲的Trace.html在新版的Chrome中打開會(huì)出現(xiàn)以下錯(cuò)誤。

想搞明白什么會(huì)有這樣的錯(cuò)誤构挤,可以參考這里的回答:https://stackoverflow.com/questions/36865899/react-native-android-systrace-html-is-blank-in-ubuntu-14-04

2.2 使用 Python 命令啟動(dòng) Systrace (推薦)

使用Python 命令執(zhí)行Systrace 共分三步髓介。

  1. 從 Android Studio 下載并安裝最新的 Android SDK 工具

2.安裝 Python2 環(huán)境,Systrace 不支持 Python3

3.使用將 Android 4.3(API 級(jí)別 18)或更高版本的設(shè)備連接到電腦

4.在控制臺(tái)中執(zhí)行 Systrace 指令(下一節(jié)具體介紹)

systrace 命令在 Android SDK 工具軟件包中提供筋现,并且可以在 android/Sdk/platform-tools/systrace/ 中找到唐础。

  1. Systrace 指令

Sysrace 在命令行中的語法結(jié)構(gòu)如下

python systrace.py [options] [categories]

例如,以下命令會(huì)調(diào)用 systrace 來記錄設(shè)備活動(dòng)矾飞,并生成一個(gè)名為 mynewtrace.html 的 HTML 報(bào)告一膨。此類別列表是大多數(shù)設(shè)備的合理默認(rèn)列表。

# 使用前需要先cd到systrace.py所在的目錄
python systrace.py -o mynewtrace.html sched freq idle am wm gfx view \
binder_driver hal dalvik camera input res

提示:如果要在跟蹤輸出中查看任務(wù)名稱洒沦,必須在命令參數(shù)中添加sched類別咐低。

3.1 Systrace 支持的 options

在控制臺(tái)輸入python systrace.py -h可以查看Systrace支持的所有options以及對(duì)應(yīng)的作用搓幌。stpython systrace.py的別名,需要預(yù)先在環(huán)境變量中定義膛锭,之后會(huì)介紹卢未。

3.1.1 systrce -o

將 HTML 跟蹤報(bào)告寫入指定的文件携取。如果未指定此選項(xiàng)稚疹,systrace會(huì)將報(bào)告保存到 systrace.py所在的目錄中香拉,并將其命名為 trace.html。'

python systrace.py -o trace.html

3.1.2 systrce -t N

跟蹤設(shè)備活動(dòng) N 秒濒翻。如果未指定此選項(xiàng)屁柏,systrace會(huì)提示在命令行中按 Enter 鍵結(jié)束跟蹤.

python systrace.py -t 5

3.1.3 systrce -b N

使用 N KB 的跟蹤緩沖區(qū)大小啦膜。使用此選項(xiàng),可以限制跟蹤期間收集到的數(shù)據(jù)的總大小前联。

python systrace.py -b 2048

3.1.4 systrce -k functions

跟蹤逗號(hào)分隔列表中指定的特定內(nèi)核函數(shù)的活動(dòng)。

python systrace.py -k

3.1.5 systrce -a app-name

啟用對(duì)應(yīng)用的跟蹤娶眷,指定為包含進(jìn)程名稱的逗號(hào)分隔列表似嗤。這些應(yīng)用必須包含 Trace類中的跟蹤檢測(cè)調(diào)用。應(yīng)在分析應(yīng)用時(shí)指定此選項(xiàng)届宠。很多庫(例如 RecyclerView)都包括跟蹤檢測(cè)用烁落,這些調(diào)用可在啟用應(yīng)用級(jí)跟蹤時(shí)提供有用的信息。如需了解詳情豌注,請(qǐng)參閱定義自定義事件伤塌。如需跟蹤搭載 Android 9(API 級(jí)別 28)或更高版本的設(shè)備上的所有應(yīng)用,請(qǐng)傳遞用添加引號(hào)的通配符字符 "*"轧铁。

python systrace.py -a 
# 或
python systrace.py -a "*"

3.1.6 systrce --from-file=file-path

根據(jù)文件(例如包含原始跟蹤數(shù)據(jù)的 TXT 文件)創(chuàng)建交互式 HTML 報(bào)告每聪。

python systrace.py --form-file = trace.txt

3.1.7 systrce -e device-serial

在已連接的特定設(shè)備(由對(duì)應(yīng)的設(shè)備序列號(hào)標(biāo)識(shí))上進(jìn)行跟蹤。

python systrace.py -e emulator-5554

設(shè)備序列號(hào)可以使用 adb devices 查看

3.2 Systrace 支持的 categories

使用 -l 指令可以查已連接設(shè)備可用的服務(wù)列表齿风,如下所示药薯,部分服務(wù)只能在取得root權(quán)限時(shí)才能追蹤。

3.3 快捷啟動(dòng)Systrace

在Ubuntu系統(tǒng)的home目錄中打開.bashrc文件救斑,在最底部加入以下代碼童本,

# Systrace
alias st='python /home/link/Android/Sdk/platform-tools/systrace/systrace.py'

alias st-start='python /home/link/Android/Sdk/platform-tools/systrace/systrace.py -o /home/link/桌面/TraceReport/trace.html'

然后命令行中執(zhí)行 source .bashrc,使配置生效脸候。

source .bashrc

這樣我們就可以使用 stst-start 來快速執(zhí)行 systrace 腳本穷娱。

4. 瀏覽 Systrace 報(bào)告

以下內(nèi)容部分摘錄自Android官方文檔 - 瀏覽Systrace報(bào)告 | Android開發(fā)者,為了便于閱讀运沦,在官方文檔的基礎(chǔ)上有一定修改和刪減泵额。

在Chrome瀏覽器(或是基于Chromium的Edge瀏覽器)的地址欄輸入chrome://tracing命令,然后將生成的trace.html文件拖進(jìn)來携添,或者通過load按鈕導(dǎo)入梯刚,可以看到如下所示的報(bào)告:

Systrace會(huì)生成包含多個(gè)部分的輸出 HTML 文件。該報(bào)告列出了每個(gè)進(jìn)程的線程薪寓。如果給定線程會(huì)渲染界面幀亡资,該報(bào)告還會(huì)沿時(shí)間軸指明所渲染的幀。將報(bào)告從左向右移動(dòng)時(shí)向叉,時(shí)間會(huì)向前推移锥腻。報(bào)告從上到下包含以下幾個(gè)部分:

4.1 用戶互動(dòng)

第一部分包含表示應(yīng)用或游戲中的具體用戶互動(dòng)(例如點(diǎn)按設(shè)備屏幕)的條形圖。這些互動(dòng)可用作有用的時(shí)間標(biāo)記母谎。

4.2 CPU 活動(dòng)

下一部分顯示了表示每個(gè) CPU 中的線程活動(dòng)的條形圖瘦黑。這些條形會(huì)顯示所有應(yīng)用(包括應(yīng)用或游戲)中的 CPU 活動(dòng)。

CPU 活動(dòng)部分可以展開,展開后就可以查看每個(gè) CPU 的休眠狀態(tài)幸斥,C-State可以簡(jiǎn)單看做CPU的工作狀態(tài)匹摇。更進(jìn)一步的含義,可以參考這篇文章:https://www.cnblogs.com/apnpc/p/13780146.html

4.3 系統(tǒng)事件

此部分中的直方圖會(huì)顯示特定的系統(tǒng)級(jí)事件甲葬,例如特定對(duì)象的紋理計(jì)數(shù)和總大小廊勃。

值得仔細(xì)檢查的直方圖是標(biāo)記為 SurfaceView 的直方圖。計(jì)數(shù)表示已傳遞到顯示管道并等待顯示在設(shè)備屏幕上的組合幀緩沖區(qū)的數(shù)量经窖。由于大多數(shù)設(shè)備都會(huì)進(jìn)行雙重或三重緩沖坡垫,因此該計(jì)數(shù)幾乎總為 0、1 或 2画侣。

描繪 Surface Flinger 進(jìn)程(包括 VSync 事件和界面線程交換工作)的其他直方圖冰悠,如圖所示:

4.4 顯示幀

這一部分通常是報(bào)告中最頂部的部分,描繪了一條多色線條配乱,后面是成堆的條形溉卓。這些形狀表示已創(chuàng)建的特定線程的狀態(tài)和幀堆棧。堆棧的每個(gè)層級(jí)代表對(duì) beginSection() 的一次調(diào)用搬泥,或?yàn)閼?yīng)用或游戲定義的自定義跟蹤事件的開頭的诵。

注意:界面線程(即通常運(yùn)行應(yīng)用或游戲的主線程)始終會(huì)顯示為第一個(gè)線程。

每個(gè)條形堆上方的多色線條表示特定線程隨時(shí)間變化的一組狀態(tài)佑钾。每段線條可以包含以下顏色之一:

綠色:正在運(yùn)行

線程正在完成與某個(gè)進(jìn)程相關(guān)的工作或正在響應(yīng)中斷西疤。

藍(lán)色:可運(yùn)行

線程可以運(yùn)行但目前未進(jìn)行調(diào)度。

白色:休眠

線程沒有可執(zhí)行的任務(wù)休溶,可能是因?yàn)榫€程在遇到斥鎖定時(shí)被阻止代赁。

橙色:不可中斷的休眠

線程在遇到 I/O 操作時(shí)被阻止或正在等待磁盤操作完成。

紫色:可中斷的休眠

線程在遇到另一項(xiàng)內(nèi)核操作(通常是內(nèi)存管理)時(shí)被阻止兽掰。

注意:在 Systrace 報(bào)告中芭碍,可以點(diǎn)擊該線條以確定該線程在給定時(shí)間由哪個(gè) CPU 控制。

4.4 鍵盤快捷鍵

下表列出了查看 Systrace 報(bào)告時(shí)可以使用的鍵盤快捷鍵:

快捷鍵 說明
W 放大跟蹤時(shí)間軸孽尽。
A 在跟蹤時(shí)間軸上向左平移窖壕。
S 縮小跟蹤時(shí)間軸。
D 在跟蹤時(shí)間軸上向右平移杉女。
E 以當(dāng)前鼠標(biāo)位置為中定位跟蹤時(shí)間軸瞻讽。
M 高亮當(dāng)前選區(qū)。
1 將當(dāng)前正在使用中的選擇模型更改為“選擇”模式熏挎。對(duì)應(yīng)于鼠標(biāo)選擇器工具欄中顯示的第 1 個(gè)按鈕
2 將當(dāng)前正在使用中的選擇模型更改為“平移”模式速勇。對(duì)應(yīng)于鼠標(biāo)選擇器工具欄中顯示的第 2 個(gè)按鈕
3 將當(dāng)前正在使用中的選擇模型更改為“縮放”模式。對(duì)應(yīng)于鼠標(biāo)選擇器工具欄中顯示的第 3 個(gè)按鈕
4 將當(dāng)前正在使用中的選擇模型更改為“計(jì)時(shí)”模式坎拐。對(duì)應(yīng)于鼠標(biāo)選擇器工具欄中顯示的第 4 個(gè)按鈕
G 在當(dāng)前所選任務(wù)的開頭顯示網(wǎng)格烦磁。
Shift + G 在當(dāng)前所選任務(wù)的末尾顯示網(wǎng)格养匈。
向左箭頭 在當(dāng)前選定的時(shí)間軸上選擇上一個(gè)事件。
向右箭頭 在當(dāng)前選定的時(shí)間軸上選擇下一個(gè)事件都伪。
鼠標(biāo)選擇器工具欄

4.5 調(diào)查性能問題

與 Systrace 報(bào)告互動(dòng)時(shí)呕乎,可以檢查記錄期間的設(shè)備 CPU 使用情況。如需瀏覽 HTML 報(bào)告方面的幫助陨晶,請(qǐng)查看鍵盤快捷鍵部分猬仁,或點(diǎn)擊報(bào)告右上角的 ? 按鈕。

以下各部分介紹了如何檢查報(bào)告中的信息以查找和修復(fù)性能問題珍逸。

4.6 識(shí)別性能問題

瀏覽 Systrace 報(bào)告時(shí)逐虚,可以通過執(zhí)行以下一項(xiàng)或多項(xiàng)操作來更輕松地識(shí)別性能問題:

  • 通過在時(shí)間間隔周圍繪制一個(gè)矩形來選擇所需的時(shí)間間隔聋溜。

  • 使用標(biāo)尺工具標(biāo)記或突出顯示問題區(qū)域谆膳。

  • 依次點(diǎn)擊 View Options > Highlight VSync,以顯示每項(xiàng)顯示屏刷新操作撮躁。

4.7 檢查界面幀和提醒

注意:本節(jié)中的內(nèi)容只面向托管代碼漱病,因?yàn)?Systrace 是通過查看系統(tǒng)基于 Java 的 Choreographer 來提供幀信息。如需面向原生代碼(特別是游戲)的指導(dǎo)把曼,請(qǐng)參閱關(guān)于幀速率一致性的討論杨帽。

如所示,Systrace 報(bào)告列出了渲染界面幀的每個(gè)進(jìn)程嗤军,并指明了沿時(shí)間軸渲染的每個(gè)幀注盈。在 16.6 毫秒內(nèi)渲染的必須保持每秒 60 幀穩(wěn)定幀速率的幀會(huì)以綠色圓圈表示。渲染時(shí)間超過 16.6 毫秒的幀會(huì)以黃色或紅色幀圓圈表示

注意:在搭載 Android 5.0(API 級(jí)別 21)或更高版本的設(shè)備上叙赚,渲染幀的工作拆分為界面線程和渲染線程老客。在以前的版本中,創(chuàng)建幀的所有工作都是在界面線程中完成的震叮。

點(diǎn)擊某個(gè)幀圓圈可將其突出顯示胧砰,并提供有關(guān)系統(tǒng)為渲染該幀所做工作的其他信息,包括提醒苇瓣。此報(bào)告還會(huì)顯示系統(tǒng)在渲染該幀時(shí)執(zhí)行的方法尉间。可以調(diào)查這些方法以確定界面卡頓的可能原因击罪。

選擇運(yùn)行速度慢的幀后哲嘲,可能會(huì)在報(bào)告的底部窗格中看到一條提醒。圖中顯示的提醒指明幀的主要問題是在[ListView] 回收和重新綁定上花費(fèi)了太多時(shí)間媳禁。指向跟蹤記錄中相關(guān)事件的鏈接可詳細(xì)說明系統(tǒng)在此期間執(zhí)行的操作撤蚊。

如需查看此工具在的跟蹤記錄中發(fā)現(xiàn)的每條提醒以及設(shè)備觸發(fā)每條提醒的次數(shù),請(qǐng)點(diǎn)擊窗口最右側(cè)的 Alerts 標(biāo)簽頁损话,如圖所示侦啸。Alerts 面板可幫助了解跟蹤記錄中出現(xiàn)的問題以及這些問題導(dǎo)致出現(xiàn)卡頓的頻率槽唾。可以將此面板視為要修正的錯(cuò)誤列表光涂。通常情況下庞萍,只需對(duì)一個(gè)區(qū)域進(jìn)行細(xì)微改動(dòng)或改進(jìn)即可移除整組提醒。

如果發(fā)現(xiàn)在界面線程上執(zhí)行的工作太多忘闻,請(qǐng)使用以下方法之一來幫助確定哪些方法占用了過多的 CPU 時(shí)間:

  • 如果想了解哪些方法可能會(huì)導(dǎo)致瓶頸钝计,請(qǐng)?jiān)谶@些方法中使用TraceCompat添加跟蹤標(biāo)記。具體的使用方式會(huì)在5.使用Systrace實(shí)戰(zhàn) 中介紹齐佳。

  • 如果不確定界面瓶頸的來源私恬,請(qǐng)使用 Android Studio 中提供的CPU profiler×段猓可以生成跟蹤日志本鸣,然后使用 CPU 分析器導(dǎo)入和檢查這些日志。

CPU Profiler 的使用方式可以參考這篇文章硅蹦,APP 性能優(yōu)化與分析CPU篇(一)-CPU Profiler

5. Systrace 實(shí)戰(zhàn)

5.1 應(yīng)用啟動(dòng)耗時(shí)分析

App冷啟動(dòng)耗時(shí)是衡量應(yīng)用啟動(dòng)性能的一個(gè)重要指標(biāo)荣德,獲取App啟動(dòng)耗時(shí)一般分為

  • adb命令獲取

可以獲取到一個(gè)不足夠嚴(yán)謹(jǐn)?shù)膯?dòng)時(shí)間,大部分情況下夠用童芹,但是只能在線下使用涮瞻。

  • 手動(dòng)打點(diǎn)

需要自行應(yīng)用中埋點(diǎn),相對(duì)繁瑣假褪,但是時(shí)間足夠精確署咽,線上、線下都可以使用生音。

  • 利用高速攝影機(jī)宁否,逐幀計(jì)算

需要自己逐幀計(jì)算,而且獲取到的時(shí)間也不是十分精確久锥。但是使用非常方便家淤,只需要一部支持延遲攝影功能的手機(jī)即可(例如iphone),適用于手邊沒有電腦的時(shí)候計(jì)算啟動(dòng)耗時(shí)瑟由。

這里演示在應(yīng)用中埋點(diǎn)絮重,并利用Systrace計(jì)算啟動(dòng)耗時(shí)。在應(yīng)用中埋點(diǎn)歹苦,主要基于TraceCompat類來實(shí)現(xiàn)青伤。TraceCompat API 如下:

方法名 作用
static void beginAsyncSection(String methodName, int cookie) 開始異步追蹤。之后必須使用相同的methodName和cookie調(diào)用endAsyncSection(String,int)殴瘦,結(jié)束這個(gè)追蹤狠角。與beginSection(String)和endSection()不同,異步事件不需要嵌套蚪腋。
static void beginSection(String sectionName) 開始追蹤丰歌。之后必須在同一線程中調(diào)用endSection()結(jié)束追蹤姨蟋。
static void endAsyncSection(String methodName, int cookie) 結(jié)束異步追蹤。
static void endSection() 結(jié)束追蹤立帖。
static boolean isEnabled() 檢查當(dāng)前是否啟用了跟蹤眼溶。這有助于避免為需要格式化的跟蹤節(jié)創(chuàng)建中間字符串。沒有必要保護(hù)所有跟蹤方法調(diào)用晓勇,因?yàn)樗鼈冊(cè)趦?nèi)部已經(jīng)檢查了這一點(diǎn)堂飞。但是,建議使用此選項(xiàng)來防止創(chuàng)建任何臨時(shí)對(duì)象绑咱,這些臨時(shí)對(duì)象在未啟用跟蹤時(shí)會(huì)傳遞給這些方法以降低運(yùn)行時(shí)成本绰筛。
static void setCounter(String counterName, int counterValue) 寫入跟蹤消息以指示給定計(jì)數(shù)器的值。
  1. 在應(yīng)用代碼中設(shè)置埋點(diǎn)描融。
public class JniApp extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // APP 啟動(dòng) 埋點(diǎn)
        TraceCompat.beginAsyncSection("JNI-app-start",10);
    }
}


public class MainActivity extends AppCompatActivity {
...

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        // MainActivity 首幀繪制結(jié)束后添加埋點(diǎn)
        TraceCompat.endAsyncSection("JNI-app-start",10);
    }

...
}

注意:認(rèn)為Activity的首幀繪制完畢就是APP啟動(dòng)完畢的情況僅限于首頁相對(duì)簡(jiǎn)單的情況铝噩,多數(shù)情況也確實(shí)如此。但是如果開屏頁很復(fù)雜稼稿,應(yīng)該將開屏頁最后一個(gè)組件繪制結(jié)束作為應(yīng)用啟動(dòng)完畢的信號(hào)薄榛。示例如下:

xxxView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    @Override
    public boolean onPreDraw() {
        TraceCompat.endAsyncSection("JNI-app-start",10);
        return true;
    }
});

  1. 在命令行運(yùn)行Systrace指令讳窟,并指定應(yīng)用的包名
st -a com.android.car.demo

得到如下的報(bào)告

  1. 選擇應(yīng)用的包名让歼,過濾掉不需要的進(jìn)程。
  1. 檢索我們?cè)O(shè)定的標(biāo)簽丽啡,點(diǎn)擊 報(bào)告中-> 切換到自定義事件谋右。
  1. 按下 m 鍵,鎖定事件补箍。

從上圖就可以看出改执,整個(gè)JNI-app-start事件總共耗時(shí) 2.07s,而這就是應(yīng)用的啟動(dòng)耗時(shí)坑雅。

如果想進(jìn)一步分析為何啟動(dòng)耗時(shí)如此之長(zhǎng)辈挂,需要繼續(xù)在可疑的地方埋點(diǎn),逐一排查裹粤。如下所示:


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 第一處 可疑點(diǎn)终蒂,布局加載耗時(shí)過長(zhǎng)?
    TraceCompat.beginSection("JNI-layout");
    binding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());
    TraceCompat.endSection();

    // 第二處 可疑點(diǎn)遥诉,初始化耗時(shí)過長(zhǎng)拇泣?
    TraceCompat.beginSection("JNI-init");
    initSomeThing();
    TraceCompat.endSection();

    TextView tv = binding.sampleText;

    // 第三處 可疑點(diǎn),JNI方法返回值耗時(shí)過長(zhǎng)矮锈?
    TraceCompat.beginSection("JNI-txt");
    String txt = stringFromJNI();
    TraceCompat.endSection();

    tv.setText(txt);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末霉翔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子苞笨,更是在濱河造成了極大的恐慌债朵,老刑警劉巖子眶,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異序芦,居然都是意外死亡壹店,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門芝加,熙熙樓的掌柜王于貴愁眉苦臉地迎上來硅卢,“玉大人,你說我怎么就攤上這事藏杖〗埽” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵蝌麸,是天一觀的道長(zhǎng)点寥。 經(jīng)常有香客問我,道長(zhǎng)来吩,這世上最難降的妖魔是什么敢辩? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮弟疆,結(jié)果婚禮上戚长,老公的妹妹穿的比我還像新娘。我一直安慰自己怠苔,他們只是感情好同廉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著柑司,像睡著了一般迫肖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攒驰,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天蟆湖,我揣著相機(jī)與錄音,去河邊找鬼玻粪。 笑死隅津,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奶段。 我是一名探鬼主播饥瓷,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼痹籍!你這毒婦竟也來了呢铆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤蹲缠,失蹤者是張志新(化名)和其女友劉穎棺克,沒想到半個(gè)月后悠垛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡娜谊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年确买,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纱皆。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡湾趾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出派草,到底是詐尸還是另有隱情搀缠,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布近迁,位于F島的核電站艺普,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鉴竭。R本人自食惡果不足惜歧譬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搏存。 院中可真熱鬧瑰步,春花似錦、人聲如沸祭埂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛆橡。三九已至,卻和暖如春掘譬,著一層夾襖步出監(jiān)牢的瞬間泰演,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工葱轩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睦焕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓靴拱,卻偏偏與公主長(zhǎng)得像垃喊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子袜炕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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