Android性能優(yōu)化之CPU Profiler

低性能的APP常見(jiàn)的表現(xiàn)有啟動(dòng)/界面切換慢洪灯、動(dòng)畫掉幀坎缭、卡頓、耗電签钩,甚至出現(xiàn)應(yīng)用無(wú)響應(yīng)掏呼、程序崩潰的現(xiàn)象。當(dāng)我們著手解決這些性能問(wèn)題時(shí)铅檩,面對(duì)的第一個(gè)問(wèn)題就是需要找到合適的工具來(lái)檢測(cè)這些問(wèn)題憎夷,用肉眼觀察來(lái)判斷定位這類問(wèn)題是不靠譜的。理想的檢測(cè)工具要能做到兩點(diǎn):

  1. 一是可以定性的告訴我們應(yīng)用是否有低性能問(wèn)題昧旨,并且能定位到的點(diǎn)拾给,指出哪個(gè)邏輯哪個(gè)方法使用系統(tǒng)資源低效,以便我們針對(duì)具體的問(wèn)題給出對(duì)應(yīng)的優(yōu)化方案兔沃;
  2. 二是能定量說(shuō)明問(wèn)題點(diǎn)的嚴(yán)重程度蒋得,有具體的數(shù)字來(lái)衡量,這樣我們對(duì)比優(yōu)化前后的測(cè)量數(shù)據(jù)乒疏,就可以清晰地看到優(yōu)化方案的收益和效果额衙。
Android Profiler

為了滿足上面兩個(gè)需求,我們需要使用到systraceCPU Profiler這兩個(gè)檢測(cè)工具缰雇。

工具一:systrace
這個(gè)工具的作用從名字‘system trace’系統(tǒng)跟蹤就能看出一二入偷。我們主要是通過(guò)這個(gè)工具來(lái)記錄分析系統(tǒng)級(jí)函數(shù)的執(zhí)行情況。它從android內(nèi)核收集CPU調(diào)度械哟、存儲(chǔ)器訪問(wèn)疏之、應(yīng)用線程等信息,生成一張html格式的報(bào)表暇咆。這個(gè)工具還會(huì)自動(dòng)分析這些數(shù)據(jù)锋爪,高亮警示開(kāi)發(fā)者注意這些可能有問(wèn)題的地方。比如下圖UI掉幀的問(wèn)題爸业。但是systrace只提供了系統(tǒng)方法調(diào)用信息其骄,沒(méi)有指明具體是因?yàn)檎{(diào)用我們APP程序哪個(gè)方法導(dǎo)致的,從systrace中只能定位出大概是在首個(gè)Activity創(chuàng)建的時(shí)候發(fā)生的扯旷。想要獲取關(guān)于APP執(zhí)行的詳細(xì)信息就得使用今天的主角CPU Profiler了拯爽。

systrace

點(diǎn)擊查看systrace更多詳情。

工具二:CPU Profiler
CPU Profiler 可實(shí)時(shí)檢查應(yīng)用的 CPU 使用率和線程運(yùn)行情況钧忽,并記錄函數(shù)跟蹤毯炮,以便我們優(yōu)化和調(diào)試相關(guān)代碼逼肯。簡(jiǎn)單點(diǎn)說(shuō)就是我們可以通過(guò)CPU Profiler查看應(yīng)用在某段時(shí)間里某個(gè)線程執(zhí)行了哪些方法,并且還定量的展示了執(zhí)行這些方法所耗費(fèi)的時(shí)間及其方法的調(diào)用堆棧桃煎。稍有經(jīng)驗(yàn)的程序員都知道應(yīng)用啟動(dòng)慢篮幢、界面切換慢、動(dòng)畫不流暢卡頓等類似問(wèn)題基本都是UI刷新不及時(shí)的表現(xiàn)为迈,UI刷新不及時(shí)就是因?yàn)閁I線程被其他邏輯方法長(zhǎng)時(shí)間占用導(dǎo)致三椿。吶,CPU Profiler簡(jiǎn)直就是為了解決這個(gè)問(wèn)題而生的葫辐,輕松的分析出在卡頓(或者其他)過(guò)程中主線程都執(zhí)行了哪些耗時(shí)操作搜锰。

