微信iOS SQLite源码优化实践

【腾讯Bugly干货分享】微信iOS SQLite源码优化实践 本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58022433221be01499480 作者:张三华 前言随着微信iOS客户端业务的增长,在数据库上遇到的性能瓶颈也逐渐凸显。在微信的卡顿监控系统上,数据库相关的卡顿不断上升。而在用户侧也逐渐能感知到这种卡顿,尤其是有大量群聊、联系人和消息收发的重度用户。我们在对SQL 阅读详情

# 微信iOS SQLite源码优化实践


Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师。每周都会举行嘉宾分享,话题讨论等活动。

本期,我们邀请了腾讯WXG iOS 开发工程师——张三华,为大家分享《微信iOS SQLite源码优化实践》。

### 分享内容简介:

SQLite是微信iOS选用的数据库,随着微信iOS客户端业务的增长,在重度用户的场景下,性能瓶颈逐渐显现。靠单纯地修改SQLite的参数配置,已经不能彻底解决问题,因此我们尝试从源码开始做深入的优化。

### 内容大体框架:

  1. SQLite对于多线程的处理和不足及微信的优化

  2. SQLite在I/O上可压榨的性能

  3. 其他细节优化

### 下面是本期分享内容整理

Hello,大家好,我是张三华,目前在微信主要负责 iOS 的基础优化工作。第一次进行这种微信群分享,可能准备的不是太充分。若有任何疑问,欢迎在分享结束后提问。

下面开始我们今天的分享。

## 引言

SQLite 是我们在移动端常用的数据库,微信也是基于它封装了一层 ObjC 接口。我们知道,微信里消息的收发是很频繁的,尤其是对于重度用户,这对于数据库的多线程并发和 I/O 是很大的挑战。

通常对这部分做优化,有两种方式:

* 一是修改 SQLite 的参数,如 Cache Size 等

* 二是改业务层调用,如主线程操作 dispatch 到子线程。

然而,前者有明显的瓶颈,后者则是个 endless 的工作。我们希望能一劳永逸地解决同类问题。这就是我们本次所要分享的优化。

## 1. 多线程并发优化

### 1.1 SQLite 多句柄方案

我们先讲 SQLite 所提供的多线程并发方案。它对这方面的支持做的很不错,在使用上,只需

  1. 开启句柄多线程支持的配置 PRAGMA SQLITE_THREADSAFE=2

  2. 确保同一个句柄同一时间只有一个线程在操作

  3. (可选)开启 WAL 模式 PRAGMA journal_mode=WAL

此时写操作会先 append 到 wal 文件末尾,而不是直接覆盖旧数据。而读操作开始时,会记下当前的 WAL 文件状态,并且只访问在此之前的数据。这就确保了多线程读与读、读与写之间可以并发地进行。

### 1.2 Busy Retry 方案

而写与写之间仍会互相阻塞。SQLite 提供了 Busy Retry 的方案,即发生阻塞时,会触发 Busy Handler,此时可以让线程休眠一段时间后,重新尝试操作。重试一定次数依然失败后,则返回 SQLITE_BUSY 错误码。

下面这段代码是 SQLite 默认的 Busy Handler

这里写图片描述

### 1.3 Busy Retry 方案的不足

上面介绍了 SQLite 多线程并发方案,接下来我们把焦点放在 Busy Retry 这个方案的不足上。

Busy Retry 的方案虽然基本能解决问题,但对性能的压榨做的不够极致。在 Retry 过程中,休眠时间的长短和重试次数,是决定性能和操作成功率的关键。

然而,它们的最优值,因不同操作不同场景而不同。若休眠时间太短或重试次数太多,会空耗 CPU 的资源;若休眠时间过长,会造成等待的时间太长;若重试次数太少,则会降低操作的成功率。如下图
这里写图片描述

可以看到

* CPU空转那段,线程一操作还没结束,这里空耗了 CPU 的资源

* 线程闲置那段,线程一已经结束,而线程二仍在等待,空耗了时间

对于这个的优化,简单的方法可以是修改休眠时间,尽最大限度缩短以上两段空耗的资源。

