COW

虚拟内存[02] Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈【转】

泄露秘密 提交于 2020-04-28 12:39:06
转自: https://durant35.github.io/2017/10/29/VM_Stacks/  Linux 中有几种栈?各种栈的内存位置? 关于栈 函数调用栈的典型内存布局 栈帧 (Stack Frame) 的边界由栈帧基地址指针 EBP 和 栈指针 ESP 界定, EBP 指向当前栈帧底部 (高地址),在当前栈帧内位置固定; ESP 指向当前栈帧顶部 (低地址); 当程序执行时, ESP 会随着数据的入栈和出栈而移动,因此函数中对大部分数据的访问都基于 EBP 进行。 栈帧存放着 参数 , 局部变量 及 恢复前一栈帧所需要的数据 等。 进程栈  进程虚拟地址空间中的栈区,正指的是我们所说的 进程栈 。 进程栈 是属于用户态栈,和 进程虚拟地址空间 (Virtual Address Space) 密切相关。 图: 32 位系统下进程地址空间默认布局(左)和进程地址空间经典布局(右)   进程栈 的初始化大小是由编译器和链接器计算出来的,但是栈的实时大小并不是固定的,Linux 内核会根据入栈情况对栈区进行动态增长(其实也就是添加新的页表)。但是并不是说栈区可以无限增长,它也有最大限制 RLIMIT_STACK (一般为 8M),我们可以通过 ulimit 来查看或更改 RLIMIT_STACK 的值 ( stack size ): 1 2 3 4 5 6 7 8 9

国产数据库存储引擎X-Engine的科研之路

喜你入骨 提交于 2020-04-23 04:58:20
X-Engine是阿里云RDS MySQL 的存储引擎之一,基于Log-structured Merge Tree (LSM-tree),较基于 B-tree 一族的其它存储引擎而言年轻很多,所以在实践中遇到问题也更多,对研究的需求也更大。 LSM-tree是1996 年美国计算机科学家 Patrick O'Neil 等人提出的一种数据结构,和 B-tree 相比,它拥有更快的写入性能和层次化的存储结构,能够同时利用好 DRAM 内存的高性能和持久化存储的高容量。尤其是 LSM-tree 的分层存储结构,可以天然地利用数据局部性将热数据和冷数据区别开,方便压缩算法有的放矢,有机会在降低整体成本的情况下,实现同样优秀的性能。但是,与几乎所有的计算机数据结构和系统设计一样,有得必有失。LSM-tree 难以避免的在读性能、I/O 写放大和空间效率上面对挑战。 01、写路径上的罗生门 首先,LSM-tree 使用了能够支持快速写入的 copy-on-write (CoW)方式来存储新增数据。顾名思义,假如要使用 CoW 来更新一条记录,不需要定位存储引擎中该条记录的地址并将它读取出来,只需要直接将我要更新的内容(例如,key = 100, value = value +100)写入内存和日志(直接写磁盘)即可。 这样整个写入操作就像记日记一样

老白学编程

夙愿已清 提交于 2020-04-22 23:03:33
NetData plugin 之 proc Netdata 的数据采集都是通过各个plugin来进行的。找几个有代表性的plugin来看看。 概述 该plugin 顾名思义, 是针对于类Linux系统(BSD有单独的plugin), 通过读取 /proc 下面的数据来进行采集。 列表 先列一下都有哪些项。 文件 说明 /proc/stat 系统和内核的统计信息 /proc/uptime 系统运行时间 /proc/loadavg 负载 /proc/sys/kernel/random/entropy_avail 熵池大小,单位bit /proc/pressure 参考一下 psi /proc/interrupts 中断表 /proc/softirqs 系统软中断信息 /proc/vmstat 虚拟内存统计信息 /proc/meminfo 当前内存信息 /sys/kernel/mm/ksm ksmd 类似一个COW机制 /sys/block/zram 虚拟内存的压缩 /sys/devices/system/edac/mc EDAC即error detection and correction(错误检测与纠正) /sys/devices/system/node numa node 信息 /proc/pagetypeinfo 伙伴系统信息 /proc/net/dev 网络适配器统计信息

国产数据库存储引擎X-Engine的科研之路

