国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Puppeteer性能優(yōu)化與執(zhí)行速度提升

KnewOne / 2990人閱讀

摘要:所以需要理解運(yùn)行的原理,才能方便優(yōu)化。如果啟動(dòng)時(shí)能綁定到某個(gè)核上也能提升速度單核上進(jìn)行進(jìn)程切換耗費(fèi)的時(shí)間更少。優(yōu)化執(zhí)行流程接下來(lái)我們?cè)俣鄮?yōu)化對(duì)應(yīng)的頁(yè)面。參考文章性能優(yōu)化與執(zhí)行速度提升利用優(yōu)化

Puppeteer自身不會(huì)消耗太多資源,耗費(fèi)資源的大戶是Chromium Headless。所以需要理解Chromium運(yùn)行的原理,才能方便優(yōu)化。

Chromium消耗最多的資源是CPU,一是渲染需要大量計(jì)算,二是Dom的解析與渲染在不同的進(jìn)程,進(jìn)程間切換會(huì)給CPU造成壓力(進(jìn)程多了之后特別明顯)。其次消耗最多的是內(nèi)存,Chromium是以多進(jìn)程的方式運(yùn)行,一個(gè)頁(yè)面會(huì)生成一個(gè)進(jìn)程,一個(gè)進(jìn)程占用30M左右的內(nèi)存,大致估算1000個(gè)請(qǐng)求占用30G內(nèi)存,在并發(fā)高的時(shí)候內(nèi)存瓶頸最先顯現(xiàn)。

優(yōu)化最終會(huì)落在內(nèi)存和CPU上(所有軟件的優(yōu)化最終都要落到這里),通常來(lái)說(shuō)因?yàn)椴l(fā)造成的瓶頸需要優(yōu)化內(nèi)存,計(jì)算速度慢的問(wèn)題要優(yōu)化CPU。使用Puppeteer的用戶多半會(huì)更關(guān)心計(jì)算速度,所以下面我們談?wù)勅绾蝺?yōu)化Puppeteer的計(jì)算速度。

優(yōu)化Chromium啟動(dòng)項(xiàng)

通過(guò)查看Chromium啟動(dòng)時(shí)都有哪些參數(shù)可以配置,能找到大部分線索,因?yàn)镃hromium這種頂級(jí)的開(kāi)源產(chǎn)品,文檔與接口都是非常清晰的,肯定可以找到相關(guān)配置項(xiàng)來(lái)定制啟動(dòng)方式。Chromium 啟動(dòng)參數(shù)列表

我們需要找到下面幾種配置來(lái)提升速度:

    如果將Dom解析和渲染放到同一進(jìn)程,肯定能提升時(shí)間(進(jìn)程上下文切換的時(shí)間)。對(duì)應(yīng)的配置是??single-process?

    部分功能disable掉,比如GPU、Sandbox、插件等,減少內(nèi)存的使用和相關(guān)計(jì)算。

    如果啟動(dòng)Chromium時(shí)能綁定到某個(gè)CPU核上也能提升速度(單核上進(jìn)行進(jìn)程切換耗費(fèi)的時(shí)間更少)。可惜沒(méi)有找到對(duì)應(yīng)的配置,官方文檔寫(xiě)的是Chromium啟動(dòng)時(shí)會(huì)自動(dòng)綁定CPU大核(ARM架構(gòu)的CPU通常有大小核之分),依此推測(cè)Chromium啟動(dòng)時(shí)是會(huì)綁核的。(此處我并未驗(yàn)證)

最后配置如下:

const browser = await puppeteer.launch(
{
    headless:true,
    args: [
        ‘–disable-gpu’,
        ‘–disable-dev-shm-usage’,
        ‘–disable-setuid-sandbox’,
        ‘–no-first-run’,
        ‘–no-sandbox’,
        ‘–no-zygote’,
        ‘–single-process’
    ]
});

Chromium 啟動(dòng)參數(shù)列表?文檔中的配置項(xiàng)都可以嘗試看看,我沒(méi)有對(duì)所有選項(xiàng)做測(cè)試,但可以肯定存在某些選項(xiàng)能提升Chromium速度。

優(yōu)化Chromium執(zhí)行流程

接下來(lái)我們?cè)俣鄮?yōu)化Chromium對(duì)應(yīng)的頁(yè)面。我之前的文章中提過(guò),如果每次請(qǐng)求都啟動(dòng)Chromium,再打開(kāi)tab頁(yè),請(qǐng)求結(jié)束后再關(guān)閉tab頁(yè)與瀏覽器。流程大致如下:

請(qǐng)求到達(dá)->啟動(dòng)Chromium->打開(kāi)tab頁(yè)->運(yùn)行代碼->關(guān)閉tab頁(yè)->關(guān)閉Chromium->返回?cái)?shù)據(jù)

真正運(yùn)行代碼的只是tab頁(yè)面,理論上啟動(dòng)一個(gè)Chromium程序能運(yùn)行成千上萬(wàn)的tab頁(yè),可不可以復(fù)用Chromium每次只打開(kāi)一個(gè)tab頁(yè)然后關(guān)閉呢?當(dāng)然是可以的,Puppeteer提供了?puppeteer.connect()??方法,可以連接到當(dāng)前打開(kāi)的瀏覽器。流程如下:

請(qǐng)求到達(dá)->連接Chromium->打開(kāi)tab頁(yè)->運(yùn)行代碼->關(guān)閉tab頁(yè)->返回?cái)?shù)據(jù)

代碼如下:

const MAX_WSE = 4;  //啟動(dòng)幾個(gè)瀏覽器 
let WSE_LIST = []; //存儲(chǔ)browserWSEndpoint列表
init();
app.get("/", function (req, res) {
    let tmp = Math.floor(Math.random()* MAX_WSE);
    (async () => {
        let browserWSEndpoint = WSE_LIST[tmp];
        const browser = await puppeteer.connect({browserWSEndpoint});
        const page = await browser.newPage();
        await page.goto("file://code/screen/index.html");
        await page.setViewport({
            width: 600,
            height: 400
        });                
        await page.screenshot({path: "example.png"});
        await page.close();
        res.send("Hello World!");
    })();
});

function init(){
    (async () => {
        for(var i=0;itrue,
                args: [
                "--disable-gpu",
                "--disable-dev-shm-usage",
                "--disable-setuid-sandbox",
                "--no-first-run",
                "--no-sandbox",
                "--no-zygote",
                "--single-process"
            ]});
            browserWSEndpoint = await browser.wsEndpoint();
            WSE_LIST[i] = browserWSEndpoint;
        }
        console.log(WSE_LIST);
    })();        
}
利用cluster優(yōu)化Puppeteer

通常情況下我們會(huì)使用??.map()??搭配??Promise.all()??的方式并行處理異步,但是在使用?Puppeteer?批量截圖時(shí)發(fā)現(xiàn)?Promise.all?會(huì)打開(kāi)多個(gè)瀏覽器,導(dǎo)致機(jī)器性能急劇下降。

?Promise.all()??并行處理

利用??Reduce??是多個(gè)?Promise?順序執(zhí)行

await tasks.reduce((sequence, url, idx) => {
  return sequence.then(() => {
    // doAnalyze 是個(gè)異步函數(shù)
    return doAnalyze(url, idx);
  });
}, Promise.resolve())

場(chǎng)景:有40個(gè)URL,需要獲取每個(gè)博客的首頁(yè)截圖

如果是?Promise.all()?,程序啟動(dòng)會(huì)同時(shí)打開(kāi)20+的chromium瀏覽器,導(dǎo)致機(jī)器卡死。

使用?reduce?緩解了壓力,但沒(méi)充分利用多核性能

參入?Cluster?

// cluster_index.js 入口文件
const cluster = require("cluster");

(async () => {
  let run;
  if (cluster.isMaster) {
    run = require("./cluster_master");
  } else {
    run = require("./cluster_worker");
  }
  try {
    await run();
  } catch (e) {
    // 追蹤函數(shù)的調(diào)用軌跡
    console.trace(e);
  }
})();
// cluster_master.js master進(jìn)程分配任務(wù)

const cluster = require("cluster");
const numCPUs = require("os").cpus().length;