我们通过 A/B Test 对不同休眠时间进行了实验,得到了如下的结果
这里写图片描述可以看到,倘若休眠时间与重试成功率的关系,按照绿色的曲线进行分布,那么 p 点的值也不失为该方案的一个次优解。然而不同业务和操作的需求,还是有很大的不同的。

既然 SQLite 的方案不行,我们就要开始往深层探索新的可能性了。

### 1.4 SQLite 中控制并发相关的原理

SQLite是一个适配不同平台的数据库,不仅支持多线程并发,还支持多进程并发。它的核心逻辑可以分为两部分:

这里写图片描述

* **Core 层**。包括了接口层、编译器和虚拟机。通过接口传入 SQL 语句,由编译器编译SQL生成虚拟机的操作码 opcode。而虚拟机是基于生成的操作码,控制 Backend 的行为。

* **Backend 层**。由 B-Tree、Pager、OS 三部分组成,实现了数据库的存取数据的主要逻辑。

在架构最底端的 OS 层是对不同操作系统的系统调用的抽象层。它实现了一个 VFS(Virtual File System),将 OS 层的接口在编译时映射到对应操作系统的系统调用。锁的实现也是在这里进行的。

SQLite 通过两个锁来控制并发。第一个锁对应 DB 文件,通过5种状态进行管理;第二个锁对应WAL文件,通过修改一个 16-bit 的 unsigned short int 的每一个 bit 进行管理。尽管锁的逻辑有一些复杂,但此处并不需关心。这两种锁最终都落在 OS 层的 sqlite3OsLock、sqlite3OsUnlock 和 sqlite3OsShmLock 上具体实现。

它们在锁的实现比较类似。以 lock 操作在 iOS 上的实现为例:

  1. 通过 pthread_mutex_lock 进行线程锁,防止其他线程介入。然后比较状态量,若当前状态不可跳转,则返回 SQLITE_BUSY

  2. 通过 fcntl 进行文件锁,防止其他进程介入。若锁失败,则返回 SQLITE_BUSY

而 SQLite 选择 Busy Retry 的方案的原因也正是在此

**文件锁没有线程锁类似 pthread_cond_signal 的通知机制。当一个进程的数据库操作结束时,无法通过锁来第一时间通知到其他进程进行重试。因此只能退而求其次,通过多次休眠来进行尝试。**

1.5 新的方案

搞清楚了 SQLite 并发的实现,我们就是可以开始改造了。

我们知道,iOS app 是单进程的,并没有多进程并发的需求,这和 SQLite 的设计初衷是不相同的。这就给我们的优化提供了理论上的基础。在 iOS 这一特定场景下,我们可以舍弃兼容性,提高并发性。

新的方案修改为,当 OS 层进行 lock 操作时:

  1. 通过 pthread_mutex_lock 进行线程锁,防止其他线程介入。然后比较状态量,若当前状态不可跳转,则将当前期望跳转的状态,插入到一个 FIFO 的 Queue 尾部。最后,线程通过 pthread_cond_wait 进入 休眠状态,等待其他线程的唤醒。

  2. 忽略文件锁

当 OS 层的 unlock 操作结束后:

  1. 取出 Queue 头部的状态量,并比较状态是否能够跳转。若能够跳转,则通过 pthread_cond_signal_thread_np 唤醒对应的线程重试。这里写图片描述

新的方案可以在 DB 空闲时的第一时间,通知到其他正在等待的线程,最大程度地降低了空等待的时间,且准确无误。

此外,由于 Queue 的存在,当主线程被其他线程阻塞时,可以将主线程的操作“插队”到 Queue 的头部。当其他线程发起唤醒通知时,主线程可以有更高的优先级,从而降低用户可感知的卡顿

## 2. I/O 性能优化

上面介绍了多线程并发的优化,接下来将介绍 I/O 方面的优化。

### 2.1 mmap

提到 I/O 效率的提升,最容易想到的就是 mmap了,它可以减少数据从 kernel 层到 user 层的数据拷贝,从而提高效率。

SQLite 不仅支持 mmap,而且推荐使用,在大多数平台是在一定程度上默认打开的。然而早期的 iOS 版本的存在一些 bug,SQLite 在编译层就关闭了在 iOS 上对 mmap 的支持,并且后知后觉地在16年1月才重新打开。所以如果使用的 SQLite 版本较低,还需注释掉相关代码后,重新编译生成后,才可以享受上 mmap 的性能。

