iOS耗电量优化实践

前言-理论篇

耗电量分析是衡量应用性能表现的一个重要指标,要做好一款app,不仅仅是实现功能,我们需要考虑很多性能指标,让用户用的更爽,在开发过程中,要充分考虑到各项性能指标,比如定位精度,更高的精度,往往意味着更高的能耗,因此要平衡好精度和功耗,避免我们的app过多的过多的电量消耗,而界面卡顿可能意味着大量的多余计算,不仅影响流畅度,影响电量消耗,网络的不合理使用,也会增加耗电量,这些都是影响耗电量和用户体验的重要因素,因此必须要重视app耗电量。

1.耗电量概念

`x 轴`为时间,`y 轴`为电量消耗的坐标图
  • Idle 表示app处于休眠状态,几乎不使用电量。
  • Active状态说明app处于工作状态,用电量比较高,图中的第二个 Active 的耗电远高于第一个,这是因为app所做的工作类型不同而导致的。
  • Overhead指的是调起硬件来支持app功能所消耗的电量,这部分是支持硬件工作必要的电量消耗。
  • 图中横线以下所包区域是固定开销(Fixed Cost),横线以上区域是动态开销(Dynamic cost)。

2.节省电量的四个基本原则:

  • 识别:想清楚你需要app在特定时刻需要完成哪些工作,如果是不必要的工作,考虑延后执行或者省去。

  • 优化:优化app的功能实现,尽可能以更有效率的方式去完成功能。

  • 合并:不需要立刻获取,可以延后合并执行,比如合并网络

  • 减少:在满足需求的基础上,尽量减少做重复工作的频率。

一、耗电大户

耗电大户

1.网络

app进行网络通信时,蜂窝数据和Wi-Fi等元器件开始工作就会消耗大量电能,应减少数据传输,合并网络请求,适当的网络延时等。

2.定位

app为了记录用户的活动或者提供基于位置的服务会进行定位。定位精度越高,定位时间越长,消耗电量也就越多。

3.CPU

app做的每件事几乎都需要用CPU,所以CPU是电能消耗大户,高CPU使用时会迅速消耗掉用户的电池电量,所以我们要更合理的使用CPU,降低能耗。

4.GPU

app内容每次更新到屏幕上都需要消耗电能处理像素信息。动画和视频格外耗电。不经意的或者不必要的内容更新同样会消耗电能,所以UI不可见时,应该避免更新其内容。

5.传感器和蓝牙

长时间用不上加速度计、陀螺仪、磁力计等设备的动作数据时,应该停止更新数据,不然也会浪费电能。应按需获取,用完即停。蓝牙活动频度太高会消耗电能,应该尽量分批、减少数据轮询等操作。

二、测试工具

1.Energy Impact

Energy Imapct
1.1Average energy Imapct

Average energy Imapct代表的是app的耗电量评级,low(绿色区域)high (黄色区域)very high(红色区域)。通过这张图,我们可以大致了解 app 电量的使用情况。理想的状态是 app 处于 low、high 状态。如果处于very high状态,我们需要分析哪些功能导致耗电量大涨。

1.2Average Componet Utilization

Average Componet Utilization展示的是OverheadCPUNetWorkLocationGPU各部分耗电量的占比,通过这个占比,我们可以分析各部分耗电量是否较高。

1.3Energy Impact

Energy Impact会实时展示电量消耗,每个柱子代表每秒的电量消耗,通过每个柱子由不同的颜色组成,展示各部分电量消耗的比例,依次是Overhead(红色)、CPU(蓝色)、网络(深黄)、定位(淡黄)、GPU(绿色)、后台(深灰)、前台(淡灰)、Suspend(白色)

1.4总结

在使用Energy Impact的过程中,首先可以观察Average energy Imapct。了解app的整体耗电量情况,处在什么位置,对整体有个大概的了解,然后通过Average Componet Utilization来观察app整体耗电量中,具体哪一部分占比较高,最后使用Energy Impact进行实时分析,分析页面各部分消耗是否是必要的,比如某个页面只在进入的时候需要获取经纬度,后面不需要实时获取经纬度,那么在进入页面获取经纬度以后,就要将定位关闭,以减少电量消耗。

