HarmonyOS之ArkTS高性能編程實(shí)踐

概述

本文參考業(yè)界標(biāo)準(zhǔn)力麸,并結(jié)合應(yīng)用TS&JS部分的性能優(yōu)化實(shí)踐經(jīng)驗(yàn),從應(yīng)用編程指南拣挪、高性能編程實(shí)踐、性能優(yōu)化調(diào)試工具等維度俱诸,為應(yīng)用開發(fā)者提供參考指導(dǎo)菠劝,助力開發(fā)者開發(fā)出高性能的應(yīng)用。

應(yīng)用TS&JS高性能編程實(shí)踐

高性能編程實(shí)踐乙埃,是在開發(fā)過程中逐步總結(jié)出來的一些高性能的寫法和建議闸英,在業(yè)務(wù)功能實(shí)現(xiàn)過程中,我們要同步思考并理解高性能寫法的原理介袜,運(yùn)用到代碼邏輯實(shí)現(xiàn)中甫何。

本文中的實(shí)踐示例代碼,會(huì)統(tǒng)一標(biāo)注正例或者反例遇伞,正例為推薦寫法辙喂,反例為不推薦寫法。

屬性訪問與屬性增刪

熱點(diǎn)循環(huán)中常量提取鸠珠,減少屬性訪問次數(shù)

在實(shí)際的應(yīng)用場(chǎng)景中抽離出來如下用例巍耗,其在循環(huán)中會(huì)大量進(jìn)行一些常量的訪問操作,該常量在循環(huán)中不會(huì)改變渐排,可以提取到循環(huán)外部炬太,減少屬性訪問的次數(shù)。

【反例】

// 優(yōu)化前代碼
private getDay(year: number): number {
  /* Year has (12 * 29 =) 348 days at least */
  let totalDays: number = 348;
  for (let index: number = 0x8000; index > 0x8; index >>= 1) {
    // 此處會(huì)多次對(duì)Time的INFO及START進(jìn)行查找驯耻,并且每次查找出來的值是相同的
    totalDays += ((Time.INFO[year- Time.START] & index) !== 0) ? 1 : 0;
  }
  return totalDays + this.getDays(year);
}

可以將Time.INFO[year - Time.START]進(jìn)行熱點(diǎn)函數(shù)常量提取操作亲族,這樣可以大幅減少屬性的訪問次數(shù),性能收益明顯可缚。

【正例】

// 優(yōu)化后代碼
private getDay(year: number): number {
  /* Year has (12 * 29 =) 348 days at least */
  let totalDays: number = 348;
  const info = Time.INFO[year - Time.START]; // 1. 從循環(huán)中提取不變量
  for (let index: number = 0x8000; index > 0x8; index >>= 1) {
    if ((info & index) !== 0) {
      totalDays++;
    }
  }
  return totalDays + this.getDays(year);
}

避免頻繁使用delete

delete對(duì)象的某一個(gè)屬性會(huì)改變其布局霎迫,影響運(yùn)行時(shí)優(yōu)化效果,導(dǎo)致執(zhí)行性能下降帘靡。

說明:

不建議直接使用delete刪除對(duì)象的任何屬性知给,如果有需要,建議使用map和set或者引擎實(shí)現(xiàn)的高性能容器類

【反例】

class O1 {
  x: string | undefined = "";
  y: string | undefined = "";
}
let obj: O1 = {x: "", y: ""};

obj.x = "xxx";
obj.y = "yyy";
delete obj.x;

建議使用如下兩種寫法之一實(shí)現(xiàn)屬性的增刪涩赢。

【正例】

// 例1:將Object中不再使用的屬性設(shè)置為null
class O1 {
  x: string | null = "";
  y: string | null = "";
}
let obj: O1 = {x: "", y: ""};

obj.x = "xxx";
obj.y = "yyy";
obj.x = null;

// 例2:使用高性能容器類操作屬性
import HashMap from '@ohos.util.HashMap'; 
let myMap= new HashMap();

myMap.set("x", "xxx");
myMap.set("y", "yyy");
myMap.remove("x");

數(shù)值計(jì)算

數(shù)值計(jì)算避免溢出

