Js使用多线程Worker和单线程异步处理数据时间比较

Js使用多线程Worker和单线程异步处理数据比较

多线程worker入口文件main.js

模拟10w条数据查询或者计算时间

复制代码
const { Worker } = require('worker_threads');
const os = require('os');

// 模拟100000条数据
const totalData = 100000;
const data = new Array(totalData).fill(0).map((_, i) => i + 1);

// 获取CPU核心数,确定工作线程数量
const numWorkers = os.cpus().length;
console.log(`使用 ${numWorkers} 个线程处理 ${totalData} 条数据`);

// 计算每个线程处理的数据量
const chunkSize = Math.ceil(totalData / numWorkers);

// 创建Promise数组用于等待所有线程完成
const workerPromises = [];

console.time('多线程处理时间');

// 分发任务给工作线程
for (let i = 0; i < numWorkers; i++) {
  // 计算当前线程处理的数据范围
  const start = i * chunkSize;
  const end = Math.min(start + chunkSize, totalData);
  const chunk = data.slice(start, end);
  
  // 如果没有数据需要处理,则跳过
  if (chunk.length === 0) continue;
  
  // 创建工作线程
  const workerPromise = new Promise((resolve, reject) => {
    const worker = new Worker('./worker.js', {
      workerData: { 
        chunk,
        workerId: i + 1
      }
    });
    	
    	// 主线程监听接收子线程发回的数据
    worker.on('message', ({ workerId, result }) => {
      console.log(`线程 ${i + 1} 处理完成,结果: ${result}-${workerId}`);
      resolve(result);
    });
    
    worker.on('error', (err) => {
      console.error(`线程 ${i + 1} 发生错误:`, err);
      reject(err);
    });
    
    worker.on('exit', (code) => {
      if (code !== 0) {
        console.error(`线程 ${i + 1} 异常退出,退出码: ${code}`);
        reject(new Error(`Worker stopped with exit code ${code}`));
      }
    });
  });
  
  workerPromises.push(workerPromise);
}

// 等待所有线程完成并汇总结果
Promise.all(workerPromises)
  .then(results => {
    console.timeEnd('多线程处理时间');
    const totalResult = results.reduce((sum, result) => sum + result, 0);
    console.log(`所有线程处理完成,最终结果: ${totalResult}`);
  })
  .catch(err => {
    console.error('处理过程中发生错误:', err);
  });

多线程worker.js子线程处理逻辑

复制代码
const { parentPort, workerData } = require('worker_threads');

// 接收主线程传入的数据
const { chunk, workerId } = workerData;

// 模拟数据处理任务(计算平方和)
function processData(dataChunk) {
  let result = 0;
  for (let i = 0; i < dataChunk.length; i++) {
    // 模拟复杂计算
    result += dataChunk[i] * dataChunk[i];
  }
  return result;
}

// 执行数据处理
const result = processData(chunk);

// 将数据发送结果回主线程
parentPort.postMessage({ workerId, result });

多线程worker10w,100w, 500w,1000w,1亿条数据计算结果耗时间

复制代码
多线程:使用 12 个线程处理 100000 条数据
线程 4 处理完成,结果: 7139301874851-4
线程 1 处理完成,结果: 192982263735-1
线程 7 处理完成,结果: 24504788352639-7
线程 2 处理完成,结果: 1350736926699-2
线程 6 处理完成,结果: 17558607652635-6
线程 3 处理完成,结果: 3666176797071-3
线程 5 处理完成,结果: 11770112160039-5
线程 10 处理完成,结果: 52289441697099-10
线程 11 处理完成,结果: 63866363226735-11
线程 8 处理完成,结果: 32608654260051-8
线程 9 处理完成,结果: 41870205374871-9
线程 12 处理完成,结果: 76520962763575-12
多线程处理时间: 137.53ms
所有线程处理完成,最终结果: 333338333350000