Google官方提供的Android開(kāi)發(fā)工具Android Studio附帶了很多開(kāi)發(fā)調(diào)試工具,這其中就包括了一系列的性能分析工具另患。在Android Studio 3.0之前這些工具叫Android Monitor tools纽乱,Android Studio 3.0開(kāi)始成為Android Profiler tools。我現(xiàn)在使用的Android Studio版本是3.2.1昆箕,這篇文章主要介紹的是3.2.1版本Android Profiler tools中的CPU Profiler - CPU分析器鸦列。下面我們來(lái)看下CPU Profiler的使用方法。

一鹏倘、CPU Profiler概覽

1薯嗤、打開(kāi)CPU Profile界面
  1. 點(diǎn)擊 View > Tool Windows > Android Profiler(也可以點(diǎn)擊工具欄中的 Android Profiler )。
  2. 在 Android Profiler 工具欄中點(diǎn)擊“+”號(hào)選擇您想要分析的設(shè)備和應(yīng)用進(jìn)程纤泵。 如果您通過(guò) USB 連接了某個(gè)設(shè)備但該設(shè)備未在設(shè)備列表中列出栋烤,請(qǐng)確保您已啟用 USB 調(diào)試砰盐。
  3. 點(diǎn)擊 CPU 時(shí)間線中的任意位置即可打開(kāi) CPU Profiler。Android Profiler 界面是CPU、內(nèi)存亏推、網(wǎng)絡(luò)阐污、電量4項(xiàng)性能數(shù)據(jù)共享時(shí)間線視圖叔遂,此共享時(shí)間線視圖只顯示時(shí)間線圖表微渠。 要詳細(xì)分析,需要點(diǎn)擊性能數(shù)據(jù)對(duì)應(yīng)的圖表循狰,打開(kāi)詳情視圖窟社。
Android Profiler 共享時(shí)間線視圖

打開(kāi) CPU Profiler 后,可以看到類似下圖的一些內(nèi)容绪钥。它將立即開(kāi)始顯示應(yīng)用的 CPU 使用率和線程 Activity灿里。

CPU Profiler
  1. Event 時(shí)間線: 顯示應(yīng)用中在其生命周期不同狀態(tài)間轉(zhuǎn)換的 Activity,并表明用戶與設(shè)備的交互程腹,包括觸摸事件匣吊、按鍵點(diǎn)擊的事件。 如需了解有關(guān) Event 時(shí)間線的更多信息,包括如何啟用它色鸳,請(qǐng)閱讀 啟用高級(jí)分析侣灶。

  2. CPU 時(shí)間線: 顯示應(yīng)用的實(shí)時(shí) CPU 使用率(以占總可用 CPU 時(shí)間的百分比表示)以及應(yīng)用使用的總線程數(shù)。 此時(shí)間線還顯示其他進(jìn)程的 CPU 使用率(如系統(tǒng)進(jìn)程或其他應(yīng)用)缕碎,以便您可以將其與您的應(yīng)用使用率進(jìn)行對(duì)比。 通過(guò)沿時(shí)間線的水平軸移動(dòng)鼠標(biāo)池户,您還可以檢查歷史 CPU 使用率數(shù)據(jù)咏雌。

  3. 線程活動(dòng)時(shí)間線: 列出屬于應(yīng)用進(jìn)程的每個(gè)線程并使用下面列出的顏色沿時(shí)間線標(biāo)示它們的狀態(tài)。 在記錄一個(gè)函數(shù)跟蹤后校焦,可以從此時(shí)間線中選擇一個(gè)線程以在跟蹤窗格中檢查其數(shù)據(jù)赊抖。

    • 綠色區(qū)域: 表示線程處于活動(dòng)狀態(tài)或準(zhǔn)備使用 CPU。 即寨典,它正在“運(yùn)行中”或處于“可運(yùn)行”狀態(tài)氛雪。
    • 黃色區(qū)域: 表示線程處于活動(dòng)狀態(tài),但它正在等待一個(gè) I/O 操作(如磁盤或網(wǎng)絡(luò) I/O)耸成,然后才能完成它的工作报亩。
    • 灰色區(qū)域: 表示線程正在休眠且沒(méi)有消耗任何 CPU 時(shí)間。 當(dāng)線程需要訪問(wèn)尚不可用的資源時(shí)偶爾會(huì)發(fā)生這種情況井氢。 線程進(jìn)入自主休眠或內(nèi)核將此線程置于休眠狀態(tài)弦追,直到所需的資源可用。
  4. Record按鈕:現(xiàn)在當(dāng)我們與應(yīng)用交互時(shí)花竞,可以通過(guò) CPU Profiler 監(jiān)控 CPU 使用率和線程狀態(tài)了劲件。 不過(guò),如想要了解應(yīng)用執(zhí)行代碼的詳細(xì)信息约急, 我們需要記錄和檢查函數(shù)跟蹤零远。

