深入理解Swift编译原理 – Swift源码编译
Swift - 踩坑集锦
记录使用Swift的时候遇到的一些奇葩问题。
ARM64汇编分析常用指令、寄存器
ARM64 汇编快速查阅表 – 持续更新…
理解C++内存排序和可见性
本文主要总结了C++在原子操作上的内存模型以及内存排序标准。
相对来说,C++已经是比较接近系统底层的语言了,C++设计也是希望如此,毕竟它本身已经如此复杂了。在C++ 11的标准里,推出了非常多的新特性,它们让C++变得非常灵活,而它们都依赖于标准里的多线程内存模型。但可能大部分的开发者都不知道这些,因为一般情况下,他们只需要通过mutex这一类高级的同步锁,来在多线程下解决数据竞争问题。至于这些锁是如何实现的,对他们来说并不重要。但是如果要接触到更底层的原理,或需要编写lock-free数据结构,亦或者是需要做更高性能的优化时,那么我们就需要理解这些更接近「机器语言」的数据结构和设计。有时候,一些原子类型或者原子操作,甚至可以让代码缩减到只有1-2个CPU指令。
WAL Mode
在版本为release 3.7.0的版本上,SQLite介绍了一种新的日志机制,叫WAL日志。这个日志模式与传统回滚日志模式二选一。可以通过pragma journal_mode=WAL指令来开启这个模式。当数据库在WAL模式下(在Pager文章内提到,日志文件的头偏移量处于18位置的值是2),SQLite就会完全使用WAL日志了。在wal日志模式下,日志文件的名字和数据库的名字一样,后面紧跟’-wal’后缀,并且会与原始数据库文件存在于同一个目录下。
Storage
本文讨论了SQLite如何在最底层,组织数据库内容和日志文件内容。它定义了这些文件的格式。将一整个数据库文件划分为固定大小的页面,这些页面用来存储B/B+树页面,空闲页面,和其他页面。在默认的日志模式下,日志文件将数据库页面的镜像前内容存储为日志记录;但是,在WAL日志模式式下,日志文件存储了数据库页面的更新后的镜像内容。
Transaction Management
数据库管理系统的主要任务就是帮助用户在数据库上操作和存储数据。另外,DBMS还需要在用户的并发调用下保护数据库,以及在应用的崩溃,系统崩溃,系统掉电的情况下保持数据库的一致性。出于这些目的,DBMS在一个抽象的事务中执行所有的数据库操作。对于保持数据库的一致性来说,事务管理非常关键。SQLite依赖原生的文件锁,并且实现了页面日志来实现ACID。SQLite只支持一级事务,也就是说不支持事务嵌套。本文讨论了SQLite是如何实现了事务的ACID,从而更新单个和多个数据库。
Pager那一篇文章会解释SQLite事务管理器pager的内部工作原理。
The Pager Module
本文讨论的是SQLite的Pager模块。本模块在原生操作系统的基础上实现了一个抽象的基于页面的数据库文件系统。它按照固定大小的页面来管理数据,并且定义了一些接口从数据库文件中来操作这些页面。它提供了一个数据库页面的内存缓存,来帮助BTree模块加速操作数据库页面。它不仅仅是一个缓存的管理中心,同样也是实现ACID的事务管理中,以及事务回滚管理。并发控制和回滚机制对于上层模块来说是完全透明的。他可以理解为一个传统数据库管理系统的持久化层。
SQLite--Tokenize(词法分析器)
SQLite的词法分析器的代码逻辑其实很简单,但是其中也不乏SQLite对于执行效率的优化。甚至可以说SQLite在追求高效的每一个细节点,都无所不用其极。文章从源码的角度分别看具体的实现逻辑与优化的细节
SQLite--KeywordHash
SQLite 的关键字有很多个(在3.27.2版本就支持136个)。从用户侧输入一个SQL语句到Tokenize(词法分析器)的时候,SQLite如何快速判断一个单词是否是关键字呢?第一想法肯定是利用哈希表,SQLite也确实是如此。但是如何构建一个查询高效,存储占用低,而且还支持关键字”裁剪”的哈希表呢?这里从源码的角度来看,SQLite是如何一步一步的精简优化一个词法分析器的关键字查询表的。