常見的可能導(dǎo)致溢出的數(shù)值計(jì)算包括如下場(chǎng)景戈次,溢出之后,會(huì)導(dǎo)致引擎走入慢速的溢出邏輯分支處理筒扒,影響后續(xù)的性能朝扼。

  • 針對(duì)加法、減法霎肯、乘法、指數(shù)運(yùn)算等運(yùn)算操作榛斯,應(yīng)避免數(shù)值大于INT32_MAX或小于INT32_MIN观游,否則會(huì)導(dǎo)致int溢出。

  • 針對(duì)&(and)驮俗、>>>(無符號(hào)右移)等運(yùn)算操作懂缕,應(yīng)避免數(shù)值大于INT32_MAX,否則會(huì)導(dǎo)致int溢出王凑。

數(shù)據(jù)結(jié)構(gòu)

使用合適的數(shù)據(jù)結(jié)構(gòu)

在實(shí)際的應(yīng)用場(chǎng)景中抽離出來如下用例搪柑,該接口中使用JS Object來作為容器去處理Map的邏輯,建議使用HashMap來進(jìn)行處理索烹。

【反例】

getInfo(t1, t2) {
  if (!this.check(t1, t2)) {
    return "";
  }
  // 此處使用JS Object作為容器
  let info= {};  
  this.setInfo(info);
  let t1= info[t2];
  return (t1!= null) ? t1: "";
}
setInfo(info) {
  // 接口內(nèi)部實(shí)際上進(jìn)行的是map的操作
  info[T1] = '七六';   
  info[T2] = '九一';
  ... ...
  info[T3] = '十二';
}

代碼可以進(jìn)行如下修改工碾,除了使用引擎中提供的標(biāo)準(zhǔn)內(nèi)置map之外,還可以使用ArkTS提供的高性能容器類百姓。

【正例】

import HashMap from '@ohos.util.HashMap'; 

getInfo(t1, t2) {
  if (!this.check(t1, t2)) {
    return "";
  }
  // 此處替換為HashMap作為容器
  let info= new HashMap();
  this.setInfo(info);
  let t1= info.get(t2);
  return (t1!= null) ? t1: "";
}
setInfo(info) {
  // 接口內(nèi)部實(shí)際上進(jìn)行的是map的操作
  info.set(T1, '七六');   
  info.set(T2, '九一');
  ... ...
  info.set(T3, '十二');
}

數(shù)值數(shù)組推薦使用TypedArray

如果是涉及純數(shù)值計(jì)算的場(chǎng)合渊额,推薦使用TypedArray數(shù)據(jù)結(jié)構(gòu)。

常見的TypedArray包括:Int8Array垒拢、Uint8Array旬迹、Uint8ClampedArray、Int16Array求类、Uint16Array奔垦、Int32Array、Uint32Array尸疆、Float32Array椿猎、Float64Array、BigInt64Array仓技、BigUint64Array鸵贬。

【正例】

const typedArray1 = new Int8Array([1, 2, 3]);  // 針對(duì)這一場(chǎng)景,建議不要使用new Array([1, 2, 3])
const typedArray2 = new Int8Array([4, 5, 6]);  // 針對(duì)這一場(chǎng)景脖捻,建議不要使用new Array([4, 5, 6])
let res = new Int8Array(3);
for (let i = 0; i < 3; i++) {
  res[i] = typedArray1[i] + typedArray2[i];
}

避免使用稀疏數(shù)組

分配數(shù)組時(shí)阔逼,應(yīng)避免其大小超過1024或形成稀疏數(shù)組。

虛擬機(jī)在分配超過1024大小的數(shù)組或者針對(duì)稀疏數(shù)組地沮,均采用hash表來存儲(chǔ)元素嗜浮,相對(duì)使用偏移來訪問數(shù)組元素速度較慢羡亩。

在開發(fā)時(shí),盡量避免數(shù)組變成稀疏數(shù)組危融。

【反例】

// 如下幾種情形會(huì)變成稀疏數(shù)組
// 1. 直接分配100000大小的數(shù)組畏铆,虛擬機(jī)會(huì)處理成用hash表來存儲(chǔ)元素
let count = 100000;
let result: number[] = new Array(count);