下图就是 SQLite 注释掉相关代码的 commit
这里写图片描述
开启 mmap 后,SQLite 性能将有所提升,但这还不够。因为它只会对 DB 文件进行了 mmap,而 WAL 文件享受不到这个优化。原因如下:

> 开启 WAL 模式后,写入的数据会先 append 到 WAL 文件的末尾。待文件增长到一定长度后,SQLite 会进行 checkpoint。这个长度默认为1000个页大小,在 iOS 上约为3.9MB。

> 而在多句柄下,对 WAL 文件的操作是并行的。一旦某个句柄将 WAL 文件缩短了,而没有一个通知机制让其他句柄进行更新 mmap 的内容。此时其他句柄若使用 mmap 操作已被缩短的内容,就会造成 crash。而普通的 I/O 接口,则只会返回错误,不会造成 crash。因此,SQLite 没有实现对 WAL 文件的 mmap。

> 显然 SQLite 的设计是针对容量较小的设备,尤其是在十几年前的那个年代,这样的设备并不在少数。而随着硬盘价格日益降低,对于像 iPhone 这样的设备,几 MB 的空间已经不再是需要斤斤计较的了。

> 另一方面,文件重新增长,对于文件系统来说,这就意味着需要消耗时间重新寻找合适的文件块。

**权衡两者,我们可以改为**

  1. 数据库关闭并 checkpoint 成功时,不再 truncate 或删除 WAL 文件,只修改 WAL 的文件头的 Magic Number。下次数据库打开时, SQLite 会识别到 WAL 文件不可用,重新从头开始写入。

  2. 为 WAL 添加 mmap 的支持 有了上面两个优化,整体性能就会提升不少了。

这里我没有贴具体代码需要改哪些地方,一方面是因为改动点较零散,另一方面是代码上的改动并不难。这个优化的工作量主要是在 SQLite 原理和优化点的挖掘上了,大家可以根据优化方案去尝试。

## 3. 其他优化

不过我们还有一些简单易行且效果还不错的小优化,希望可以成为大家打开 SQLite 黑盒的一个契机。

### 3.1 禁用文件锁

如我们在多线程优化时所说,对于 iOS app 并没有多进程的需求。因此我们可以直接注释掉 os_unix.c 中所有文件锁相关的操作。也许你会很奇怪,虽然没有文件锁的需求,但这个操作耗时也很短,是否有必要特意优化呢?其实并不全然。耗时多少是比出来。

SQLite 中有 cache 机制。被加载进内存的 page,使用完毕后不会立刻释放。而是在一定范围内通过 LRU 的算法更新 page cache。这就意味着,如果 cache 设置得当,大部分读操作不会读取新的 page。然而因为文件锁的存在,本来只需在内存层面进行的读操作,不得不进行至少一次 I/O 操作。而我们知道,I/O 操作是远远慢于内存操作的。

### 3.2 禁用内存统计锁

SQLite 会对申请的内存进行统计,而这些统计的数据都是放到同一个全局变量里进行计算的。这就意味着统计前后,都是需要加线程锁,防止出现多线程问题的。

以下 SQLite 内存申请的函数可以看到,当内存统计打开时,会跑代码的第二个 if,malloc 的前后被锁保护了起来。

这里写图片描述

其实这里内存申请的量不大,并不是非常耗时的操作,但却很频繁。多线程并发时,各线程很容易互相阻塞。因为耗时很短,所以被阻塞的时间也很短暂。似乎不会有太大问题。但频繁地阻塞却意味着线程不断地切换,这是个很影响性能的操作,尤其对于单核设备。

因此,如果不需要内存统计的特性,可以通过 sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0)进行关闭。这个修改虽然不需要改动源码,但如果不查看源码,恐怕是比较难发现的。

## 4. 结语

总的来说,移动客户端数据库虽然不如后台数据库那么复杂,但也存在着不少可挖掘的技术点。

