Javascript cpu:phantom:page的比率是否可以超过1:1:1
我是否可以为每个CPU创建更多的PhantomJS进程,或者同时为每个PhantomJS进程创建多个网页实例 例如,1:1:1意味着:1台带有4个CPU的pc,我生成4个PhantomJS进程,并同时在每个进程中创建1个网页 这是对并发性的限制 有没有好办法证明我可以改变1:1:1的比例,哪一个比例是好的Javascript cpu:phantom:page的比率是否可以超过1:1:1,javascript,performance,concurrency,phantomjs,Javascript,Performance,Concurrency,Phantomjs,我是否可以为每个CPU创建更多的PhantomJS进程,或者同时为每个PhantomJS进程创建多个网页实例 例如,1:1:1意味着:1台带有4个CPU的pc,我生成4个PhantomJS进程,并同时在每个进程中创建1个网页 这是对并发性的限制 有没有好办法证明我可以改变1:1:1的比例,哪一个比例是好的 如果phantom:page的比率为1:n,是否会发生上下文切换争用情况,这会导致PhantomJS错误?没有三向比率。一个比率正好有两个方面。现在我们已经解决了这个问题,让我们把比率分成两半
如果phantom:page的比率为1:n,是否会发生上下文切换争用情况,这会导致PhantomJS错误?没有三向比率。一个比率正好有两个方面。现在我们已经解决了这个问题,让我们把比率分成两半 我们可以用x个可用线程(CPU/内核)和y个PhantomJS进程来定义x:y。然后我们可以用
页面
实例的z个数定义y:z
核心与过程
只要硬件支持(主要是RAM),就可以运行任意多个PhantomJS进程。但是对于大多数架构(全部?),当y>x
时,相对性能(y/x
)会下降。如果有多个进程而没有那么多的内核,那么至少两个进程必须共享一个内核(如果有多线程,则为线程)。所以这两个过程不会像其他过程那样快。这与PhantomJS无关,而是正常的多进程行为
如果您有y>>x
,那么即使是进程的上下文切换也可能成为瓶颈,一切都会非常缓慢
始终只希望生成与核心/线程数量相同的进程(可能更少)
对于几乎所有情况,默认情况下,PhantomJS进程都独立运行。只有当它们运行的页面使用本地存储时,您可能会遇到问题。localStorage始终保留在磁盘上,无法更改
PhantomJS流程与页面
实例
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
}
]
很高兴再次见到你,@Artjom B。但是你的答案仍然是
x=y,y=z
。我希望y>z
来自您,因为javascript的事件驱动可能是指z>y
。我的理由是,因为JavaScript是单线程的,所以不会有任何并行性(只有并发性)来提高性能。除了管理多个进程外,还需要以编程方式管理这些page
实例为代价。我没有做任何基准测试,因为正如我所说,这在很大程度上取决于您请求的页面以及您实际如何管理多个page
实例。是的,我的意思是z>y
。程序管理页面实例是另一个问题。在我看来:事件驱动
意味着当一个事件等待回调时,cpu可以在下一个事件循环之前做其他事情,有cpu间隔。我也没有做过任何基准测试。你对基准有什么建议吗?谢谢~是的,使用y>z
进行并发处理比顺序y=z
更快。我添加了一个基准。再次感谢您,抱歉回复太晚。最后,我发现了问题所在。让我慢下来的关键是幻影发出的缓慢的回应。我的测试运行在4cpu 8G内存上,同时运行260个幻影进程是最快的。当进程计数小于260时,系统资源有空闲,大于260时,总时间成本时间激增。**因此我的结论是,当phantom等待响应时,进程可以放弃系统资源控制,phantom可以根据一般经验打破与cpu的比率**