// 處理的任務(wù)列表
let arr = [
  "https://github.com/guoguoya",
  "http://www.52cik.com",
  "http://zhalice.com",
  "https://www.yzqroom.cn",
  "http://zxh.name",
  "https://fogdong.github.io/",
  "http://github.com/elsieyin",
  "https://summer.tlb058.com",
  "https://skymon4.cn",
  "http://www.jiweiqing.cn",
  "http://effect.im",
  "http://dingkewz.com",
  "http://xcdh.me",
  "http://d2g.io",
  "http://codingdemon.com",
  "http://blog.leanote.com/dujuncheng",
  "http://niexiaotao.com",
  "http://zhengchengwen.com",
  "http://blog.tophefei.com",
  "https://zh-rocco.github.io",
  "http://wangyn.net",
  "http://dscdtc.ml",
  "http://jweboy.github.io",
  "http://www.wenghaoping.com",
  "http://zhoujingchao.github.io",
  "http://kyriejoshua.github.io/jo.github.io/",
  "http://www.withyoufriends.com",
  "http://if2er.com",
  "https://github.com/zhou-yg",
  "http://github/suoutsky",
  "http://richardsleet.github.io",
  "http://www.89io.com",
  "https://guoshencheng.com",
  "http://www.landluck.com.cn",
  "http://www.89io.com",
  "http://myoungxue.top",
  "https://github.com/Wangszzju",
  "http://www.hacke2.cn",
  "https://github.com/enochjs",
  "https://i.jakeyu.top",
  "http://muyunyun.cn",
];

module.exports = async () => {
  // 每個(gè) CPU 分配 N 個(gè)任務(wù)
  const n = Math.floor(arr.length / numCPUs);
  // 未分配的余數(shù)
  const remainder = arr.length % numCPUs;

  for (let i = 1; i <= numCPUs; i += 1) {
    const tasks = arr.splice(0, n + (i > remainder ");"exit", (worker) => {
    console.log(`worker #${worker.id} PID:${worker.process.pid} died`);
  });
  cluster.on("error", (err) => {
    console.log(`worker #${worker.id} PID ERROR: `, err);
  });
};
// cluster_worker.js worker進(jìn)程 完成任務(wù)

const cluster = require("cluster");
const puppeteer = require("puppeteer");

// 禁止直接啟動(dòng)
if (cluster.isMaster) {
  console.log("----", cluster.worker.id)
  process.exit(0);
}

module.exports = async () => {
  const env = process.env.tasks;
  let tasks = [];
  if (/^[.*]$/.test(env)) {
    tasks = JSON.parse(env);
  }
  if (tasks.length === 0) {
    console.log("");, tasks)
    // 非法啟動(dòng), 釋放進(jìn)程資源
    process.exit(0);
  }
  console.log(`worker #${cluster.worker.id} PID:${process.pid} Start`);
  await tasks.reduce((sequence, url, idx) => {
    return sequence.then(() => {
      return doAnalyze(url, idx);
    });
  }, Promise.resolve())

  console.log(cluster.worker.id + " 順利完成");
  process.exit(0);
};

async function doAnalyze(url, i) {
  try {
    const browser = await (puppeteer.launch({
      // 若是手動(dòng)下載的chromium需要指定chromium地址, 默認(rèn)引用地址為 /項(xiàng)目目錄/node_modules/puppeteer/.local-chromium/
      // executablePath: "/Users/huqiyang/Documents/project/z/chromium/Chromium.app/Contents/MacOS/Chromium",
      //設(shè)置超時(shí)時(shí)間
      timeout: 30000,
      //如果是訪問(wèn)https頁(yè)面 此屬性會(huì)忽略https錯(cuò)誤
      ignoreHTTPSErrors: true,
      // 打開(kāi)開(kāi)發(fā)者工具, 當(dāng)此值為true時(shí), headless總為false
      devtools: false,
      // 關(guān)閉headless模式, 會(huì)打開(kāi)瀏覽器
      headless: false
    }));
    const page = await browser.newPage();
    await page.setViewport({width: 1920, height: 1080});
    await page.goto(url);
    await page.waitFor(4000);
    console.log(cluster.worker.id, url, i, "截圖中...");
    await page.screenshot({
      path: `./img_cluster/${cluster.worker.id}-${i}.png`,
      // path: "3.png",
      type: "png",
      // quality: 100, 只對(duì)jpg有效
      // fullPage: true,
      // 指定區(qū)域截圖,clip和fullPage兩者只能設(shè)置一個(gè)
      // clip: {
      //   x: 0,
      //   y: 0,
      //   width: 1920,
      //   height: 600
      // }
    });
    browser.close();
  } catch (error) {
    console.log(cluster.worker.id, url, i)
    console.log(error)
  }
};
多個(gè)page輪詢與多個(gè)browser輪詢

為了性能,現(xiàn)有解決方案是初始化若干個(gè)browser,請(qǐng)求打過(guò)來(lái)時(shí),直接在browserList中取一個(gè)browser實(shí)例使用。 作為對(duì)比,可以參考初始化一個(gè)browser,預(yù)先打開(kāi)若干個(gè)page,請(qǐng)求打過(guò)來(lái)時(shí),直接在pageList中取一個(gè)page實(shí)例使用。