旧城冷巷雨未停 提交于 2020-04-21 18:58:57
X-Engine是阿里云RDS MySQL 的存储引擎之一,基于Log-structured Merge Tree (LSM-tree),较基于 B-tree 一族的其它存储引擎而言年轻很多,所以在实践中遇到问题也更多,对研究的需求也更大。 LSM-tree是1996 年美国计算机科学家 Patrick O'Neil 等人提出的一种数据结构,和 B-tree 相比,它拥有更快的写入性能和层次化的存储结构,能够同时利用好 DRAM 内存的高性能和持久化存储的高容量。尤其是 LSM-tree 的分层存储结构,可以天然地利用数据局部性将热数据和冷数据区别开,方便压缩算法有的放矢,有机会在降低整体成本的情况下,实现同样优秀的性能。但是,与几乎所有的计算机数据结构和系统设计一样,有得必有失。LSM-tree 难以避免的在读性能、I/O 写放大和空间效率上面对挑战。 01、写路径上的罗生门 首先,LSM-tree 使用了能够支持快速写入的 copy-on-write (CoW)方式来存储新增数据。顾名思义,假如要使用 CoW 来更新一条记录,不需要定位存储引擎中该条记录的地址并将它读取出来,只需要直接将我要更新的内容(例如,key = 100, value = value +100)写入内存和日志(直接写磁盘)即可。 这样整个写入操作就像记日记一样

【POJ

寵の児 提交于 2020-04-21 08:02:09
Cleaning Shifts Descriptions: 原文是English,我这就直接上Chinese了,想看原文的点一下链接哦 大表哥分配 N (1 <= N <= 25,000) 只中的一些奶牛在牛棚附近做些清洁。 他总是要让至少一只牛做清洁。他把一天分成T段(1 <= T <= 1,000,000), 第一段是1,最后一段是T 每只奶牛只在一些时间段有空。奶牛如果选择某一段时间,则必须完成整段时间的工作 你的任务是帮助FJ安排一些奶牛,使每段时间至少有一只奶牛被安排来做这件事。并且奶牛数应尽可能小。如果不可能办到,输出-1 Input 注意,输入包含多组测试数据,请处理到文件结束 * 第一行:N和T * 第二行至N+1行: 每一行包括奶牛能工作的开始和结束时间。闭区间。 Output *每组数据一行,输出完成清洁所需最少的奶牛数,如果不可能办到,输出-1 Sample Input 3 10 1 7 3 6 6 10 Sample Output 2 题目链接: https://vjudge.net/problem/POJ-2376 给定N个小区间以及区间起点终点,求能用它们覆盖区间[1,T]的最小组合。 贪心策略是从左往右,尽量选择长度最大的区间。 首先对所有奶牛排序,按照开始时间排序。 然后更新起点=终点+1,搜索剩下的奶牛中能够覆盖这个起点同时终点最远的那一头

实战|使用Spark Streaming写入Hudi

你。 提交于 2020-04-19 10:02:56
1. 项目背景 传统数仓的组织架构是针对离线数据的OLAP(联机事务分析)需求设计的,常用的导入数据方式为采用sqoop或spark定时作业逐批将业务库数据导入数仓。随着数据分析对实时性要求的不断提高,按小时、甚至分钟级的数据同步越来越普遍。由此展开了基于spark/flink流处理机制的(准)实时同步系统的开发。 然而实时同步数仓从一开始就面临如下几个挑战: 小文件问题。不论是spark的microbatch模式,还是flink的逐条处理模式,每次写入HDFS时都是几M甚至几十KB的文件。长时间下来产生的大量小文件,会对HDFS namenode产生巨大的压力。 对update操作的支持。HDFS系统本身不支持数据的修改,无法实现同步过程中对记录进行修改。 事务性。不论是追加数据还是修改数据,如何保证事务性。即数据只在流处理程序commit操作时一次性写入HDFS,当程序rollback时,已写入或部分写入的数据能随之删除。 Hudi是针对以上问题的解决方案之一。以下是对Hudi的简单介绍,主要内容翻译自官网。 2. Hudi简介 2.1 时间线(Timeline) Hudi内部按照操作时刻(instant)对表的所有操作维护了一条时间线,由此可以提供表在某一时刻的视图,还能够高效的提取出延后到达的数据。每一个时刻包含: 时刻行为:对表操作的类型,包含: commit:提交

Linux 中的零拷贝技术 (二) 转