2、記錄和檢查函數(shù)跟蹤

要開(kāi)始記錄函數(shù)跟蹤厌蔽,從下拉菜單中選擇 SampledInstrumented 記錄配置牵辣,或選擇您創(chuàng)建的自定義記錄配置,然后點(diǎn)擊 Record 躺枕。 與應(yīng)用交互并在完成后點(diǎn)擊 Stop recording服猪。 分析器將自動(dòng)選擇記錄的時(shí)間范圍,并默認(rèn)在函數(shù)跟蹤窗格中顯示主線程函數(shù)跟蹤信息拐云,如下圖所示罢猪。如果您想檢查另一個(gè)線程的函數(shù)跟蹤,只需從線程活動(dòng)時(shí)間線中選中它叉瘩,函數(shù)跟蹤窗格就會(huì)切換成所選線程的函數(shù)跟蹤信息膳帕。

跟蹤函數(shù)

  1. 選擇時(shí)間范圍: 用于確定您要在跟蹤窗格中檢查所記錄時(shí)間范圍的哪一部分。 當(dāng)您首次記錄函數(shù)跟蹤時(shí),CPU Profiler 將在 CPU 時(shí)間線中自動(dòng)選擇您的記錄的完整長(zhǎng)度危彩。 如果您想僅檢查所記錄時(shí)間范圍一小部分的函數(shù)跟蹤數(shù)據(jù)攒磨,您可以點(diǎn)擊并拖動(dòng)突出顯示的區(qū)域邊緣以修改其長(zhǎng)度。
  2. 時(shí)間戳: 用于表示所記錄函數(shù)跟蹤的開(kāi)始和結(jié)束時(shí)間(相對(duì)于分析器從設(shè)備開(kāi)始收集 CPU 使用率信息的時(shí)間)汤徽。 在選擇時(shí)間范圍時(shí)娩缰,您可以點(diǎn)擊時(shí)間戳以自動(dòng)選擇完整記錄,如果您有多個(gè)要進(jìn)行切換的記錄谒府,則此做法尤其有用拼坎。
  3. 跟蹤窗格: 用于顯示您所選的時(shí)間范圍和線程的函數(shù)跟蹤數(shù)據(jù)。 僅在您至少記錄一個(gè)函數(shù)跟蹤后此窗格才會(huì)顯示完疫。 在此窗格中泰鸡,您可以選擇想如何查看每個(gè)堆疊追蹤(使用跟蹤標(biāo)簽),以及如何測(cè)量執(zhí)行時(shí)間(使用時(shí)間引用下拉菜單)壳鹤。
  4. 選擇后盛龄,可通過(guò) Top Down 樹(shù)、Bottom Up 樹(shù)芳誓、調(diào)用圖表或火焰圖的形式顯示您的函數(shù)跟蹤余舶。 您可以在下文中了解每個(gè)跟蹤窗格標(biāo)簽的更多信息。
  5. 從下拉菜單中選擇以下選項(xiàng)之一兆沙,以確定如何測(cè)量每個(gè)函數(shù)調(diào)用的時(shí)間信息:
    • Wall clock time:壁鐘時(shí)間表示實(shí)際經(jīng)過(guò)的時(shí)間欧芽。
    • Thread time:線程時(shí)間 = 實(shí)際經(jīng)過(guò)的時(shí)間 - 線程未消耗 CPU 資源的時(shí)間。 對(duì)于任何給定函數(shù)葛圃,其線程時(shí)間始終少于或等于其壁鐘時(shí)間千扔。 線程時(shí)間可以更好地了解到線程的實(shí)際 CPU 使用率中有多少是給定函數(shù)消耗的。