// 2. 分配數(shù)組之后直接,在9999處初始化吉殃,會(huì)變成稀疏數(shù)組
let result: number[] = new Array();
result[9999] = 0;

// 3. 刪除數(shù)組的element屬性辞居,虛擬機(jī)也會(huì)處理成用hash表來存儲(chǔ)元素
let result = [0, 1, 2, 3, 4];
delete result[0];

對(duì)象初始化

使用字面量進(jìn)行對(duì)象創(chuàng)建

通常在代碼中,進(jìn)行一些對(duì)象創(chuàng)建的時(shí)候蛋勺,大家會(huì)采用動(dòng)態(tài)添加屬性方式瓦灶,這種方式,在前端解析時(shí)抱完,不能獲取到更多的信息贼陶,因此不能為運(yùn)行時(shí)提供優(yōu)化信息。

【反例】

let arr = new Array();  // 創(chuàng)建一個(gè)array

let obj = new Object();  // 創(chuàng)建一個(gè)普通對(duì)象

let oFruit = new Object();
oFruit.color = "red";
oFruit.name = "apple"; // 創(chuàng)建一個(gè)對(duì)象巧娱,并設(shè)置屬性

在要求性能的場(chǎng)合碉怔,可以使用字面量進(jìn)行對(duì)象創(chuàng)建,這樣在運(yùn)行時(shí)可以獲得指令級(jí)別的優(yōu)化禁添。

【正例】

let arr = [];  // 創(chuàng)建一個(gè)array

let obj = {}; // 創(chuàng)建一個(gè)普通對(duì)象

class O1 {
  color: string = "";
  name: string = "";
}
let oFruit: O1 = {color: "red", name: "apple"};  // 創(chuàng)建一個(gè)對(duì)象撮胧,并設(shè)置屬性

對(duì)象構(gòu)造初始化

對(duì)象構(gòu)造的時(shí)候,要提供默認(rèn)值初始化老翘,不要訪問未初始化的屬性趴樱。

【反例】

// 不要訪問未初始化的屬性
class A {
  x: number;
}

// 構(gòu)造函數(shù)中要對(duì)屬性進(jìn)行初始化
class A {
  x: number;
  constructor() {
  }
}

let a = new A();
// x使用時(shí)還未賦值,這種情況會(huì)訪問整個(gè)原型鏈
print(a.x);

【正例】

// 推薦一:聲明初始化
class A {
  x: number = 0;
}

// 推薦二:構(gòu)造函數(shù)直接賦初值
class A {
  constructor() {
    this.x = 0;
  }
}

let a = new A();
print(a.x);

number正確初始化

針對(duì)number類型酪捡,編譯器在優(yōu)化時(shí)會(huì)區(qū)分整型和浮點(diǎn)類型叁征。開發(fā)者在初始化時(shí)如果預(yù)期是整型就初始化成0,如果預(yù)期是浮點(diǎn)型就初始化為0.0逛薇,不要把一個(gè)number類型初始化成undefined或者null捺疼。

【正例】

function foo(d: number) : number {
  // 變量i預(yù)期是整型,不要聲明成undefined/null或0.0永罚,直接初始化為0
  let i: number = 0; 
  i += d;
  return i;
}

避免動(dòng)態(tài)添加屬性

對(duì)象在創(chuàng)建的時(shí)候啤呼,如果開發(fā)者明確后續(xù)還需要添加屬性,可以提前置為undefined呢袱。動(dòng)態(tài)添加屬性會(huì)導(dǎo)致對(duì)象布局變化官扣,影響編譯器和運(yùn)行時(shí)優(yōu)化效果。

【反例】

// 后續(xù)obj需要再添加z屬性
class O1 {
  x: string = "";
  y: string = "";
}
let obj: O1 = {"x": xxx, "y": "yyy"};
...
// 這種動(dòng)態(tài)添加方式是不推薦的
obj.z = "zzz";

【正例】

class O1 {
  x: string = "";
  y: string = "";
  z: string = "";
}
let obj: O1 = {"x": "xxx", "y": "yyy", "z": ""};
...
obj.z = "zzz";

