网易首页 > 网易号 > 正文 申请入驻

让 Node.js 变“懒”的 COW 技术

0
分享至

作者:神说要有光来源: 神光的编程秘籍

COW 不是奶牛,是 Copy-On-Write 的缩写,这是一种是复制但也不完全是复制的技术。

一般来说复制就是创建出完全相同的两份,两份是独立的:

但是,有的时候复制这件事没多大必要,完全可以复用之前的,这时候可以只是引用之前的那份,在写内容的时候才去复制对应的一部分内容。这样如果内容用于读的话,就免去了复制,而如果需要写,才会真正复制部分内容来做修改。

这就叫做“写时复制”,也就是 Copy-On-Write。

原理很简单,但是在操作系统的内存管理和文件系统中却很常见,Node.js 里面也因为这种技术变“懒”了。

本文我们来探究下 Copy-On-Write 在 Node.js 的进程创建和文件复制的应用:

文件复制

文件复制这件事最常见的思路就是完全写一份相同的文件内容到另一个位置,但是这样有两个问题:

  • 完全写一份相同的内容,如果同样的文件复制了几百次,那么也创建相同的内容几百次么?太浪费硬盘空间了
  • 如果写到一半断电了怎么办?覆盖的内容如何恢复?

怎么办呢?这时候操作系统设计者就想到了 COW 技术。

用 COW 技术实现文件复制以后完美解决了上面两个问题:

  • 复制只是添加一个引用到之前的内容,如果不修改并不会真正复制,只有到第一次修改内容的时候才去真正复制对应的数据块,这样就避免了大量硬盘空间的浪费。
  • 写文件时会先在另一个空闲磁盘块做修改,等修改完之后才会复制到目标位置,这样就不会有断电无法回滚的问题

在 Node.js 的 fs.copyFile 的 api 就可以使用 Copy-On-Write 模式:

默认情况下,copyFile 会写入目标文件,覆盖原内容