二库正、CPU Profiler 使用示例

上面把 CPU Profiler 工具的基本界面介紹了一下曲楚。下面我們通過(guò)兩個(gè)例子來(lái)進(jìn)一步了解下 CPU Profiler 的用法。

示例1:界面切換卡頓

問(wèn)題:首次打開(kāi)播放頁(yè)時(shí)界面卡頓褥符,待優(yōu)化龙誊。
分析:界面卡頓,應(yīng)該數(shù)主線有耗時(shí)操作導(dǎo)致UI刷新不及時(shí)喷楣。所以我們是用CPU Profiler來(lái)定位問(wèn)題趟大。

  1. AS(Android Studio)連接上手機(jī),手機(jī)上運(yùn)行要分析APP來(lái)到MainActivity铣焊,再在AS的Profiler窗口選擇要調(diào)試的進(jìn)程逊朽,打開(kāi)CPU Profiler。
  2. 然后在AS上點(diǎn)擊 Record 曲伊,再在手機(jī)上操作跳轉(zhuǎn)到PlayerActivity完成后點(diǎn)擊 Stop recording叽讳。得到如下圖所示信息。
  3. 仔細(xì)查看主線程Call Chart信息,發(fā)現(xiàn)播放頁(yè)的onCreate()里的MultiscreenManager.init();耗用了絕大多數(shù)時(shí)間岛蚤。仔細(xì)查看這一方法作用是初始化投屏相關(guān)功能邑狸。(初始話方法的具體邏輯去掉了,調(diào)用了sleep方法來(lái)模擬)

Call Chart 標(biāo)簽提供函數(shù)跟蹤的圖形表示形式涤妒,其中单雾,水平軸表示函數(shù)耗費(fèi)的時(shí)間,垂直軸顯示其被調(diào)用者她紫。 對(duì)系統(tǒng) API 的函數(shù)調(diào)用顯示為橙色铁坎,對(duì)應(yīng)用自有函數(shù)的調(diào)用顯示為綠色,對(duì)第三方 API(包括 Java 語(yǔ)言 API)的函數(shù)調(diào)用顯示為藍(lán)色犁苏。

播放頁(yè)啟動(dòng)函數(shù)調(diào)用圖

解決方案:問(wèn)題找到了解決就很容易了,投屏功能不是播放頁(yè)啟動(dòng)的必須初始化項(xiàng)目扩所,但是如果后置到用戶點(diǎn)擊投屏功能以后再去初始化投屏SDK围详,則會(huì)影響投屏功能的用戶體驗(yàn)。這種問(wèn)題有一個(gè)國(guó)際標(biāo)準(zhǔn)解決方案祖屏,把該任務(wù)添加到閑時(shí)任務(wù)系統(tǒng)中去助赞。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_player);

    Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
        @Override
        public boolean queueIdle() {
            MultiscreenManager.init();
            return false;
        }
    });
}