調(diào)用構(gòu)造函數(shù)的入?yún)⒁c標(biāo)注類型匹配

由于TS語言類型系統(tǒng)是一種標(biāo)注類型羞福,不是編譯期強(qiáng)制約束惕蹄,如果入?yún)⒌膶?shí)際類型與標(biāo)注類型不匹配,會(huì)影響引擎內(nèi)部的優(yōu)化效果。

【反例】

class A {
    private a: number | undefined;
    private b: number | undefined;
    private c: number | undefined;
    constructor(a?: number, b?: number, c?: number) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}
// new的過程中沒有傳入?yún)?shù)卖陵,a遭顶,b,c會(huì)獲取一個(gè)undefined的初值泪蔫,和標(biāo)注類型不符
let a = new A();

針對(duì)上文的示例場(chǎng)景棒旗,開發(fā)者大概率預(yù)期該入?yún)㈩愋褪莕umber類型,需要顯式寫出來撩荣。

參照正例進(jìn)行如下修改铣揉,不然會(huì)造成標(biāo)注的入?yún)⑹莕umber,實(shí)際傳入的是undefined餐曹。

【正例】

class A {
    private a: number | undefined;
    private b: number | undefined;
    private c: number | undefined;
    constructor(a?: number, b?: number, c?: number) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}
// 初始化直接傳入默認(rèn)值0
let a = new A(0, 0, 0);

不變的變量聲明為const

不變的變量推薦使用const進(jìn)行初始化老速。

【反例】

// 該變量在后續(xù)過程中并未發(fā)生更改,建議聲明為常量
let N = 10000;

function getN() {
  return N;
}

【正例】

const N = 10000; 

function getN() {
  return N;
}

接口及繼承

避免使用type類型標(biāo)注

如果傳入的參數(shù)類型是type類型凸主,實(shí)際入?yún)⒖赡苁且粋€(gè)object literal,也可能是一個(gè)class额湘,編譯器及虛擬機(jī)因?yàn)轭愋筒还潭ㄇ渫拢瑹o法做編譯期假設(shè)進(jìn)而進(jìn)行相應(yīng)的優(yōu)化。

【反例】

// type類型無法在編譯期確認(rèn), 可能是一個(gè)object literal锋华,也可能是另一個(gè)class Person
type Person = {
  name: string;
  age: number;
};
 
function greet(person: Person) {
  return "Hello " + person.name;
}

// type方式是不推薦的嗡官,因?yàn)槠溆腥缦聝煞N使用方式,type類型無法在編譯期確認(rèn)
// 調(diào)用方式一
class O1 {
  name: string = "";
  age: number = 0;
}
let objectliteral: O1 = {name : "zhangsan", age: 20 };
greet(objectliteral);

// 調(diào)用方式二
class Person {
  name: string = "zhangsan";
  age: number = 20;
}
let person = new Person();
greet(person);

【正例】

interface Person {
  name: string ;
  age: number;
}
 
function greet(person: Person) {
  return "Hello " + person.name;
}

class Person {
  name: string = "zhangsan";
  age: number = 20;
}

let person = new Person();
greet(person);

函數(shù)調(diào)用

聲明參數(shù)要和實(shí)際的參數(shù)一致

聲明的參數(shù)要和實(shí)際的傳入?yún)?shù)個(gè)數(shù)及類型一致毯焕,如果不傳入?yún)?shù)衍腥,則會(huì)作為undefined處理,可能造成與實(shí)際入?yún)㈩愋筒黄ヅ涞那闆r纳猫,從而導(dǎo)致運(yùn)行時(shí)走入慢速路徑婆咸,影響性能。

【反例】

function add(a: number, b: number) {
  return a + b;
}
// 參數(shù)個(gè)數(shù)是2芜辕,不能給3個(gè)
add(1, 2, 3);
// 參數(shù)個(gè)數(shù)是2尚骄,不能給1個(gè)
add(1);
// 參數(shù)類型是number,不能給string
add("hello", "world");

【正例】

function add(a: number, b: number) {
  return a + b;
}
// 按照函數(shù)參數(shù)個(gè)數(shù)及類型要求傳入?yún)?shù)
add(1, 2);