这次也只尝试了对 SQLite 原有的方案进行优化,而市面上还有许多优秀的数据库,如 LevelDB、RocksDB、Realm 等,它们采用了和 SQLite 不同的实现原理。后续我们将借鉴它们的优化经验,尝试更深入的优化。

以上就是我今天的分享,谢谢大家。

## 问答环节

### Q1 :前一阵微信提示我微信数据文件发现有损坏,这个是什么原因呢?

> 这个是数据库损坏,SQLite 是以B树结构存储的,如果某一个节点发生损坏,可能导致无法读取数据。损坏的原因多种多样,如断电、文件系统错误、硬盘损坏等。据我所知很多产品都出现了类似问题。

> 你看到的那个是微信的损坏监测和修复逻辑,我们做了自研的工具进行修复。这块我们后续也会分享 db 损坏的监测、保护、修复方案的

### Q2 :请问 sqlite 有时候会出 signal 11的错误,可能是什么原因导致的

> signal 11 就是 SQLITE_CORRUPT,上面提到的数据库损坏的其中一种。另一种是26 SQLITE_NOTADB

### Q3 :请问微信在全文索引上有实践吗?有没有自己做本地的搜索索引

> SQLite 是支持有全文索引的支持的,我们要做的是提供一个好的,支持中文的分词器。

### Q4 :请问微信在 db 文件修复上有什么心得呢?

> 看来大家对 db 文件损坏很关注啊。SQLite 提供了 PRAGMA integrity_check 的工具检测损坏 和 DUMP 工具导出损坏 db。但从实践来看,效果并不理想。我们采用了按 BTree 结构遍历修复的方式,以后有机会可以分享给大家

### Q5 :目前有没有已有的优化过的 sqlite 框架可供使用呢?

> iOS上SQLite 的框架似乎只有 FMDB 和 CoreData,坦白说两个都不是很好。我们是自己封装的 WCDB 框架。

### Q6 :微信的 orm 是怎么搞的

> 通过封装和规范来处理 ORM

### Q7 :请问下多句柄怎么开启,是修改 sqlite 源码后再编译的吗?

> 这个最开始有提到了

> 开启句柄多线程支持的配置 PRAGMA SQLITE_THREADSAFE=2

> 确保同一个句柄同一时间只有一个线程在操作

### Q8 :微信是怎么分析它的锁竞争的?

> 最重要的是读懂源码。辅助手段可以有 SQLite 官方的 Technical/Design Document 和 Instrument 工具

### Q9 :请问有没有对能耗的监测和优化经验?

> 检测相关的我们有卡顿监控系统,可以到我们的公众号 WeMobileDev 上了解

### Q10 :请问 sqlite 优化后有性能对比数据吗,差别有多大?

> 性能数据我以我们的卡顿系统为准,多线程并发优化使得卡顿率从4.08%降至0.19,I/O 优化使得读卡顿从1.50%降至0.20%,写卡顿从1.18%降至0.21%

### Q11 :iOS 客户端用操作数据库需要每次先 open,执行完了再 close,每次都这样,还是 app 只需要开关一次比较好呢?

> 常用的 db 没有必要经常开关,db 占用的内存并不高,可以权衡一下

### Q12 :微信对于本地空间不足会有一个强提醒,这是出于什么考虑?不同机型有不同的策略吗?

> 空间不足是个硬伤,所谓巧妇难为无米之炊。如16GB 的 iPhone,其实很影响正常使用了。不同机型会做细化

### Q13 :请问 sqlite 多线程机制,大概能应付多大量级的数据库操作(基本无卡顿),微信有这方面的测试体验吗,然后是使用了底层代码修改多线程机制后,有大概的提升量级吗?

> 优化的效果我们是以卡顿系统检测到的为准的。能否减少用户感知到的卡顿,优化用户体验才是重点,而不在于能承受多大的量级

### Q14 :微信对于数据库升级有没有特别优化的地方?或者说不同版本的跳版本升级

> 不知道这个问题指的是 SQLite 的升级还是表结构的升级。前者的话,暂时没看到 SQLite 新版本有比较大的特性值得我们跟进。后者可以用 alter table 在封装层支持升级,性能损耗不大

### Q15 :请问微信的 SQLite 有没有开启加密?如果有,性能是否有提升空间?