多线程:使用 12 个线程处理 1000000 条数据
线程 1 处理完成,结果: 192909336526235-1
线程 2 处理完成,结果: 1350351466489199-2
线程 5 处理完成,结果: 11767288968814268-5
线程 6 处理完成,结果: 17554471840396720-6
线程 7 处理完成,结果: 24499089897390324-7
线程 10 处理完成,结果: 52277555180801690-10
线程 12 处理完成,结果: 76575707891456480-12
线程 3 处理完成,结果: 3665228781859571-3
线程 9 处理完成,结果: 41860631567595040-9
线程 8 处理完成,结果: 32601143139793560-8
线程 4 处理完成,结果: 7137541282637351-4
线程 11 处理完成,结果: 63851913979419570-11
多线程处理时间: 157.043ms
所有线程处理完成,最终结果: 333333833333180000

多线程:使用 12 个线程处理 5000000 条数据
线程 1 处理完成,结果: 24112798997109916-1
线程 2 处理完成,结果: 168789245756800420-2
线程 3 处理完成,结果: 458141965665288260-3
线程 4 处理完成,结果: 892170958722391000-4
线程 5 处理完成,结果: 1470876224928001000-5
线程 6 处理完成,结果: 2194257764282043100-6
线程 7 处理完成,结果: 3062315576783943700-7
线程 9 处理完成,结果: 5232460021233481000-9
线程 8 处理完成,结果: 4075049662434223600-8
线程 12 处理完成,结果: 9572648736422312000-12
线程 11 处理完成,结果: 7981309558277722000-11
线程 10 处理完成,结果: 6534546653181478000-10
多线程处理时间: 187.851ms
所有线程处理完成,最终结果: 41666679166684790000


多线程:使用 12 个线程处理 10000000 条数据
线程 1 处理完成,结果: 192902044753839580-1
线程 3 处理完成,结果: 3665133989210254000-3
线程 2 处理完成,结果: 1350312924388518400-2
线程 4 处理完成,结果: 7137365239220742000-4
线程 5 处理完成,结果: 11767006674418960000-5
线程 6 处理完成,结果: 17554058294803753000-6
线程 8 处理完成,结果: 32600392091137303000-8
线程 10 处理完成,结果: 52276366628218470000-10
线程 7 处理完成,结果: 24498520100377230000-7
线程 11 处理完成,结果: 63850469174539485000-11
线程 9 处理完成,结果: 41859674267084380000-9
线程 12 处理完成,结果: 76581181905328590000-12
多线程处理时间: 282.691ms
所有线程处理完成,最终结果: 333333383333481550000

多线程:使用 12 个线程处理 100000000 条数据
线程 1 处理完成,结果: 192901315586678420000-1
线程 2 处理完成,结果: 1.3503090702170194e+21-2
线程 3 处理完成,结果: 3.6651245100325656e+21-3
线程 4 处理完成,结果: 7.137347635033739e+21-4
线程 5 处理完成,结果: 1.1766978445219803e+22-5
线程 6 处理完成,结果: 1.7554016940590916e+22-6
线程 7 处理完成,结果: 2.449846312114824e+22-7
线程 8 处理完成,结果: 3.2600316986890297e+22-8
线程 9 处理完成,结果: 4.185957853781544e+22-9
线程 10 处理完成,结果: 5.22762477739318e+22-10
线程 11 处理完成,结果: 6.385032469522634e+22-11
线程 12 处理完成,结果: 7.658172930169968e+22-12
多线程处理时间: 2.026s
所有线程处理完成,最终结果: 3.333333383333925e+23

单线程异步处理数据逻辑

main.js

复制代码
// 模拟100000条数据
const totalData = 100000;
const data = new Array(totalData).fill(0).map((_, i) => i + 1);

// 异步模拟处理函数
async function processDataAsync(dataChunk, taskId) {
  console.log(`任务 ${taskId} 开始处理 ${dataChunk.length} 条数据`);
  
  let result = 0;
  for (const item of dataChunk) {
    // 模拟计算操作
    result += item;
    // 添加微小延迟模拟异步处理
    if (item % 10000 === 0) {
      await new Promise(resolve => setImmediate(resolve));
    }
  }
  
  console.log(`任务 ${taskId} 处理完成,结果: ${result}`);
  return result;
}