CPU Profiler 檢測(cè)時(shí)測(cè)量的函數(shù)耗時(shí)會(huì)大于真正線上包運(yùn)行的時(shí)間。一方面是函數(shù)跟蹤工具會(huì)加入額外的計(jì)時(shí)邏輯袁勺,另一方面它還會(huì)關(guān)閉虛擬機(jī)的JIT功能雹食。所以我們一般是對(duì)比優(yōu)化前后測(cè)量的兩組數(shù)據(jù)來(lái)判斷優(yōu)化的效果。

修改后再測(cè)試下數(shù)據(jù)期丰,onCreate()方法耗時(shí)明顯降低群叶,投屏sdk初始化邏輯放在主線程空閑的時(shí)候去執(zhí)行的。還有一點(diǎn)注意下钝荡,可能出現(xiàn)從播放頁(yè)打開(kāi)到用戶請(qǐng)求投屏?xí)r街立,主線程一直不空閑,也就是我們的初始化任務(wù)沒(méi)有執(zhí)行情況埠通。所以加到閑時(shí)任務(wù)系統(tǒng)中的任務(wù)還得具備一個(gè)特點(diǎn)赎离,就是如果顯示任務(wù)沒(méi)有執(zhí)行,后續(xù)邏輯也要能正常運(yùn)行端辱。不過(guò)這個(gè)問(wèn)題也很容易解決梁剔,就是在后續(xù)邏輯執(zhí)行前先判斷下是否初始化了。

優(yōu)化后數(shù)據(jù)

示例2:應(yīng)用冷啟動(dòng)慢

問(wèn)題:殺掉進(jìn)程后舞蔽,再次啟動(dòng)應(yīng)用慢荣病,待優(yōu)化。
分析:有了上面的經(jīng)驗(yàn)喷鸽,分析這個(gè)問(wèn)題也一樣众雷,先打開(kāi)APP,選擇要調(diào)試的進(jìn)程,點(diǎn)擊record按鈕跟蹤卡頓過(guò)程中函數(shù)調(diào)用信息砾省。好了鸡岗,問(wèn)題來(lái)了,我們這里是要抓取應(yīng)用冷啟動(dòng)過(guò)程函數(shù)調(diào)用信息编兄,但是要用CPU Profiler工具抓取信息得先指定進(jìn)程轩性。應(yīng)用啟動(dòng)前又沒(méi)有進(jìn)程信息可以指定。愁狠鸳,撓頭揣苏,程序員的頭就是這么給撓禿頂?shù)摹?/p>

這個(gè)時(shí)候就該Debug 類出場(chǎng)了。我們可使用 Debug 類精確地控制設(shè)備何時(shí)開(kāi)始和停止記錄函數(shù)跟蹤信息件舵,來(lái)生成一份函數(shù)跟蹤信息文件卸察。然后再使用 Android Studio 或 Traceview 查看各個(gè)跟蹤日志。

Traceview 有點(diǎn)過(guò)時(shí)了铅祸。如果我們使用的是3.2及其更新的Android Studio坑质,就沒(méi)有必要用Traceview了。

在開(kāi)始生成跟蹤日志之前临梗,要確保應(yīng)用有權(quán)限寫入外部存儲(chǔ)WRITE_EXTERNAL_STORAGE涡扼,以便將跟蹤日志保存至該設(shè)備。創(chuàng)建跟蹤日志盟庞,在想系統(tǒng)開(kāi)始記錄跟蹤數(shù)據(jù)的位置調(diào)用 Debug.startMethodTracing()吃沪,要停止跟蹤的位置請(qǐng)調(diào)用 Debug.stopMethodTracing()。系統(tǒng)將在getExternalFilesDir() 目錄下生成 .trace 文件什猖,一般都在 ~/sdcard/Android/data/$packname/files 目錄中票彪。用Android Studio的Device File Explorer工具找到這個(gè)文件雙擊即可打開(kāi)。