> iOS 版本目前没有开启加密

### Q16 :微信 sqllite 数据库用的内存数据库吗?那和文件数据库导入导出怎么控制的?

> 没有使用内存数据库

### Q17 :可以问一下,目前做 iOS 版,没有针对 android 版么?

> 这次分享的大部分内容,对Android也是通用的,触类旁通即可。

### Q18 :请问下,句柄开几个比较合适?读写分离开来对性能是否会有提升呢?

> 我们是按需生成新句柄的,并设了上限,若超过上限会有报警。如果同一时间并发量太大的话,其实更多要考虑业务层是否适用得当。至于业务层的使用,若能做细化那自然是更好

微信 SQLite 数据库修复实践 1、前言众所周知,微信在后台服务器不保存聊天记录,微信在移动客户端所有的聊天记录都存储在一个 SQLite 数据库中,一旦这个数据库损坏,将会丢失用户多年的聊天记录。而我们监控到现网的损坏率是0.02%,也就是每 1w 个用户就有 2 个会遇到数据库损坏。考虑到微信这么庞大的用户基数,这个损坏率就很严重了。更严重的是我们用的官方修复算法,修复成功率只有 30%。损坏率高,修复率低,这两个问题都需要我 阅读详情

相关推荐

支持微信分词mmicu全文搜索的sqlite数据库工具

支持微信分词算法mmicu,icu分词的sqlite工具。可以较好的进行全文搜索FullTextSearch

14 | 存储优化(下):数据库SQLite的使用和优化

我们先来复习一下前面讲到的存储方法的使用场景:少量的 Key Value 数据可以直接使用 SharedPreferences,稍微复杂一些的数据类型也可以通过序列化成 JSON 或者 Protocol Buffers 保存,并且在开发中获取或者修改数据也很简单。 不过这几种方法可以覆盖所有的存储场景吗?数据量在几百上千条这个量级时它们的性能还可以接受,但如果是几万条的微信聊天记录呢?而且如何实现快速地对某几个联系人的数据做增删改查呢? 对于大数据的存储场景,我们需要考虑稳定性、性能和可扩展性,这个时候就.

ChinaDragon10的博客 3605

使用TensorFlow搭建FNN(全连接神经网络)的基本步骤

提示:转载请注明出处,若本文无意侵犯到您的合法权益,请及时与作者联系。 目录 一、定义神经网络的输入输出 二、搭建神经网络 1、定义一个神经层中的权重 2、定义一个神经层中的阈值 3、定义一个神经层中的激活函数 4、组合神经层为神经网络 三、搭建损失函数和优化器 1、搭建损失函数 首先介绍第一个函数这其中用到的共同的函数为 2、定义优化器 四、训练神经网络 全连接神经网络的网络结构如下: 一、定义神经网络的输入输出 神经网络最擅长的工作就是模拟非线性函数,即一个复杂的高..

qq_41959920的博客 4070

【腾讯Bugly干货分享】微信iOS SQLite源码优化实践分享实录

SQLite是微信iOS选用的数据库,随着微信iOS客户端业务的增长,在重度用户的场景下,性能瓶颈逐渐显现。靠单纯地修改SQLite的参数配置,已经不能彻底解决问题,因此我们尝试从源码开始做深入的优化。

腾讯Bugly的专栏 4299

基于LSTM语义分析的企业风险预测系统

在数字化时代,企业面临着前所未有的挑战和机遇,而风险管理作为确保企业稳定发展的关键一环,其重要性日益凸显。为了及时、准确地监测和分析企业相关的风险,并预测可能带来的风险,本文介绍了一种基于长短期记忆(LSTM)语义分析的企业风险预测系统。该系统利用深度学习技术,通过将收集到的企业数据进行预处理和分析,结合LSTM模型对文本进行深度语义分析,从而实现对潜在风险的预测和评估。系统设计方面,该系统包括数据预处理、LSTM模型构建与训练、风险预测以及可视化展示等模块。

qiufangtaowvnyyidtf的博客 1392

山东大学软件学院计算机组成原理课程设计实验二