// 异步处理主函数
async function runAsyncProcessing() {
  console.log(`使用异步方式处理 ${totalData} 条数据`);
  
  // 获取CPU核心数,确定任务数量
  const numTasks = require('os').cpus().length;
  const chunkSize = Math.ceil(totalData / numTasks);
  
  console.time('异步处理时间');
  
  // 分割数据
  const tasks = [];
  for (let i = 0; i < numTasks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, totalData);
    const chunk = data.slice(start, end);
    
    if (chunk.length > 0) {
      tasks.push(processDataAsync(chunk, i + 1));
    }
  }
  
  // 并行执行所有任务
  try {
    const results = await Promise.all(tasks);
    console.timeEnd('异步处理时间');
    
    const totalResult = results.reduce((sum, result) => sum + result, 0);
    console.log(`所有异步任务处理完成,最终结果: ${totalResult}`);
  } catch (error) {
    console.error('异步处理过程中发生错误:', error);
  }
}

// 运行异步处理
runAsyncProcessing();

单线程10w,100w,1000w,1亿条数据计算结果耗时间

复制代码
使用异步方式处理 100000 条数据
任务 1 开始处理 8334 条数据
任务 1 处理完成,结果: 34731945
任务 2 开始处理 8334 条数据
任务 3 开始处理 8334 条数据
任务 4 开始处理 8334 条数据
任务 5 开始处理 8334 条数据
任务 6 开始处理 8334 条数据
任务 7 开始处理 8334 条数据
任务 7 处理完成,结果: 451465281
任务 8 开始处理 8334 条数据
任务 9 开始处理 8334 条数据
任务 10 开始处理 8334 条数据
任务 11 开始处理 8334 条数据
任务 12 开始处理 8326 条数据
任务 2 处理完成,结果: 104187501
任务 3 处理完成,结果: 173643057
任务 4 处理完成,结果: 243098613
任务 5 处理完成,结果: 312554169
任务 6 处理完成,结果: 382009725
任务 8 处理完成,结果: 520920837
任务 9 处理完成,结果: 590376393
任务 10 处理完成,结果: 659831949
任务 11 处理完成,结果: 729287505
任务 12 处理完成,结果: 797943025
异步处理时间: 17.806ms
所有异步任务处理完成,最终结果: 5000050000

使用异步方式处理 1000000条数据
任务 2 开始处理 83334 条数据
任务 3 开始处理 83334 条数据
任务 4 开始处理 83334 条数据
任务 5 开始处理 83334 条数据
任务 6 开始处理 83334 条数据
任务 7 开始处理 83334 条数据
任务 8 开始处理 83334 条数据
任务 9 开始处理 83334 条数据
任务 10 开始处理 83334 条数据
任务 11 开始处理 83334 条数据
任务 12 开始处理 83326 条数据
任务 1 处理完成,结果: 3472319445
任务 2 处理完成,结果: 10416875001
任务 4 处理完成,结果: 24305986113
任务 5 处理完成,结果: 31250541669
任务 7 处理完成,结果: 45139652781
任务 8 处理完成,结果: 52084208337
任务 10 处理完成,结果: 65973319449
任务 11 处理完成,结果: 72917875005
任务 3 处理完成,结果: 17361430557
任务 6 处理完成,结果: 38195097225
任务 9 处理完成,结果: 59028763893
任务 12 处理完成,结果: 79854430525
异步处理时间: 60.151ms
所有异步任务处理完成,最终结果: 500000500000

使用异步方式处理 5000000 条数据
任务 1 开始处理 416667 条数据
任务 2 开始处理 416667 条数据
任务 3 开始处理 416667 条数据
任务 4 开始处理 416667 条数据
任务 5 开始处理 416667 条数据
任务 6 开始处理 416667 条数据
任务 7 开始处理 416667 条数据
任务 8 开始处理 416667 条数据
任务 9 开始处理 416667 条数据
任务 10 开始处理 416667 条数据
任务 11 开始处理 416667 条数据
任务 12 开始处理 416663 条数据
任务 1 处理完成,结果: 86805902778
任务 4 处理完成,结果: 607640069445
任务 7 处理完成,结果: 1128474236112
任务 10 处理完成,结果: 1649308402779
任务 2 处理完成,结果: 260417291667
任务 3 处理完成,结果: 434028680556
任务 5 处理完成,结果: 781251458334
任务 6 处理完成,结果: 954862847223
任务 8 处理完成,结果: 1302085625001
任务 9 处理完成,结果: 1475697013890
任务 11 处理完成,结果: 1822919791668
任务 12 处理完成,结果: 1996511180547
异步处理时间: 161.471ms
所有异步任务处理完成,最终结果: 12500002500000