參考文章:

Puppeteer性能優(yōu)化與執(zhí)行速度提升 利用cluster優(yōu)化Puppeteer

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/7302.html

相關(guān)文章

  • 前端每周清單第 29 期:Web 現(xiàn)狀分析優(yōu)化策略、Vue 單元測(cè)試、Headless Chrom

    摘要:前端每周清單第期現(xiàn)狀分析與優(yōu)化策略單元測(cè)試爬蟲(chóng)作者王下邀月熊編輯徐川前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開(kāi)發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開(kāi)發(fā)教程工程實(shí)踐深度閱讀開(kāi)源項(xiàng)目巔峰人生等欄目。 showImg(https://segmentfault.com/img/remote/1460000011008022); 前端每周清單第 29 期:Web 現(xiàn)狀分析與優(yōu)化策略...

    HackerShell 評(píng)論0 收藏0
  • 從零開(kāi)始開(kāi)發(fā)一個(gè)Node交互式命令行應(yīng)用

    摘要:導(dǎo)言對(duì)于大多數(shù)前端開(kāi)發(fā)者而言,談到命令行工具,大家肯定都用過(guò)。但是談到開(kāi)發(fā)命令行工具,估計(jì)就沒(méi)幾人有了解了。如何優(yōu)化這個(gè)圖片爬蟲(chóng)工具目前還有點(diǎn)啊,我們的目標(biāo)是要開(kāi)發(fā)一個(gè)交互式的命令行應(yīng)用,肯定不能止于此。 導(dǎo)言:對(duì)于大多數(shù)前端開(kāi)發(fā)者而言,談到命令行工具,大家肯定都用過(guò)。但是談到開(kāi)發(fā)命令行工具,估計(jì)就沒(méi)幾人有了解了。本文旨在用最短的時(shí)間內(nèi),幫您開(kāi)發(fā)一個(gè)實(shí)用(斜眼笑)的圖片爬蟲(chóng)命令行應(yīng)用。...

    Harriet666 評(píng)論0 收藏0
  • 前端每周清單第 48 期:Slack Webpack 構(gòu)建優(yōu)化,CSS 命名規(guī)范用戶追蹤,Vue.

    摘要:發(fā)布是由團(tuán)隊(duì)開(kāi)源的,操作接口庫(kù),已成為事實(shí)上的瀏覽器操作標(biāo)準(zhǔn)。本周正式發(fā)布,為我們帶來(lái)了,,支持自定義頭部與腳部,支持增強(qiáng),兼容原生協(xié)議等特性變化。新特性介紹日前發(fā)布了大版本更新,引入了一系列的新特性與提升,本文即是對(duì)這些變化進(jìn)行深入解讀。 showImg(https://segmentfault.com/img/remote/1460000012940044); 前端每周清單專注前端...

    sean 評(píng)論0 收藏0
  • 前端每周清單年度總結(jié)盤(pán)點(diǎn)

    摘要:前端每周清單年度總結(jié)與盤(pán)點(diǎn)在過(guò)去的八個(gè)月中,我?guī)缀踔蛔隽藘杉拢ぷ髋c整理前端每周清單。本文末尾我會(huì)附上清單線索來(lái)源與目前共期清單的地址,感謝每一位閱讀鼓勵(lì)過(guò)的朋友,希望你們能夠繼續(xù)支持未來(lái)的每周清單。 showImg(https://segmentfault.com/img/remote/1460000010890043); 前端每周清單年度總結(jié)與盤(pán)點(diǎn) 在過(guò)去的八個(gè)月中,我?guī)缀踔蛔隽?..

    jackwang 評(píng)論0 收藏0
  • 前端核心工具:yarn、npm、cnpm三者如何優(yōu)雅的在一起使用 ?

    摘要:由于文件中版本號(hào)的特點(diǎn),下面三個(gè)版本號(hào)在安裝的時(shí)候代表不同的含義。安裝版本統(tǒng)一為了防止拉取到不同的版本,有一個(gè)鎖定文件記錄了被確切安裝上的模塊的版本號(hào)。 showImg(https://segmentfault.com/img/bVbs8Rg?w=1920&h=1080); 一位用不好包管理器的前端,是一個(gè)入門(mén)級(jí)前端,一個(gè)用不好webpack的前端,是一個(gè)初級(jí)前端 三個(gè)包管理器是可以一...

    sihai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<