• 1. Baseline
    • 1.1 Read
    • 1.2 Write
    • 1.3 Batch Write
  • 2. Multithread
    • 2.1 Multithread Read-Read
    • 2.2 Multithread Read-Write
    • 2.3 Multithread Write-Write
  • 3. Initialization
  • 4. Different Configurations
    • 4.1 Cipher Read
    • 4.2 Cipher Write
    • 4.3 Sync Write
  • 自定义benchmark

    为了测试WCDB的性能数据,我们提供了benchmark,用于横向比较FMDB、纵向比较不同的参数配置,并可用于验证后续更多性能优化的效果。

    我们同时将benchmark的代码上传到了WCDB的仓库,开发者也可自行修改参数或加入更多的benchmark。

    Benchmark基于以下原则进行:

    • 所有测试都在同一个设备上进行,并且设备不同时进行其他高性能损耗的任务。
    • 测试的样本量“足够大”,以避免误差导致结果相差较大。
    • 所有测试均在Release且不连接Xcode调试的状态下进行。
    • 每个benchmark取5次与平均值的误差不超过±5%的结果。
    • 数据库完全关闭后再打开进行测试,以避免缓存影响结果。

    • 如无特殊说明,SQLite配置均为WAL模式、缓存大小2000字节、页大小4 kb:

    • PRAGMA cache_size=-2000

    • PRAGMA page_size=4096
    • PRAGMA journal_mode=WAL
      测试数据均为含有一个整型和一个二进制数据的表:CREATE TABLE benchmark(key INTEGER, value BLOB),二进制数据长度为100字节。

    本文档的数据均为iOS benchmark的平均值,所有数据四舍五入取三位有效数字。原始数据和macOS的数据请参考:Benchmark原始数据

    1. Baseline

    1.1 Read

    读操作性能测试:该测试为从数据库中取出所有数据,并拼装为object。

    性能数据与Benchmark - 图1

    1.2 Write

    写操作性能测试:该测试为将object的数据不断插入到数据库中(不使用事务)。

    性能数据与Benchmark - 图2

    1.3 Batch Write

    批量写操作性能测试:该测试为将object的数据批量插入数据库(使用事务)。

    性能数据与Benchmark - 图3

    WCDB写操作和批量写操作的性能分别优于FMDB 28%180% ,而读操作则劣于FMDB 5%

    对于读操作,SQLite速度很快,因此封装层的消耗会占比较多。FMDB只做了最简单的封装, 而WCDB还包括ORM、WINQ等操作,因此执行的指令会比FMDB多,从而导致性能稍差于FMDB。但WCDB也通过一些优化手段减少这种差距。例如,通过IMP指针调用函数、部分操作No-ARC等等。

    而写操作,WCDB也做了许多针对性的优化。例如,WAL模式下写入操作触发checkpoint时,不立即执行checkpoint,而是由一个checkpoint线程来完成,从而减少单次操作的耗时等等。

    2. Multithread

    2.1 Multithread Read-Read

    多线程读操作性能测试:该测试同时启动两个线程,分别从数据库中取出所有数据,并拼装为object。

    性能数据与Benchmark - 图4

    2.2 Multithread Read-Write

    多线程读写操作性能测试:该测试同时启动两个线程,一个线程从数据库中取出所有数据,并拼装为object;另一个将object的数据批量插入到数据库中。

    性能数据与Benchmark - 图5

    2.3 Multithread Write-Write

    多线程写操作性能测试:该测试同时启动两个线程,分别将object的数据批量插入数据库。

    性能数据与Benchmark - 图6

    WCDB的多线程读写操作性能优于FMDB 62% ,而多线程读操作基本与FMDB持平。

    FMDB在多线程写测试中,直接返回错误SQLITE_BUSY,因此无法比较。而基于SQLite的机制,WCDB的多线程写操作实质也是串行执行,但不会出错导致操作中断。

    3. Initialization

    初始化性能测试:该测试针对创建SQLite连接的初始化过程,即创建SQLite连接,并设置最基本的配置。SQLite的初始化速度会根据表的数量而增加。

    性能数据与Benchmark - 图7

    WCDB通过针对性的优化,使得初始化性能优于FMDB 107%

    4. Different Configurations

    4.1 Cipher Read

    加密数据库读操作测试:该测试基于Baseline Read,并将数据库改为加密数据库。

    性能数据与Benchmark - 图8

    4.2 Cipher Write

    加密数据库写操作测试:该测试基于Baseline Write,并将数据库改为加密数据库。

    性能数据与Benchmark - 图9

    加密操作分别会对读和写增加 28%26% 的性能损耗。

    4.3 Sync Write

    数据库同步写操作测试:该测试基于Baseline Write,并在每次写入都同步等待完全写入到磁盘,即增加以下配置:

    • PRAGMA synchronous=FULL
    • PRAGMA checkpoint_fullfsync=1
    • PRAGMA fullfsync=1
      性能数据与Benchmark - 图10

    同步写操作会大幅降低写操作的性能,但对于数据稳定有很强的保护作用,能够降低 50% 的数据库损坏率。推荐对重要的数据库开启。

    自定义benchmark

    我们也提供benchmark的代码,以供开发者修改参数或新增其他benchmark,重复验证性能。

    benchmark的代码位于源码的objc/benchmark/目录下,运行方式为:

    • 安装Carthage。因为benchmark包含对FMDB的测试,因此需要通过carthage安装FMDB。
    • 打开objc/benchmark/WCDB-benchmark.xcodeprj工程,分别有Benchmark-WCDB-macOSBenchmark-FMDB-macOSBenchmark-WCDB-iOSBenchmark-FMDB-iOS四个target,按照需求运行测试。
    • 修改objc/benchmark/supporting/iOS/Config.plistobjc/benchmark/supporting/macOS/Config.plist中的参数,切换不同测试或不同参数测试。