15-445 Storage
DBMS 的一个设计目标是支持管理超过内存量的数据库。由于相较于读写内存,读写磁盘的开销比较大,因此必须小心地设计,让读写数据库地性能最大化。
文件布局
DMBS 将数据库以特定格式存储在磁盘上的一个或多个文件中,并使用存储管理器(storage manager)进行管理。存储管理器将文件抽象为 Heap File,并将其划分为多个 page,并且维护着一些信息,以此来跟踪读取或写入页面的数据。
Heap File 是存储 page 的无序集合,因此 DBMS 应该提供创建、获取、写入、删除、迭代 page 的接口,一次让上层服务能够有效地利用 page。为了有效地利用 page,有两种管理 page 的方式:链表法(Linked List)和页目录法(Page Directory)
链表法(Linked List)
在该方法中,page 以链表的形式被关联起来了。为了有效地管理这些 page,Heap File 开头维护了一个 header page,用来存储空闲链表(free page list)和数据链表(data page list)的引用。
当我们需要访问页面时 ...
函数过程调用
对于一个过程 (函数 / 方法),必须要支持下面一个或多个机制:
传递控制:自动更新程序计数器 PC 的值
传递数据:提供参数传递和结果返回功能
分配和释放内存:提供内存的分配和释放机制
传递控制
在传递控制部分,我们需要做的事情是自动更新程序计数器 PC 的值,让程序能够按照正确的顺序执行。要做到自动更新 PC 的值,我们需要做到下面两点:
调用过程前将返回地址压栈,以便被调过程返回时能够继续执行。同时将 PC 的值设置为被调函数的首地址值,以便程序能够执行被调函数
被调函数返回时,将返回地址弹栈,并将 PC 的值设置为这个返回地址,以便程序能从调用位置够继续执行
在 x86-64 中,分别使用 call 指令和 ret 指令来实现这两个功能。
数据传递
在过程的调用过程中,后调用的过程一般会先执行完毕,所有程序一般都会使用栈作为数据结构来管理内存。一个过程可能会有许多信息,这部分信息也需要存储在栈上,这一部分称之为栈帧。一个通用栈帧示意图如下图所示。
参数传递
在 x86-64 中,可以通过寄存器最多传递 6 个整型参数,而这些寄存器是有顺序。过程中传递的参数依 ...
cache 简要介绍
概述
随着存储技术的发展,CPU 和主存之间的速度差距已经非常大了。为了弥补 CPU 与主存之间的速度差异,通常会在 CPU 与主存之间添加若干个中间层,这种组织存储器系统的方法被称为存储器层次结构。
在存储器层次结构中,从高层往低层走,存储设备逐渐变慢,存储容量更大,价格更便宜,这一点与存储器制作的材料有关。一般最快的是 L0 缓存中的 CPU 寄存器,其次是基于 SRAM 的高速缓存存储器 L1、L2 等。再往下就是基于 DRAM 的主存存储器,然后是慢速的硬盘。为了使用最小的造价获取最大的收益,上层小而快的设备会作为下层大而慢的设备的缓存,如果所需数据在缓存中,就可以直接从缓存中获取数据。只有当缓存中不存在时,才会访问下层设备,并将数据存放到缓存中。
这样的存储结构之所以是有效的,得益于局部性原理。局部性包括时间局部性和空间局部性:
时间局部性:被引用过一次的内存位置很可能在不远的将来再次被引用
空间局部性:如果一个内存位置被引用了一次,那么程序很可能在不远的价格你来引用附近位置的内存
上层设备与下层设备之间的数据传送是以块(block)为单位的,也就是说如果想要访问 ...
Latex Basic
学习一个工具,一般都是从最简单的开始,所以我们先来打印一个 “Hello, world”
12345678910111213\documentclass{article}% 导言区 可以设置样式% 控制序列以 \ 开头,以第一个空格或非字母字符结束% {article} 表示控制序列有一个必要的参数,该参数的值为 article,% 这个控制序列的作用是调用名为 article 的文档\begin{document}% 只有再 document 环境中的内容,才会被正常输出到文档中去% 或是作为控制序列对文档产生影响Hello, world!\end{document}
\documentclass{article} 中包含了一个控制序列 \xxx,可以影响文档的输出效果。与 \end{document} 一起表示文档范围
documentclass{article} 到 begin{document} 之间是导言区, ...
PicGo + Github 作为图床
PicGo 简介
图床一般指存储图片的服务器,同时还允许将图片对外公开。PicGo 是一款用 Electron-vue 开发的软件,可以支持微博,七牛云,腾讯云 COS,又拍云,GitHub,阿里云 OSS,SM.MS,imgur 等 8 种常用图床,功能强大,简单易用。
这里是最新版本的项目发布地址:
https://github.com/Molunerfinn/PicGo/releases
创建流程
首先,我们需要在 Github 上创建一个仓库,作为存储的服务器(注意,一定要创建公共仓库,否则无法通过外链显示)。然后,我们需要生成一个 token,点击头像 --> setting --> Developer settings,选择 Personal access tokens。Note 等相关信息随便填写,然后生成 token,一定要记住 token,后面会用到的。
接下来我们打开 PicGo,找到 GitHub 图床,填入按照格式填入内容
仓库名称:github 用户名/仓库名称
分支:一般填写 main,如果是 master 填写 master
token: ...
Integer 缓存问题分析
在《阿里巴巴Java开发手册》中有一段关于包装类之间值比较问题的规范:
【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
说明:对于 Integer var = ? 在 - 128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产 生,会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
我们来看一段代码
12345public static void main(String[] args) { Integer a = 127, b = 127, c = 128, d = 128, System.out.println(a == b); System.out.println(c == d);}
true
false
为什么会这样呢?在 Integer var = ? 这个过程发生了什么才会造成这样的结果呢?
通过调试,发现 ...
8086 给出物理地址的方法
以下内容来自于《汇编语言》(第三版)
8086CPU 有 20 位地址总线,可以传送 20 位地址,达到 1MB 寻址能力。但是 8086CPU 是 16 位结构,在内部一次性处理、传输、暂时存储的地址为 16 位。从 8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出 16 位地地址,表现出地寻址能力只有 64KB。
8086CPU采用一种在内部用两个 16 位地址合成的方法来形成一个 20 位的物理地址。8086CPU 相关部件的逻辑结构如图所示
CPU中相关部件提供两个 16 位的地址,一个称为段地址,另一个称为偏移地址。段地址和偏移地址通过内部总线送入一个称为地址加法器的部件。地址加法器将两个 16 位地址合成为一个 20 位的物理地址,然后通过内部总线将 20 位物理地址送入输入输出控制电路。然后输入输出控制电路将 20 位物理地址送上地址总线,这 20 位物理地址就被地址总线传送到了存储器。
地址加法器采用 物理地址 = 段地址 * 16 + 偏移地址(给常用的说法是 段地址左移 4 位 + 偏移地址)的方法将段地址与偏移地址进行合成。比如 8086 ...
Java 接口初始化
学习学习类初始化的时候看到了下面关于接口的两大结论:
在初始化一个类时,并不会初始化它所实现的接口
在初始化一个接口时,并不会先初始化它的父接口
因为接口中的变量都是 public static final 的,所以我一直在想,如何才能让接口初始化呢。直到我看到了网上的一个例子:
12345678910111213141516171819202122public class InterfaceTest { public static void main(String[] args) { System.out.println(Parent.thread); }}interface Parent { public static final int a = 1; public static Thread thread = new Thread(){ { System.out.println(a); } }; public static Thread thread2 = new Thre ...
关于 Java 类初始化顺序的思考
最近在学习Java类的加载机制遇到了这样的一个题目
123456789101112131415161718192021222324public class InitializeOrder { public static void main(String[] args) { Singleton singleton = Singleton.getInstance(); System.out.println("counter1: " + Singleton.counter1); System.out.println("counter2: " + Singleton.counter2); }}class Singleton { public static int counter1; public static int counter2 = 0; private static Singleton singleton = new Singleton(); private Singleton() ...
Hello World
文章设置
文章封面
在 markdown 文件中的 Front-matter 添加 cover。如果不配置,可以设置显示默认的 cover
12title: Hello Worldcover: https://cdn.jsdelivr.net/gh/jerryc127/CDN@latest/cover/default_bg.png
显示目录
可以在主题文件中配置,也可以在特定页面的 Front-matter 添加 toc_number 和 toc 进行配置。主题会优先判断文章的配置
文章内容
标签外挂
1234567{% hideInline content,display,bg,color %}{% hideBlock display,bg,color %}content{% endhideBlock %}{% hideToggle display,bg,color %}content{% endhideToggle % ...