public class DymApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        SimpleDateFormat date = new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss");
        String logDate = date.format(new Date());
        
        // 在Application創(chuàng)建的時(shí)候開(kāi)始函數(shù)跟蹤
        // 傳入的參數(shù)是函數(shù)跟蹤信息文件名不狮,加時(shí)間戳保證文件不會(huì)被覆蓋
        Debug.startMethodTracing("sample-" + logDate);
    }
}

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        try {
            // TODO: 2018/12/7 怎么又是這個(gè)倒霉的sleep抹镊,為了測(cè)試APP啟動(dòng)卡頓問(wèn)題
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 在首頁(yè)Activity創(chuàng)建完成停止函數(shù)跟蹤
        Debug.stopMethodTracing();
    }
}

函數(shù)跟蹤日志生成了,分析就和之前沒(méi)什么兩樣了荤傲。

CPU Profiler 中還有一些信息也是很有用的垮耳,比如Top Down 和 Bottom Up ,這里沒(méi)有講到遂黍,大家可以自己去看下终佛,有什么不明白的,也可以在下面留言討論雾家。

三铃彰、結(jié)束

總的來(lái)說(shuō)就是 CPU Profiler 可以讓我們查看應(yīng)用進(jìn)程中的每個(gè)線程,某段時(shí)間內(nèi)執(zhí)行了哪些函數(shù)芯咧,以及在其執(zhí)行期間每個(gè)函數(shù)消耗的 CPU 資源(文章中耗時(shí)只得就是占用CPU的時(shí)間)牙捉。 還可以使用函數(shù)跟蹤來(lái)識(shí)別調(diào)用方被調(diào)用方竹揍。 據(jù)此可以確定哪些函數(shù)負(fù)責(zé)調(diào)用常常會(huì)消耗大量特定資源的任務(wù),并嘗試優(yōu)化應(yīng)用代碼以避免不必要的開(kāi)支邪铲。

大家努力芬位,最大限度減少應(yīng)用的 CPU 使用率,向德芙巧克力一樣带到,在各種新舊設(shè)備上都能提供縱享絲滑的用戶體驗(yàn)昧碉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揽惹,隨后出現(xiàn)的幾起案子被饿,更是在濱河造成了極大的恐慌,老刑警劉巖搪搏,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狭握,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡疯溺,警方通過(guò)查閱死者的電腦和手機(jī)哥牍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喝检,“玉大人,你說(shuō)我怎么就攤上這事撼泛∧铀担” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵愿题,是天一觀的道長(zhǎng)损俭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)潘酗,這世上最難降的妖魔是什么杆兵? 我笑而不...
    開(kāi)封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮仔夺,結(jié)果婚禮上琐脏,老公的妹妹穿的比我還像新娘。我一直安慰自己缸兔,他們只是感情好日裙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著惰蜜,像睡著了一般昂拂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抛猖,一...
    開(kāi)封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天格侯,我揣著相機(jī)與錄音鼻听,去河邊找鬼。 笑死联四,一個(gè)胖子當(dāng)著我的面吹牛撑碴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碎连,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼灰羽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鱼辙?” 一聲冷哼從身側(cè)響起廉嚼,我...
    開(kāi)封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倒戏,沒(méi)想到半個(gè)月后怠噪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杜跷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年傍念,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葛闷。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡憋槐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淑趾,到底是詐尸還是另有隱情阳仔,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布扣泊,位于F島的核電站近范,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏延蟹。R本人自食惡果不足惜评矩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阱飘。 院中可真熱鬧斥杜,春花似錦、人聲如沸沥匈。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咐熙。三九已至弱恒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棋恼,已是汗流浹背返弹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工锈玉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人义起。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓拉背,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親默终。 傳聞我的和親對(duì)象是個(gè)殘疾皇子椅棺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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