const fsPromises = require('fs').promises;
(async function() {
try {
await fsPromises.copyFile('source.txt', 'destination.txt');
} catch(e) {
console.log(e·message);

但是可以通过第三个参数指定复制的策略:

const fs = require('fs');
const fsPromises = fs.promises;
const { COPYFILE_EXCL, COPYFILE_FICLONE, COPYFILE_FICLONE_FORCE} = fs.constants;
(async function() {
try {
await fsPromises.copyFile('source.txt', 'destination.txt', COPYFILE_FICLONE);
} catch(e) {
console.log(e·message);

支持的 flag 有 3 个:

  • COPYFILE_EXCL: 如果目标文件已存在,会报错(默认是覆盖)
  • COPYFILE_FICLONE: 以 copy-on-write 模式复制,如果操作系统不支持就转为真正的复制(默认是直接复制)
  • COPYFILE_FICLONE_FORCE:以 copy-on-write 模式复制,如果操作系统不支持就报错

这3个常量分别是 1,2,4,可以通过按位或把它们合并之后传入:

const flags = COPYFILE_FICLONE | COPYFILE_EXCL;
fsPromises.copyFile('source.txt', 'destination.txt', flags);

Node.js 支持操作系统的 copy-on-write 技术,在一些场景下可以提升性能,建议使用 COPYFILE_FICLONE 的方式,会比默认的方式好一些。

进程创建

fork 是常见的创建进程的方式,而它的实现就是一种 copy-on-write 技术。

我们知道,进程在内存中分为代码段、数据段、堆栈段这 3 部分:

  • 代码段:存放要执行的代码
  • 数据段:存放一些全局数据
  • 堆栈段:存放执行的状态

如果基于该进程创建一个新的进程,那么要复制这 3 部分内存。而如果这三部分内存是一样的内容,那就浪费了内存空间。

所以 fork 并不会真正的复制内存,而是创建一个新的进程,引用父进程的内存,当做数据的修改的时候,才会真正复制该部分的内存。

这也是为什么把进程创建叫做 fork,也就是分叉,因为不完全是独立的,只是某部分做了分叉,成了两份,但是大部分还是一样的。

但如果要执行的代码不一样怎么办呢,这时候就要用 exec 了,它会创建新的代码段、数据段、堆栈段、执行新的代码。

Node.js 里面同样可以用 fork 和 exec 的 api:

fork:

const cluster = require('cluster');
if (cluster·isMaster) {
console.log('I am master');
cluster.fork();
cluster.fork();
} else if (cluster·isWorker) {
console.log(`I am worker #${cluster.worker.id}`);

exec:

const { exec } = require('child_process');
exec('my.bat', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
console.log(stdout);

fork 是 linux 进程创建的基础,由此可见 copy-on-write 技术多么重要了。

总结

复制同样的内容多份无疑比较浪费空间,所以操作系统在做文件复制、进程创建时的内存复制的时候都采用了 Copy-On-Write 技术,只有真正修改的时候才会去做复制。

Node.js 支持了 fs.copyFile 的 flags 的设置,可以指定 COPYFILE_FICLONE 来使用 Copy-On-Write 的方式做文件复制,也建议大家使用这种方式来节省硬盘空间,提高文件复制的性能。

进程的 fork 也是 Copy-On-Write 的实现,并不会直接复制进程的代码段、数据段、堆栈段到新的内容,而是引用之前的,只有在修改的时候才会做真正的内存复制。

除此以外,Copy-On-Write 在 Immutable 的实现,在分布式的读写分离等领域都有很多应用。

COW 让 Node.js 变“懒”了,但性能却更高了。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
汪小菲官宣三胎生子!晒马筱梅和小宝贝合影,爷爷抱着他爱不释手

汪小菲官宣三胎生子!晒马筱梅和小宝贝合影,爷爷抱着他爱不释手

TVB的四小花
2026-02-24 16:45:39
拖了十年不发证?C919收起讨好硬刚欧美适航霸权,直接掀桌改规则

拖了十年不发证?C919收起讨好硬刚欧美适航霸权,直接掀桌改规则

刘旷
2026-02-22 12:51:46
春节返工高速大堵车,成都女子搭顺风车至广州耗时42小时,坐到腿部肿胀病情复发

春节返工高速大堵车,成都女子搭顺风车至广州耗时42小时,坐到腿部肿胀病情复发

极目新闻
2026-02-24 18:14:46
突发!两日本车企被我国列入“出口管制”关注名单!

突发!两日本车企被我国列入“出口管制”关注名单!

电动知家
2026-02-24 13:44:19
大风追踪|河南15岁女孩被当街殴打,母亲再发声:女儿伤情鉴定轻伤二级,苏醒后一直默默流泪

大风追踪|河南15岁女孩被当街殴打,母亲再发声:女儿伤情鉴定轻伤二级,苏醒后一直默默流泪

大风新闻
2026-02-24 11:52:06
2026年,看电视不用再交“月租”了!这几种方法,合法还免费

2026年,看电视不用再交“月租”了!这几种方法,合法还免费

小柱解说游戏
2026-02-24 06:38:45
一个月跌了三分之一,寒武纪今天盘中又闪崩,买了你就没开心过!

一个月跌了三分之一,寒武纪今天盘中又闪崩,买了你就没开心过!

财经智多星
2026-02-24 16:27:20
22岁谷爱凌:我有个想法,但我不敢说,要做个动作成女子历史第1

22岁谷爱凌:我有个想法,但我不敢说,要做个动作成女子历史第1

风过乡
2026-02-24 10:45:07
返程被堵高速,发现应急车道被占用,女子挨个拍照,半小时举报20多辆车,当事人发声:不能让守规矩的人吃亏;交警回应:处理中

返程被堵高速,发现应急车道被占用,女子挨个拍照,半小时举报20多辆车,当事人发声:不能让守规矩的人吃亏;交警回应:处理中

每日经济新闻
2026-02-24 18:36:05
恭喜筱梅生了小马宝!宝宝白白胖胖,大眼睛,高鼻梁,非常可爱!

恭喜筱梅生了小马宝!宝宝白白胖胖,大眼睛,高鼻梁,非常可爱!

离离言几许
2026-02-24 11:48:01
墨西哥贩毒集团报复行动已致73死,目前未收到中国公民受伤信息,骚乱地华人:毒贩烧掉汽车拦路,街上空无一人

墨西哥贩毒集团报复行动已致73死,目前未收到中国公民受伤信息,骚乱地华人:毒贩烧掉汽车拦路,街上空无一人

极目新闻
2026-02-24 18:14:46
被「中国钓王」邓刚认证的钓鱼神车,吉利银河翼真L380到底是什么来路?

被「中国钓王」邓刚认证的钓鱼神车,吉利银河翼真L380到底是什么来路?

AutoBusiness
2025-09-05 11:47:55
特朗普发AI视频,化身美国冰球运动员,赤手空拳殴打加拿大运动员,圆梦“拿下加拿大”;此前特朗普称:我想让加拿大成第51个州

特朗普发AI视频,化身美国冰球运动员,赤手空拳殴打加拿大运动员,圆梦“拿下加拿大”;此前特朗普称:我想让加拿大成第51个州

大风新闻
2026-02-24 15:02:04
最后通牒到期直接动手 巴拿马政府强行接管长和港口 员工被令“不得与公司沟通”

最后通牒到期直接动手 巴拿马政府强行接管长和港口 员工被令“不得与公司沟通”

圆维度
2026-02-24 12:38:14
乌媒:俄乌冲突爆发4周年,泽连斯基首次展示冲突初期所使用地下掩体

乌媒:俄乌冲突爆发4周年,泽连斯基首次展示冲突初期所使用地下掩体

环球网资讯
2026-02-24 17:12:54
奥运冠军“拉拉链露胸”,让耐克绷不住了!

奥运冠军“拉拉链露胸”,让耐克绷不住了!

品牌营销报
2026-02-23 11:31:10
上海市公安局公开招聘1100名辅警

上海市公安局公开招聘1100名辅警

警民直通车上海
2026-02-24 12:37:20
美国只有3亿人,为何消费力能远超中国14亿人?现在全“露馅”了

美国只有3亿人,为何消费力能远超中国14亿人?现在全“露馅”了

青橘罐头
2026-02-24 07:05:49
返程路上女子被丈夫丢在服务区,当场崩溃!丈夫:没发现,很懊悔

返程路上女子被丈夫丢在服务区,当场崩溃!丈夫:没发现,很懊悔

半岛晨报
2026-02-24 15:51:26
26岁男子春节离家失联5天,山中发现外套!父亲:事前曾去奶奶坟前,手机留“遗言”

26岁男子春节离家失联5天,山中发现外套!父亲:事前曾去奶奶坟前,手机留“遗言”

红星新闻
2026-02-24 13:12:52
2026-02-24 19:52:49
Nodejs开发
Nodejs开发
分享只有程序员懂的干货
648文章数 823关注度
往期回顾 全部

科技要闻

AI颠覆发展最新牺牲品!IBM跳水重挫超13%

头条要闻

20家日本实体被列入管制名单 中方:完全正当 合理合法

头条要闻

20家日本实体被列入管制名单 中方:完全正当 合理合法

体育要闻

苏翊鸣总结米兰征程:我仍是那个热爱单板滑雪的少年

娱乐要闻

汪小菲官宣三胎出生:承诺会照顾好3个孩子

财经要闻

县城消费「限时繁荣」了十天

汽车要闻

入门即满配 威兰达AIR版上市 13.78万元起

态度原创

亲子
手机
本地
数码
军事航空

亲子要闻

萌娃质问老爸:妈妈为什么嫁给你,老爸的回答竟让萌娃面露难色

手机要闻

iQOO 15R发布,这配置能打吗?

本地新闻

春花齐放2026:《骏马奔腾迎新岁》

数码要闻

宜鼎推出CXL AIC扩展卡:可为兼容设备扩展最大256GB内存

军事要闻

美军参联会主席警告:对伊朗动武可能带来重大风险

无障碍浏览 进入关怀版