文章目录一、实验时间二、实验内容1.设计异步模16加1计数器2.设计4位移位器3.超前进位16位ALU的设计 一、实验时间 2021年4月1日星期四,第五周 二、实验内容 1.设计异步模16加1计数器 基本功能:使用D触发器(dff元件)和异或门构建从0开始计数的模16加1计数器 对应的电路图(这里已经实现了预置初值的功能) 拓展功能: (1)实现模256加1计数器 (2)实现计数器预置初值的功能 这里复用了上面的模16加1计数器 这里异步触发器预置初值的功能是这样实现的: (1)首先将CLR端调为0,

叶卡捷琳堡的博客 5248

WeChatExporter技术架构深度解析:iOS微信数据提取与可视化方案

在移动应用数据管理领域,微信聊天记录的本地化备份与解析一直是技术实现中的难点。WeChatExporter作为一款开源工具,通过逆向工程iOS微信数据存储机制,实现了聊天记录的完整提取与可视化展示。本文将深入剖析该工具的技术架构、实现原理及应用场景,为开发者提供一套完整的微信数据解析技术方案。 ## 数据提取机制与SQLite逆向分析 微信iOS版本采用SQLite数据库作为核心数据存储方案,

gitblog_00505的博客 435

从Peer到脉冲地震波:免费Python工具全流程配置教程(PyCharm+Anaconda)

本文详细介绍了如何使用Python工具链(PyCharm+Anaconda)实现从Peer数据库获取地震波数据到生成脉冲地震波的全流程配置。通过开源工具EQTOOL和PySeismicGen,结合Python环境搭建、数据格式转换和脉冲地震动生成技术,为结构抗震分析提供高效、灵活的解决方案。

weixin_29093169的博客 430

腾讯开源微信数据库框架WCDB

腾讯开源微信数据库框架WCDBWCDB(WeChat Database)是一个高效、完整、易用的移动数据库框架,基于SQLCipher,支持iOS, macOS和Android。最早期的微信,各个平台除了“使用 SQLite”这个共识,基本各自为政。Android 平台由于 SDK 提供的支持尚可,而且使用 NDK 开发不便,自然选择系统 API 接口进行开发。iOS 情况则有不同。系统提供的Co...

haifangnihao的博客 4893

IEEE投稿完整流程——以IEEE Transactions on Cybernetics为例【附:论文格式模板】

前言 以下是官方的流程,包括了论文的格式和提交的流程,重要!重要!重要! 在IEEE的官网中,也有论文提交的文件 可以直接参考: 中文版: 作者指南 英文版: Manuscripts-Author-Guide 作者指南的版本指导流程可能和最新版的官网不一致!!! 或者在下面的链接中,按照你的论文类型,选择不同的论文模板: IEEE article template 以下以IEEE Transactions on Cybernetics 为例子 IEEE Transactions on Cyberne

XC___XC的博客 10万+

OpenClaw 最强技能 self-improving-agent 详解:让 AI 从错误中自主学习

self-improving-agent 是 OpenClaw 生态中最受欢迎的技能插件,下载量突破 268k。它能让 AI 记住犯过的错误和解决方案,实现持续自我改进。本文深入讲解其工作原理、安装配置和实战案例。测试数据显示:部署流程时间从 15 分钟降到 2 分钟(87%↓),API 调试时间从 2 小时降到 20 分钟,数据库查询编写时间减少 90%。文章包含完整架构图、配置文件示例、3 个详细实战案例和性能测试数据,适合开发者、运维和数据分析师使用。

qq_38610923的博客 3634

【腾讯Bugly干货分享】微信 iOS SQLite 源码优化实践

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58... 作者:张三华 前言 随着微信iOS客户端业务的增长,在数据库上遇到的性能瓶颈也逐渐凸显。在微信的卡顿监控系统上,数据库相关的卡顿不断上升。而在用户侧也逐渐能感知到这种卡顿,尤其是有大量群聊、联系人和消息收...

weixin_33812433的博客 227

IDEA系列(四):IDEA导入Maven工程项目并配置Tomcat启动

本片文章主要介绍如何导入一个存在的maven项目并配置Tomcat启动项目,方便自己使用,也分享出来,希望可以帮助到其他人。

低调D树苗的博客 1243

