javascript - cpu能比:phantom:page be more than 1:1:1

标签 javascript performance concurrency phantomjs

我可以为每个 CPU 创建更多 PhantomJS 进程 或同时为每个 phantom 进程创建 1 个以上 网页 实例吗?

例如,1:1:1 表示:1 台电脑有 4 个 CPU,我生成 4 个 PhantomJS 进程,并创建 1 个网页同时在每个进程中。

这是并发的限制。

有没有好的方法证明可以改变1:1:1的比例以及哪个比例好?

如果 phantom:page 的比例为 1:n,是否会发生上下文切换竞争条件,这会导致 PhantomJS 错误吗?

最佳答案

不存在三向比率这样的东西。比率恰好有两个方。现在我们已经解决了这个问题,让我们分割比例。

我们可以用 x 个可用线程(CPU/核心)和 y 个 PhantomJS 进程来定义 x:y。然后我们可以用 z 个 page 实例定义 y:z。

核心与进程

只要硬件支持(主要是RAM),您可以运行任意数量的PhantomJS进程。但对于大多数架构(全部?),当 y > x 时,相对性能 (y/x) 会下降。当您有许多进程但核心数量较少时,则至少两个进程必须共享一个核心(如果有多线程,则必须共享一个线程)。因此,这两个过程的完成速度不会像其他过程那么快。这与 PhantomJS 无关,而是正常的多进程行为。

如果你有y >> x,那么即使进程的上下文切换也可能成为瓶颈,一切都会变得非常慢。

始终希望只生成与您拥有的核心/线程一样多的进程(甚至可能更少)。

对于几乎所有情况,PhantomJS 进程默认独立运行。仅当它们运行的​​页面使用 localStorage 时,您才可能遇到问题。 localStorage 始终保留在磁盘上,并且无法更改。

PhantomJS 进程与 page 实例

PhantomJS 运行 JavaScript 脚本。由于 JavaScript 整体上是单线程的,因此无法获得任何并行处理,但可以通过正常的 JavaScript 事件循环获得并发性。

PhantomJS 支持每个进程多个 page 实例,并且效果相当好,但当然,由于 JavaScript 是单线程的,多个页面的执行是交错的。这意味着“同时”打开两个页面应该会导致逐个打开它们所需的时间大致相同。

严格来说并非如此,因为等待一个页面的资源可以让其他页面进行进一步的处理。当页面顺序打开时,某个页面等待资源加载的时间无法被其他页面使用。

另一方面,不能在一个进程中使用大量page实例,因为不同页面的请求会互相阻碍。 HTTP 请求在 TCP 上运行。如果有多个 TCP 争夺带宽,则连接的整体效率会降低。但这应该仍然比顺序情况更快。这就是为什么 HTTP/2 (SPDY) 是个好主意。

并发处理比顺序方式更快,但是对每个 PhantomJS 进程(甚至可能是多个进程)管理多个 page 实例进行编程会更困难。

基准:多个页面实例

此脚本显示请求站点的两个版本。第一次迭代的结果有很大不同,因为缓存尚未填充。缓存以后无法清除,因此每次迭代都会在第一次迭代之后使用缓存的资源。

var urls = [
    'https://google.com', 
    'http://stackoverflow.com/contact', 
    'http://stackoverflow.com/questions?pagesize=15&sort=newest', 
    'http://www.spiegel.de/'
];

function sequential(callback) {
    var copiedUrls = JSON.parse(JSON.stringify(urls)),
        page = require('webpage').create(),
        start = (new Date()).getTime();
    function sequentialHelper(){
        //console.log("seqHelp " + copiedUrls.length);
        if (copiedUrls.length == 0) {
            start = (new Date()).getTime() - start;
            page.close();
            callback(start);
            return;
        }
        page.open(copiedUrls.shift(), function(s){
            sequentialHelper();
        });
    }
    sequentialHelper();
}

function parallel(callback) {
    var copiedUrls = JSON.parse(JSON.stringify(urls)),
        max = copiedUrls.length,
        pages = [], 
        start;
    function checkFin(){
        max--;
        //console.log("parCheck " + max);
        if (0 === max) {
            start = (new Date()).getTime() - start;
            pages.forEach(function(page){
                page.close();
            });
            callback(start);
        }
    }
    start = (new Date()).getTime();
    copiedUrls.forEach(function(url){
        var page = require('webpage').create();
        pages.push(page);
        page.open(url, function(s){
            checkFin();
        });
    });
}

var repeat = 5,
    current = 0,
    times = [];

function repeater(){
    if (current === repeat) {
        console.log(JSON.stringify(times, undefined, 4));
        phantom.exit();
    }
    console.log("repeated: " + (current+1));

    var t = {
        par: (new Date()).getTime()
    };
    parallel(function(innerTime){
        t.par = (new Date()).getTime() - t.par;
        t.pari = innerTime;
        t.seq = (new Date()).getTime();
        sequential(function(innerTime){
            t.seq = (new Date()).getTime() - t.seq;
            t.seqi = innerTime;
            times.push(t);
            repeater();
        });
    });
    current++;
}

repeater();

输出:

[
    {
        "par": 10653,
        "pari": 10652,
        "seq": 5304,
        "seqi": 5301
    },
    {
        "par": 2936,
        "pari": 2936,
        "seq": 5224,
        "seqi": 5219
    },
    {
        "par": 3167,
        "pari": 3167,
        "seq": 4478,
        "seqi": 4474
    },
    {
        "par": 2506,
        "pari": 2506,
        "seq": 6868,
        "seqi": 6862
    },
    {
        "par": 2479,
        "pari": 2479,
        "seq": 3753,
        "seqi": 3749
    }
]

关于javascript - cpu能比:phantom:page be more than 1:1:1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29488620/

相关文章:

performance - RabbitMQ 与 MSMQ 的比较

java - 同步和合并消息/数据流

java - 在 Java 6 中实现多生产者/消费者模式的最佳方式

javascript - 如何允许下载以二进制数据形式从 AJAX 返回的文件

javascript - iOS UIWebView 应用程序在 Safari 中打开链接

PHP:查询超过最大时间(如何处理)

c# - 这个流行的 StackOverflow 答案不正确吗?

multithreading - 生成比线程更多的任务

javascript - 客户支持字幕滚动

javascript - 单击操作不适用于 Chrome 上的输入文件元素