函數(shù)內(nèi)部變量盡量使用參數(shù)傳遞

能傳遞參數(shù)的盡量傳遞參數(shù)侵续,不要使用閉包倔丈。閉包作為參數(shù)會(huì)多一次閉包創(chuàng)建和訪問。

【反例】

let arr = [0, 1, 2];

function foo() {
  // arr 盡量通過參數(shù)傳遞
  return arr[0] + arr[1];
}
foo();

【正例】

let arr = [0, 1, 2];

function foo(array: Array) : number {
  // arr 盡量通過參數(shù)傳遞
  return array[0] + array[1];
}
foo(arr);

函數(shù)與類聲明

避免動(dòng)態(tài)聲明function與class

不建議動(dòng)態(tài)聲明function和class状蜗。

以如下用例為例需五,動(dòng)態(tài)聲明了class Add和class Sub,每次調(diào)用foo都會(huì)重新創(chuàng)建class Add和class Sub轧坎,對(duì)內(nèi)存和性能都會(huì)有影響宏邮。

【反例】

function foo(f: boolean) {
  if (f) {
    return class Add{};
  } else {
    return class Sub{};
  }
}

【正例】

class Add{};
class Sub{};
function foo(f: boolean) {
  if (f) {
    return Add;
  } else {
    return Sub;
  }
}

TS&JS性能優(yōu)化工具使用

通過如下工具和使用方法,能夠幫助開發(fā)者查看待分析場(chǎng)景下各階段的耗時(shí)分布情況,并進(jìn)一步針對(duì)耗時(shí)情況使用對(duì)應(yīng)的工具做細(xì)化分析蜀铲。

工具使用介紹:

  1. 針對(duì)應(yīng)用開發(fā)者边琉,推薦使用自帶的Smartperf工具來進(jìn)行輔助分析,可以從宏觀角度查看應(yīng)用各個(gè)階段耗時(shí)分布情況记劝,快速找到待分析優(yōu)化模塊变姨。
  2. 針對(duì)第一步分析得到的待優(yōu)化模塊,需要進(jìn)行進(jìn)一步分析確認(rèn)耗時(shí)點(diǎn)是在TS&JS部分還是C++部分厌丑。C++部分耗時(shí)模塊細(xì)化分析建議使用hiperf工具定欧;針對(duì)TS&JS部分耗時(shí),可以使用CPU Profiler工具怒竿。
  3. 針對(duì)虛擬機(jī)開發(fā)者砍鸠,如果需要進(jìn)一步拆分細(xì)化,推薦使用虛擬機(jī)提供的RUNTIME_STAT工具耕驰。

Smartperf工具使用指導(dǎo)

以如下某個(gè)應(yīng)用場(chǎng)景使用過程的trace為例爷辱,可以通過Smartperf工具抓取到應(yīng)用使用階段的耗時(shí)信息,其中大部分為GC(Garbage Collection朦肘,垃圾回收)等操作饭弓。如果此接口大部分是應(yīng)用開發(fā)者通過TS&JS實(shí)現(xiàn),并且在trace中體現(xiàn)此階段比較耗時(shí)媒抠,則可以繼續(xù)使用CPU Profiler工具來進(jìn)一步分析TS&JS部分耗時(shí)情況弟断。

除了可以查看系統(tǒng)的trace之外,還可以在應(yīng)用的源碼的關(guān)鍵流程中加入一些trace點(diǎn)趴生,用于做性能分析阀趴。startTrace用于記錄trace起點(diǎn),finishTrace用于記錄trace終點(diǎn)苍匆,在應(yīng)用中增加trace點(diǎn)的方式如下:

import hiTraceMeter from '@ohos.hiTraceMeter';
... ...
hiTraceMeter.startTrace("fillText1", 100);
... ...
hiTraceMeter.finishTrace("fillText1", 100);

在應(yīng)用層或Native層增加trace點(diǎn)刘急,具體可見 性能打點(diǎn)跟蹤開發(fā)指導(dǎo)

hiperf工具使用指導(dǎo)