优点:
实时性高、数据分析可以通过图形直观展示、可以获取`Overhead(红色)、CPU(蓝色)、网络(深黄)、定位(淡黄)、GPU(绿色)、后台(深灰)、前台(淡灰)、Suspend(白色)等数据和各部分数据占比。

缺点:
颗粒度较大,想做详细的分析,需要借助,其它工具。比如针对CPU的消耗情况,可以通过Time Profiler来进行分析,分析具体哪部分代码消耗较多,使用Network Profiler来分析网络的消耗情况、使用Location Profiler来分析定位的情况,详细获取各部分数据,找到电量的消耗点。

2.Energy Log

2.1Energy Log使用:
energy log

设置路径:开发者 -> Logging -> Energy -> Start Recording -> Stop Recording。

首先找到开发者,点击进入,找到Logging选项,如下图:

<img src="https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/ios_settings_2x.png" width = "300" height = "500" align = center /><img src="https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/ios_developer_2x.png" width = "300" height = "500" align = center /></br>

然后点金进入Logging选项、进入新页面,打开Energy开关,同时点击Start Recording,此时开始记录电量消耗情况,,这时你可以选择想要测试的app,在测试完毕后,点击Stop Recording,关闭电量记录功能,如下图:

<img src="https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/ios_logging_startrecording_2x.png" width = "300" height = "500" align = center /><img src="https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/ios_logging_stoprecording_2x.png" width = "300" height = "500" align = center /></br>

最后,将手机连接到电脑,导出设备中的电量记录数据,在Energy Log中,可以看到详细的电量消耗数据,如下图:

<img src="https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/instruments_file_menu_importloggeddatafromdevice_menuitem_2x.png" width = "400" height = "500" div align = center /></br>

2.2Energy Log组成:
energylog4
  • Energy Usage Log 代表能耗消耗级别,有 0 到 20 的级别,表示应用在任何给定时间使用了多少电量,值越大表示越耗电。可以用来分析app的总体能耗。

  • CPU Activity Log 代表cpu能源消耗,包括 :Foreground app ActivityGraphics ActivityMedia ActivityOther Activity

  • Network Activity Log 代表网络能源消耗,包括 :Cellular inCellular outWi-Fi InWi-Fi Out

  • Display Brightness Log 代表屏幕消耗。

  • Sleep/Wake Log 代表仪器捕获有关设备当前状态的信息。

  • Bluetooth On/Off Log 代表蓝牙开关状态。

  • Wi-Fi On/Off Log 代表Wi-Fi开关状态。

  • Gps On/Off Log 代表Gps开关状态。

2.3总结

在使用Energy Log过程中,可以通过横向比较各个维度的数据,来分析各部分的能源消耗,分析能耗的使用情况,更合理的使用手机电量。

优点:
Energy Log可以测试自己app和别人app的电量消耗,有各个上面👆维度的详细数据,比如:某个时刻的cpu使用情况、定位使用情况,可以关联CPU、定位、总能耗消耗等数据,通过这些数据,分析使用是否合理。

缺点:
Energy Log只能看整体能耗的水平,同时由于log不是实时的,要具体确定某个页面或者某个路径的能耗情况,需要自己测试的时候记录一下,只能大概对照,而且不能输出精准数据。

3.Sysdiagnose

Sysdiagnose是用来诊断系统问题的工具,它包括了过去几天里,系统整体的详细功耗情况、各个App在各个硬件上的耗电情况,温度、电流等等一系列详细的数据。这些数据最终会存储在数据库中,数据库中包含多张数据表,比如在iOS12的系统中,有多达406张表。

3.1配置和数据获取

苹果官方在Battery Life Logging Instructions中详细说明了导出日志的步骤。通过安装电量分析的profile来记录手机耗电量信息,使用iTunes进行同步,最终从文件夹(~/Library/Logs/CrashReporter/MobileDevice/你的手机名/)中获取后缀是.PLSQL或者.PLSQL.gz的几个文件,这些文件记录了手机中各个app的耗电情况。

3.2分析数据

数据库中有多张表格,这些表格的具体用途,苹果没有详细说明,下面是腾讯和一些开发者总结的部分表格信息。

表名 内容
PLBatteryAgent_EventBackward_Battery 整机的电量信息,包含电流、电压、温度等信息。(每20秒记录一条数据)
PLBatteryAgent_EventBackward_Battery_UI 剩余电量百分比。(每20秒记录一条数据)
PLIOReportAgent_EventBackward_EnergyModel 整机不同硬件上的详细功耗数据。分别记录了 CPU、GPU、DRAM 等硬件的耗电量。
PLAccountingOperator_Aggregate_RootNodeEnergy 各个 App 的详细耗电数据。记录各个 App 在各个硬件上的耗电量。(每小时更新一次数据)
PLAccountingOperator_EventNone_Nodes 各个硬件对应的 Node ID,以及各个 App 的对应的 Node ID。
PLAccountingOperator_EventNone_AllApps 手机中安装的所有 App 的信息
PLApplicationAgent_EventForward_Application App 运行状态记录。记录各个 App 在某个时间段以什么状态运行。
PLAppTimeService_Aggregate_AppRunTime App 的运行时长统计。(每小时更新一次数据。
PLBatteryAgent_EventForward_LightningConnectorStatus Lighting 接口连接状态。
PLBatteryAgent_EventNone_BatteryConfig 电池的配置信息。包括电池容量、循环计数、电池寿命、电池温度等信息。
PLBatteryAgent_EventNone_BatteryShutdown 电池导致的意外关机记录。
PLCameraAgent_EventForward_Camera 相机使用记录。记录了相机类型和使用相机的 App
PLConfigAgent_EventNone_Config 本机的一些配置信息和一些系统设置。
PLDisplayAgent_Aggregate_UserTouch 屏幕点击计数。每 15 分钟记录一条数据。
PLDisplayAgent_EventForward_Display 屏幕亮度信息。包括流明、尼特、亮度滑竿值等信息。
PLProcessNetworkAgent_EventPoint_Connection 网络连接记录。记录了发起网络连接的 App、地址、端口等信息。
PLXPCAgent_EventPoint_CacheDelete 清除缓存的记录。包括申请的空间大小、清除缓存的耗时、清除的缓存大小、服务名称、紧急程度等信息。

我们可以根据上面的表格,来分析耗电情况,比如:

  • PLBatteryAgent_EventBackward_Battery_UI 可以分析剩余电量曲线
  • PLBatteryAgent_EventBackward_Battery 可以分析整体耗电量和温度变化
  • PLAccountingOperator_Aggregate_RootNodeEnergy 和 PLAccountingOperator_EventNone_Nodes 两张表,可以得到某个 Bundle ID 对应的 App 在各个硬件上的耗电情况。

下面是一些数据获取的SQL语句:

  • 查看APP运行的时间timestamp

    select ID,timestamp,datetime(timestamp, 'unixepoch', 'localtime')as time,BundleID from PLAppTimeService_Aggregate_AppRunTime where BundleID='XXX' order by timestamp

  • 查看APP的NodeID

    select * from PLAccountingOperator_EventNone_Nodes where Name ='XXX'

  • 查看APP的电量测试

    select ID,timestamp,datetime(timestamp, 'unixepoch','localtime')as time,Energy,NodeID,RootNodeID from PLAccountingOperator_Aggregate_RootNodeEnergy where NodeID=XXX order by time

  • 查看APP某个时间点的电量求和

    select datetime(timestamp, 'unixepoch', 'localtime')as time,sum(Energy),NodeID from PLAccountingOperator_Aggregate_RootNodeEnergy where NodeID=XXX and timestamp='XXX'

RootNodeID硬件对照表

RootNodeID 硬件
2 CPU
4 VENC
5 VDEC
6 ISP
7 RestOfSOC
8 GPU
9 DRAM
10 Display
11 WiFi-Data
14 AudioHeadset
15 AudioSpeaker
17 FrontCamera
18 BackCamera
19 Torch
37 BB
38 BB-Voice
47 BB-Pssi
48 GPS
50 Bluetooth
53 WiFi-IdLe
54 APSOCBaseIOReport
55 AudioCodec
3.4总结

Sysdiagnose是一个可以详细获取各个维度数据的工具,具体到某个app、某段时间、某个硬件的具体能源消耗,可以使用这个工具,进行app的不同场景的能耗数据对比、竞品app的能耗数据分析和对比,十分精确。

优点:
可以精确获取各个维度的能耗消耗数据,包括:ispapsocbasedisplaywifi dataGPUCPUrestofsocGPSDRAM、等详细数据。通过这些数据,可以分析某个app的某段时间,各个维度的能耗数据,这个数据十分精确。

缺点:
数据不能实时获取,部分数据需要等待一个小时才能获取,测试周期长,数据量较大,没有官方文档指导,需要自己分析各个表中的数据含义。

三、案例分析

1.对比分析

使用Sysdiagnose,通过对比A页面和B页面(A和B是两个不同app相同业务的页面),来分析各自耗电量情况,以及可能的优化点。下面数据单位是1/1000 mAh

1.1A页面和B页面

测试条件:iphone7,iOS12.2,记录5分钟电量消耗,滑动100次,取三次平均值.

APP Display GPS WiFi-Data CPU RestOfSOC DRAM GPU SUM
A页面 31888 0 1753 18523 5437 5059 0 62660
B页面 36180 9652 1500 16338 4792 4460 289 73211
页面对比

对比A页面和B页面能耗数据,整体能耗数据,B页面高于A页面电量消耗,CPU、RestOfSOC、DRAM数据,A页面都高于B页面,B页面GPS电量消耗量较高,这是因为B页面一直开启了GPS,Display数据B页面高于A页面,可能和动画使用有关。通过这些指标分析,可对比竞品之间的能耗水平,也可以初步为电量优化提供方向。

1.2页面中硬件电量消耗
硬件消耗占比

通过图片可以看出页面中,Display和CPU是主要消耗,占用页面整体电量消耗的80%左右,这一部分也是优化的重点,对于Diaplay的电量消耗受很多因素影响,比较复杂,比如:屏幕亮度和动画等影响。

总结:通过对比分析,可以获取app的具体电量消耗水平,可以根据具体数据,推断出app能运行的时间,同时可以对比竞品,判断app的电量消耗水平,并从具体指标分析,初步推断优化方向。

2.需求分析

image.png

上面是使用Energy Log来测试C页面的电量消耗情况,红色部分是Overhead,表示调起硬件的正常电量消耗,其占据页面57.1%,网络占10.2%,cpu占1.2%,Location占31.1%,但在这个页面中,GPS是一直开启的,也就是图中的黄色部分,实际情况是是不需要一直开启GPS定位,这一部分存在优化空间,按需要开启和关闭GPS开关。

总结

在进行电量消耗测试时,需要对页面需求进行具体分析,用来判别页面中网络、CPU、GPU、GPS各部分的电量消耗是否是合理和必要的,上面例子的情况,GPS没必要一直开启,可以在不需要使用时关闭,存在优化空间。关于更多电量优化建议,可以参考苹果官方Apple Energy Guide或者这篇翻译App功耗优化建议,会从网络、CPU、GPU、GPS等方面,更详细的角度来分析耗电量优化。

四、优化建议

1.网络

只要app执行网络操作,就会产生大量的见解能耗,网络硬件为了响应下一次任务,往往会持续活跃一段时间,下面是多次网络的能耗图。


多次网络活动产生间接能耗.png
1.1 缩减网络请求
  1. 减少、压缩网络数据。可以降低上传或下载的多媒体内容质量和尺寸等。

  2. 使用缓存,不要重复下载相同的数据。

  3. 使用断点续传,否则网络不稳定时可能多次传输相同的内容。

  4. 网络不可用时不要尝试执行网络请求,尽量只在Wi-Fi情况下联网。

  5. 让用户可以取消长时间运行或者速度很慢的网络操作,设置合适的超时时间。

  6. 网络请求失败后用SCNetworkReachability的通知监测网络状态,网络可用后再重试。

1.2 延迟联网
  1. 分批传输。比如,下载视频流时,不要传输很小的数据包,直接下载整个文件或者一大块一大块地下载。如果提供广告,一次性多下载一些,然后再慢慢展示。如果要从服务器下载电子邮件,一次下载多条,不要一条一条地下载。

  2. 网络操作能推迟就推迟。如果通过HTTP上传、下载数据,建议使用NSURLSession中的后台会话,这样系统可以针对整个设备所有的网络操作优化功耗。将可以推迟的操作尽量推迟到设备充电状态并且连接Wi-Fi时进行,比如同步和备份工作。

2.定位

  1. 如果你的app只是需要快速确定一下用户的位置,最好用CLLocationManager的requestLocation (iOS9引入)方法。定位完成之后会自动让硬件断电。

  2. 除非是在导航的时候,app大部分时间不需要实时更新,降低位置的更新频率。

  3. 尽量降低定位精度。iOS设备默认采用最高精度定位,如果你的app不是确实需要米级的位置信息,不要用最高精度(kCLLocationAccuracyBest)或10米左右的精度(kCLLocationAccuracyNearestTenMeters)。一般来说Core Location提供的精度比你设置的要好,比如你设置为3公里左右的精度,可能会收到100米左右的精度信息。

  4. 如果定位精度一直达不到设置的精度时,停止更新位置,稍后再试。

  5. 需要后台更新位置时,尽量把pausesLocationUpdatesAutomatically设为YES,如果用户不太可能移动的时候系统会自动暂停位置更新。

  6. 后台定位时延时更新位置。如果要做一个健身类的软件追踪用户徒步的距离,可以等用户移动一段距离或者过一段时间之后再更新位置,这样可以让系统优化能耗。

3.CPU

3.1尽量减少计时器使用

使用计时器时,设置一个合适的超时时,不再需要时及时关闭重复性定时器。用事件通知代替定时器。有些app用定时器监控文件内容、网络或者其他状态的变化,这会导致CPU无法进入闲置状态而增加功耗。

3.2减少后台工作

实现UIApplicationDelegate中的方法,应用进入后台前做好暂停任务,保存数据等工作。如果确实需要完成用户执行的一些任务,应该调用UIApplicationDelegate中的beginBackgroundTaskWithExpirationHandler: 方法,这样后台任务可以继续执行几分钟。任务执行完毕后一定要调用endBackgroundTask:方法,不要等着系统强行挂起进程。

3.3用QoS分级有序工作

多个app和众多操作需要共享CPU、缓存、网络等资源,为了保持高效,系统需要根据不同任务的优先级智能地管理这些工作。比如更新UI这种重要的事需要多分配资源,而一些后台任务可以延迟一些执行。服务质量(quality of service, 以下简称QoS, iOS8引入)级别可以通过NSOperation, NSOperationQueue, NSThread objects, dispatch queues, 和pthreads (POSIX threads)指定工作的优先级。

3.4优化I/O访问

app每次执行I/O任务,比如写文件,会导致系统退出闲置模式。而且写入缓存格外耗电。通过下列方法可以提高能效、改善app性能。

  1. 减小写入数据。数据有变化再写文件,尽量把多个更改攒到一起一次性写入。如果只有几个字节的数据改变,不要把整个文件重新写入一次。如果你的app经常要修改大文件里很少的内容,可以考虑用数据库存储这些数据。

  2. 避免访问存储频度太高。如果app要存储状态信息,要等到状态信息有变化时再写入。尽量分批修改,不要频繁地写入这些小变动。

  3. 尽量顺序读写数据。在文件中跳转位置会消耗一些时间。

  4. 尽量从文件读写大数据块,一次读取太多数据可能会引发一些问题。比如,读取一个32M文件的全部内容可能会在读取完成前触发内容分页。

  5. 读写大量重要数据时,考虑用dispatch_io,其提供了基于GCD的异步操作文件I/O的API。用dispatch_io系统会优化磁盘访问。

  6. 如果你的数据由随机访问的结构化内容组成,建议将其存储在数据库中,可以使用SQLite或Core Data访问。特别是需要操作的内容可能增长到超过几兆的时候。

  7. 了解系统如何缓存文件、如何优化缓存的使用。如果你不打算多次引用某些数据,不要自己缓存数据。

4.GPU

  1. 减少app使用的视图数量。

  2. 少用运算获得圆角,不论view.maskToBounds还是layer.clipToBounds都会有很大的资源开销.

  3. 尽量少用透明或半透明,会产生额外的运算.

  4. 执行动画时不要修改帧率。比如,你的app帧率是60fps,整个动画就保持这个帧率不要变。

  5. 视频播放时,app尽量不要在全屏视频上添加额外的图层(即使是隐藏的图层)

5.优化通知

  1. 尽量用本地通知(local notification),如果你的app不依赖外部数据,而是需要基于时间的通知,应该用本地通知,可以让设备的网络硬件休息一下。

  2. 远程推送有两个级别,一个是立即推送,另一个是针对功耗优化过的延时推送。如果不是真的需要即时推送,尽量使用延时推送。

五、总结

耗电量分析是应用开发中很难的课题,也是衡量性能的重要指标,做好电量优化,可以大幅度提升用户体验,在实际开发过程中,电量消耗往往是一个综合的结果,小到日常的代码习惯,积少成多,大到网络的乱用、不合理的网络超时、不合理的定位使用、不合理的CPU使用,都会带来能耗的过多消耗,而这些问题仅仅会影响电量,还会影响用户体验,而对于这一个很多因素综合起来的结果,我们需要提高日常开发的代码质量,了解不同实现方式的差异点,优化页面卡顿,优化网络使用,优化GPS使用等等,只有综合这些因素,最终获得较好的用户体验。

在做耗电量分析的时候,首先要清楚耗电量较大的点,比如:网络、定位、CPU、GPU,从这些点来入手分析,再详细分析每个点,细分每个点中的一些细节的影响,比如:网络中可能会存在导致耗电量过高的因素,我们可以使用哪些优化方法,同时根据我们的需求特点,怎么来优化,最终找到可优化点的,找到解决方案,来优化耗电量。

在优化点寻找的过程中,我们首先可以使用Energy Impact来实时分析,各个维度指标是否有问题,占比是否合理,然后在通过Time ProfilerNetwork ProfilerLocation Profiler等工具对各项指标进行详细分析,寻找优化点。
其次我们可以使用Energy Log来横向对比各个维度的数据,来分析各个维度对总功耗的影响,比如:wifi数据传输和4G数据传输时,耗电量的对比,打开蓝牙和未打开蓝牙,能耗数据的对比,查看各个维度对能耗消耗影响的权重。然后,我们可以使用Sysdiagnose可以进行不同场景、竞品app的对比分析,查找app的可优化点,也可以进行各种能耗数据的对比分析,以及优化前后的能耗数据对比,获取最终的优化效果。Sysdiagnose中的数量比较精确,同时数据比较全面,可以挖掘更多的信息,来辅助我们进行电量优化。</br>

附:iPhone各代电池容量

📱手机型号 🔋电池容量
iPhone 11 Pro Max 3500mAh
iPhone 11 Pro 3190mAh
iPhone 11 3110mAh
iPhone XS Max 3174mAh
iPhone XS 2658mAh
iPhone XR 2942mAh
iPhone 8 Plus 2675mAh
iPhone 8 1821mAh
iPhone 7 Plus 2900mAh
iPhone 7 1960mAh
iPhone 6s Plus 2750mAh
iPhone 6s 1715 mAh
iPhone 6 Plus 2915mAh
iPhone 6 1810 mAh

参考内容:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容