依然范特西╮ 提交于 2020-04-17 17:52:12
传统IO拷贝流程  比如:读取文件,再用socket发送出去  先读取、再发送,实际经过1~4四次copy。   1、第一次:将磁盘文件,读取到操作系统内核缓冲区;   2、第二次:将内核缓冲区的数据,copy到application应用程序的buffer;   3、第三步:将application应用程序buffer中的数据,copy到socket网络发送缓冲区(属于操作系统内核的缓冲区);   4、第四次:将socket buffer的数据,copy到网卡,由网卡进行网络传输。            图 1. 传统使用 read 和 write 系统调用的数据传输   传统方式,读取磁盘文件并进行网络发送,经过的四次数据copy是非常繁琐的。实际IO读写,需要进行IO中断,需要CPU响应中断(带来上下文切换),尽管后来引入DMA来接管CPU的中断请求,但四次copy是存在“不必要的拷贝”的。 题外话:什么是DMA?   其实DMA技术很容易理解,本质上,DMA技术就是我们在主板上放⼀块独立的芯片。在进行内存和I/O设备的数据传输的时候,我们不再通过CPU来控制数据传输,而直接通过 DMA控制器(DMA?Controller,简称DMAC)。这块芯片,我们可以认为它其实就是一个协处理器(Co-Processor)) Linux 下实现零拷贝的几种方式介绍 Linux 中的直接 I

Redis核心原理与应用实践

◇◆丶佛笑我妖孽 提交于 2020-04-16 11:09:16
【推荐阅读】微服务还能火多久?>>> Redis核心原理与应用实践 在很多场景下都会使用Redis,但是到了深层次的时候就了解的不是那么深刻,以至于在面试的时候经常会遇到卡壳的现象,学习知识要做到系统和深入,不要把Redis想象的过于复杂,和Mysql一样,是个读取数据的软件。 有一个理解是Redis是key value缓存服务器,更多的优点在于对value的操作更加丰富。 安装 yum install redis #yum安装 brew install redis # brew安装 redis-cli Redis 基础数据结构 Redis 有 5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。 string (字符串) Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图中所示,内部为当前字 符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时, 扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是 字符串最大长度为 512M。 键值对 set name codehole get name 批量键值对

谈谈 Copy-On-Write 容器

女生的网名这么多〃 提交于 2020-04-14 16:08:16
【推荐阅读】微服务还能火多久?>>> 1、简介 Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。 CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。 2、CopyOnWriteArrayList的实现原理 在使用CopyOnWriteArrayList之前,我们先阅读其源码了解下它是如何实现的。以下代码是向ArrayList里添加元素,可以发现在添加的时候是需要加锁的,否则多线程写的时候会Copy出N个副本出来。

每天3分钟操作系统修炼秘籍(27):Linux进程的创建

試著忘記壹切 提交于 2020-04-13 20:22:02
【今日推荐】:为什么一到面试就懵逼!>>> 点我查看秘籍连载 Linux进程的创建 在Linux中,除了pid=1的init进程外,所有进程都有父进程,父子进程以树型结构的方式存在,父进程创建出来的多个子进程之间称为兄弟进程。 在Linux中,使用fork()系统调用来创建一个新进程,调用fork()的进程是父进程,新创建出来的进程是子进程。注意:只有操作系统有权限创建进程,其它程序要想创建进程都只能通过发送fork()系统调用请求内核帮忙创建。 fork()是一个非常"奇怪"的调用,因为从fork开始就有了两个进程分支——父和子进程,fork的奇怪之处在于它对父子进程的返回值不同:对子进程返回0,对父进程返回子进程的PID。借助不同的返回值,可以判断哪个是父进程分支,哪个是子进程分支。 也许,通过代码来演示创建子进程的过程是最直观的。这里使用shell伪代码来演示,以便没有任何编程基础的人也能看懂这个过程。但是注意,shell并没有提供fork命令,所以这里的fork是假设它存在的。 pid=$(fork) # 从此开始,有两个进程分支 # 将fork的返回值(假设返回值就是fork伪命令的输出结果)赋值给pid变量 # fork对父进程的返回值是子进程的PID属性,是大于0的数值,所以父进程的pid变量大于0 # fork对子进程的返回值是0,所以子进程的pid变量等于0 #