集成在Smartperf的hiperf工具使用指導(dǎo)浸踩,具體可見 HiPerf的抓取和展示說明排霉。

hiperf工具的單獨(dú)使用指導(dǎo),具體可見 hiperf應(yīng)用性能優(yōu)化工具民轴。

TS&JS及NAPI層面耗時(shí)分析工具

TS&JS層面耗時(shí)主要分為如下幾種情況:

  1. Ability的生命周期回調(diào)的耗時(shí)攻柠。

  2. 組件的TS&JS業(yè)務(wù)代碼的回調(diào)的耗時(shí)。

  3. 應(yīng)用TS&JS邏輯代碼耗時(shí)后裸。

NAPI層面的耗時(shí)主要分為如下幾種情況:

  1. TS&JS業(yè)務(wù)代碼通過調(diào)用JS API產(chǎn)生的耗時(shí)瑰钮。

  2. TS&JS業(yè)務(wù)代碼調(diào)用開發(fā)者通過NAPI封裝的C/C++實(shí)現(xiàn)時(shí)產(chǎn)生的耗時(shí)。

針對(duì)應(yīng)用中的TS&JS及NAPI兩種業(yè)務(wù)場(chǎng)景的耗時(shí)分析微驶,我們提供了 CPU Profiler工具 浪谴,用來識(shí)別熱點(diǎn)函數(shù)及耗時(shí)代碼开睡。

其支持的采集方式如下:

  • DevEco Studio連接設(shè)備實(shí)時(shí)采集;

  • hdc shell連接設(shè)備進(jìn)行命令行采集苟耻。

可以通過CPU Profiler工具篇恒,對(duì)TS&JS中執(zhí)行的熱點(diǎn)函數(shù)進(jìn)行抓取。以應(yīng)用實(shí)際使用場(chǎng)景為例凶杖,在此場(chǎng)景中胁艰,可以抓到應(yīng)用中的某一熱點(diǎn)函數(shù),在此基礎(chǔ)上智蝠,針對(duì)該接口做進(jìn)一步分析腾么。

寫在最后

如果你覺得這篇內(nèi)容對(duì)你還蠻有幫助,我想邀請(qǐng)你幫我三個(gè)小忙

  • 點(diǎn)贊杈湾,轉(zhuǎn)發(fā)解虱,有你們的 『點(diǎn)贊和評(píng)論』,才是我創(chuàng)造的動(dòng)力漆撞。
  • 關(guān)注小編殴泰,同時(shí)可以期待后續(xù)文章ing??,不定期分享原創(chuàng)知識(shí)浮驳。
  • 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識(shí)點(diǎn)悍汛,請(qǐng)移步前往小編:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市抹恳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌署驻,老刑警劉巖奋献,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異旺上,居然都是意外死亡瓶蚂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門宣吱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窃这,“玉大人,你說我怎么就攤上這事征候『脊ィ” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵疤坝,是天一觀的道長(zhǎng)兆解。 經(jīng)常有香客問我,道長(zhǎng)跑揉,這世上最難降的妖魔是什么锅睛? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任埠巨,我火速辦了婚禮,結(jié)果婚禮上现拒,老公的妹妹穿的比我還像新娘辣垒。我一直安慰自己,他們只是感情好印蔬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布勋桶。 她就那樣靜靜地躺著,像睡著了一般扛点。 火紅的嫁衣襯著肌膚如雪哥遮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天陵究,我揣著相機(jī)與錄音眠饮,去河邊找鬼。 笑死铜邮,一個(gè)胖子當(dāng)著我的面吹牛仪召,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播松蒜,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扔茅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了秸苗?” 一聲冷哼從身側(cè)響起召娜,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惊楼,沒想到半個(gè)月后玖瘸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡檀咙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年雅倒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弧可。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔑匣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出棕诵,到底是詐尸還是另有隱情裁良,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布校套,位于F島的核電站趴久,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏搔确。R本人自食惡果不足惜彼棍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一灭忠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧座硕,春花似錦弛作、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜘拉,卻和暖如春萨西,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旭旭。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工谎脯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人持寄。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓源梭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親稍味。 傳聞我的和親對(duì)象是個(gè)殘疾皇子废麻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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