使用异步方式处理 10000000 条数据
任务 1 开始处理 833334 条数据
任务 2 开始处理 833334 条数据
任务 3 开始处理 833334 条数据
任务 4 开始处理 833334 条数据
任务 5 开始处理 833334 条数据
任务 6 开始处理 833334 条数据
任务 7 开始处理 833334 条数据
任务 8 开始处理 833334 条数据
任务 9 开始处理 833334 条数据
任务 10 开始处理 833334 条数据
任务 11 开始处理 833334 条数据
任务 12 开始处理 833326 条数据
任务 1 处理完成,结果: 347223194445
任务 2 处理完成,结果: 1041668750001
任务 4 处理完成,结果: 2430559861113
任务 5 处理完成,结果: 3125005416669
任务 7 处理完成,结果: 4513896527781
任务 8 处理完成,结果: 5208342083337
任务 10 处理完成,结果: 6597233194449
任务 11 处理完成,结果: 7291678750005
任务 3 处理完成,结果: 1736114305557
任务 6 处理完成,结果: 3819450972225
任务 9 处理完成,结果: 5902787638893
任务 12 处理完成,结果: 7986044305525
异步处理时间: 319.762ms
所有异步任务处理完成,最终结果: 50000005000000

使用异步方式处理 100000000 条数据
任务 1 开始处理 8333334 条数据
任务 2 开始处理 8333334 条数据
任务 3 开始处理 8333334 条数据
任务 4 开始处理 8333334 条数据
任务 5 开始处理 8333334 条数据
任务 6 开始处理 8333334 条数据
任务 7 开始处理 8333334 条数据
任务 8 开始处理 8333334 条数据
任务 9 开始处理 8333334 条数据
任务 10 开始处理 8333334 条数据
任务 11 开始处理 8333334 条数据
任务 12 开始处理 8333326 条数据
任务 1 处理完成,结果: 34722231944445
任务 2 处理完成,结果: 104166687500001
任务 4 处理完成,结果: 243055598611113
任务 5 处理完成,结果: 312500054166669
任务 7 处理完成,结果: 451388965277781
任务 8 处理完成,结果: 520833420833337
任务 10 处理完成,结果: 659722331944449
任务 11 处理完成,结果: 729166787500005
任务 3 处理完成,结果: 173611143055557
任务 6 处理完成,结果: 381944509722225
任务 9 处理完成,结果: 590277876388893
任务 12 处理完成,结果: 798610443055525
异步处理时间: 2.523s
所有异步任务处理完成,最终结果: 5000000050000000

在相同计算机或者服务器下,从以上大量数据计算分析可以看出,Js多线程一般在数据量级达到千万级别处理速度优势才最明显,500w级别以下计算处理单线程速度效率优势更明显。

相关推荐
史上最菜开发5 小时前
Ant Design Vue V1.7.8版本,a-input 去空格
javascript·vue.js·anti-design-vue
光算科技5 小时前
商品颜色/尺码选项太多|谷歌爬虫不收录怎么办
java·javascript·爬虫
前端不太难5 小时前
Vue Router 权限系统设计实战
前端·javascript·vue.js
Aevget5 小时前
可视化工具LightningChart JS v8.1 重磅更新:热力图与 3D 可视化能力双提升!
javascript·3d·信息可视化·数据可视化·lightningchart
Zhi.C.Yue5 小时前
React 的位掩码标记系统
javascript·react.js·ecmascript
小明记账簿5 小时前
An unexpected error occurred: “https://registry.npm.taobao.org/
前端·前端框架
醉挽清风7835 小时前
Vue+Djiango基础用法
前端·javascript·vue.js
dreams_dream5 小时前
vue2动态更改css属性方法大全
前端·css