【Dev Club 分享第七期】微信iOS SQLite源码优化实践

Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师。每周都会举行嘉宾分享,话题讨论等活动。 本期,我们邀请了腾讯WXG iOS 开发工程师——张三华,为大家分享《微信iOS SQLite源码优化实践》。 分享内容简介:SQLite是微信iOS选用的数据库,随着微信iOS客户端业务的增长,在重度用户的场景下,性能瓶颈逐渐显现。靠单纯地

fishmai的专栏 769

基于Simulink的双向DC-DC变换器在储能系统中的应用仿真

摘要:本文详细介绍了基于Simulink的双向DC-DC变换器在光伏储能系统中的仿真实现。主要内容包括:1)采用非隔离型双向Buck-Boost拓扑作为储能系统枢纽;2)针对750V直流微网中的20kWh锂电池接口场景进行建模;3)详细阐述双闭环控制器设计(电压外环+电流内环)、工作模式判断逻辑等关键步骤;4)通过仿真验证了系统在功率阶跃和模式切换下的性能。文章提供了完整的建模流程和控制方法,为储能系统接口设计提供了实用参考。

amy_mhd的博客 178

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

SQLite简单优化之一:源码优化

一:多线程并发优化(Busy Retry 的优化) 开启配置PRAGMA SQLITE_THREADSAFE=2 确保同一个句柄同一时间只有一个线程在操作 二:I/O 性能优化(保留 WAL 文件大小,mmap 优化) 配置PRAGMA mmap_size=XXX即可开启mmap 在WAL文件打开时,用unixMapfile将其映射到内存中,SQLite的OS层即会自动识别,将普通的I/O...

DongStone的专栏 834

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

微信全文搜索优化之路

前言基于本地数据的全文搜索(Full-Text-Search,简称 FTS)在移动应用上扮演着重要角色,与基于服务端提供的搜索服务不同,移动端受硬件条件限制,尤其在数据量相对较大的情况下,搜索性能问题表现得十分突出。本文以移动平台广泛采用的 SQLite FTS Extension 为例,介绍了移动平台 FTS 的基本原理,并结合微信 Android 客户端自身实践,重点讲述微信在 FTS 上的一

mobilehub 1万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

SQLite线程模式探讨

背景 最近微信 iOS 团队发表了一篇文章《微信iOS SQLite源码优化实践》,该文章介绍了微信 iOS 客户端对 SQLite 进行的源码层级的优化,以及其所取得的成果。优化点包括: 多线程并发优化(Busy Retry 的优化)I/O 性能优化(保留 WAL 文件大小,mmap 优化)其他优化(禁用文件锁,禁用内存统计锁) 其中,单是禁用内存统计锁这点优化,就取得了非

窃笑的博客 610

Sqlite优化v2

如果我们在项目中有使用 SQLite,那么下面这个SQLiteDatabaseLockedException就是经常会出现的一个问题。 归根到底是因为并发导致,而 SQLite 的并发有两个维度,一个是多进程并发,一个是多线程并发。下面我们分别来讲一下它们的关键点。多进程并发SQLite 默认是支持多进程并发操作的,它通过文件锁来控制多进程的并发。SQLite 锁的粒度并没有非常细,它针对的是整个 DB 文件。 简单来说,多进程可以同时获取 SHARED 锁来读取数据,但是只有一个进程可以获取 EXCL

麦峰强的博客 1476

OpCore-Simplify:15分钟搞定黑苹果 OpenCore EFI 的完整指南

盯着黑屏的第 4 次,你大概率也这样:对着几百行参数的 config.plist,怀疑是某个布尔值写反了,翻了两小时文档还是找不到线索。这几乎是每个黑苹果新手的第一个夜晚。OpCore-Simplify 就是为这个场景做的黑苹果 OpenCore EFI 自动化生成工具:把传统的手工硬件识别、ACPI 补丁、kext 挑选压缩成一条流水线,你喂给它一份硬件报告,它输出一个可以直接使用的 EFI。

gitblog_00551的博客 373
上一篇: iOS应用UI线程卡顿监控
下一篇: YYImage显示指定区域的webP图片
Philm_iOS
博客等级 码龄8年 74粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值