这是我参与更文挑战的第20天,活动详情查看: 更文挑战
原理
- 为什么是单线程
- 事件循环
I/O延迟
L1 | 3 cycles |
L2 | 14 cycles |
RAM | 250 cycles |
Disk | 41,000,000 |
Network | 240,000,000 |
为什么是单线程
- 轻量
- 简化并发模型,无死锁
- 没有线程切换开销
事件循环
一次完成一个任务直到运行完成
Macrotask/Microtask
Macrotask Queue
Script标签、setTimeout、setinterval、setImmediate、requestAnimationFrame、I/O、UI渲染、异步ajax、用户事件、message channel
Microtask Queue
process.nextTick、Promise、Object.observe、
MutationObserver
例外
alert()、prompt()、confirm()
Sync AJAX
意外的多线程表现
setTimeout(() => {
console.log('before alert');
alert('Pause');
console.log('after alert');
},100);
window.addEventListener('resize', () => {
console.log('resize');
})
/*
before alert
after alert
resize
*/
/*
before alert
resize
after alert
*/
复制代码
window下,改小分辨率;
linux 下直接调整浏览器窗口尺寸。
异步事件同步触发
const input1 = document.getElementById('input1');
const input2 = document.getElementById('input2');
input1.addEventListener('blur',() => {
console.log('blur');
});
setTimeout(() => {
console.log('before');
input2.focus();
console.log('after');
},100);
input1.focus();
/*
before
after
blur
*/
/*
before
blur
after
*/
复制代码
运行时特性
- Web Worker
- Service Worker
- Child_process(Node.js)
- Cluster(Node.js)
web worker
-
真正的多线程
-
不共享内存,线程安全
-
通过message channel传递数据
-
无法使用window和document对象
// main.js
function run() {
const worker = new Worker('bigLoop.js');
worker.postMessage('start');
worker.onmessage = result => {
console.log(result);
worker.terminate();
};
}
run();
run();
run();
run();
console.log('hello world');
复制代码
// bigLoop.js
onmessage = () => {
let j = 0;
for (let i = 0; i<=1000000000; i+=1) {
j += i;
j *= -1;
}
postMessage(j);
};
复制代码
service worker
-
充当页面与服务器之间的网络代理
-
具有web worker 的特点
-
仅支持https
-
独立于页面存在
Child_process
-
支持子进程
-
通过IPC通道进行进程间通信
// parent.js
const {fork} = require('child_process');
const child = fork('./child.js');
child.on('message',m => {
console.log(`message from child:${JSON.stringify(m)}`)
});
child.send({from: 'parent'});
复制代码
// child.js
process.on('message', m => {
console.log(`message from parent: ${JSON.stringify(m)}`);
});
process.send({from: 'child'});
复制代码
cluster
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if(cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for(let i = 0; i < numCPUs; i++){
cluster.fork();
}
cluster.on('exit',worker => {
console.log(`worker ${worker.process.pid} died`);
});
}
else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req,res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
复制代码
延申
-
webGL
-
Web Assembly
-
Node.js C++ Addon
WebGL
加速矩阵运算示例
import GPU from 'gpu.js';
const gpu = new GPU();
const multiplyMatrixGPU = gpu.createKernel(function (a,b) {
let sum = 0;
for (let i = 0; i < 2048; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([2048,2048]);
let now = performance.now();
const result1 = multiplyMatrixGPU(matrix1,matrix2);
console.log('GPU:',performance.now() - now, 'ms');
// GPU: 6207.63 ms
复制代码
function multiplyMatrixCPU(a,b) {
const result = [];
for (let i = 0; i < 2048; i++) {
result[i] = [];
for (let j = 0; j < 2048; j++) {
let sum = 0;
for (let k = 0; k < 2048; k++) {
sum += a[i][k] * b[k][j];
}
result[i][j] = sum;
}
}
return result;
}
let now = performance.now();
const result2 = multiplyMatrixCPU(matrix1,matrix2);
console.log('CPU:', performance.now() - now, 'ms');
// CPU: 111287.36ms
复制代码
Web Assembly
WebAssembly 是一种可以使用非 JavaScript 编程语言编写代码并且能在浏览器上运行的技术方案。
它是一种新的编码方式,一种低级的类汇编语言,当然此语言和JavaScript可以一起工作。
Node.js C++ Addon
// index.js
var primes = require('./build/Release/threads.node').primes;
primes(4);
复制代码
线程数 | 加速 |
---|---|
1 | 1.75x |
2 | 3.13x |
3 | 2.84x |
4 | 3.86x |
8 | 2.43x |
16 | 2.94x |
32 | 2.07x |
50 | 2.91x |
100 | 1.85x |
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END