在运行时确定哪个核心正在运行Node.js进程

8
我正在查看'os'和'process'模块源代码,似乎没有办法在运行时之前/期间/之后确定node.js进程在哪个核心上运行。
我需要像这样的东西:
process.env.CORE_ID   //not real

我想确认不同的node.js进程正在不同的核心上运行。虽然操作系统最终选择哪个核心来执行node.js进程,但我们应该能够在操作系统启动进程后读取这些数据,这似乎是合理的。

4个回答

12

在任何操作系统中,进程都不会与特定的核心相关联(除了一些面向实时应用场景的操作系统可能会有这种情况)。

处理器(和核心)是可以被分配给任何进程使用的资源。一个线程只能在一个核心上执行一次,但是所有进程都共享核心。操作系统负责将进程调度到可用的核心上执行。因此,当任何进程由于让同一核心内的另一个进程执行(或继续执行)而“暂停”时,没有理由期望该进程下次会在相同的核心上恢复执行。

当您在相对低CPU活动的(多核)机器上运行单个高CPU消耗的进程并执行 htop 时,可以轻微地观察到这一点。然后,您会发现始终有一个高度占用的核心,但它所在的核心会定期更改。


好的,以下陈述仅为猜测,但也许有一组可用的CPU来运行进程,您可以指定哪个池可用于哪个进程?也许您可以谈谈Node.js核心集群模块如何与您所说的内容相适应。 - Alexander Mills
1
进程(或线程)调度是操作系统的专属职责。您可以要求它创建一个新的进程(或线程),但您无法决定哪个物理处理器将执行它。我不确定您是否会混淆Node线程池,实际上,它是一个专用于同时处理异步操作的线程池。请参阅http://www.future-processing.pl/blog/on-problems-with-threads-in-node-js/。 - bitifet
谢谢,我该如何从node.js进程内访问Node.js线程池? - Alexander Mills
1
这篇文章解释得相当不错。基本上,无法完成。 http://superuser.com/questions/867127/determine-which-cpu-a-process-is-running-on。如果您想要更多的保证,请使用亲和力。 - JDPeckham

6
在思考为什么您想了解这种信息时,我认为我理解了您困惑的核心。请注意,一个进程每毫秒可能会多次切换核心。操作系统在调度方面做得非常好,我无法想象性能是如此重要,以至于您需要改进它(因为在这种情况下,您将编写自己的操作系统层,而不是在节点中)。除非是使用自定义操作系统的嵌入式硬件,否则在运行在某个核心上的进程和必须在该核心上启动的进程之间绝对没有可观察到的延迟。
请注意,现代系统甚至可以开关核心。因此,想象一个具有2个核心和2个节点进程服务请求的Web服务器。晚上工作不多时,操作系统关闭第2个核心,两个进程都在第1个核心上愉快地运行,为偶尔的请求提供服务。然后当繁忙时,操作系统启动第二个核心,大多数时间两个节点进程将同时运行,每个进程都在自己的核心上运行。但是请注意,操作系统还有很多其他进程(例如,更新实时时钟)。因此,在某些时候,节点进程A可能在核心1上运行,节点进程B可能在核心2上运行。然后,核心1用于更新时钟,而核心2仍在运行B。然而,在更新时钟的一半时,进程B在核心2上停止,进程A在那里启动。完成时钟更新后,进程B再次在核心1上启动。所有这些都发生在不到一微秒的时间内。
因此,在现代架构上,上下文切换每秒发生数百万次,不必担心它们。即使您发现在某个时候2个节点进程在不同的核心上运行,也无法保证一微秒后仍然是这样。而且,可能操作系统会比您更好地优化此过程。
现在,您可能感兴趣的事情是,是否有理由让两个进程始终在同一个核心上运行(例如,因为它们实际上不是两个进程,而是向同一个节点服务器发送的不同请求)。这只需要检查一次。只需完全加载两个节点实例,并在top/process explorer等中检查它们的CPU使用率是否超过100%。如果是,则可以假定它们至少能够在不同的核心上运行,并进一步假定操作系统将调度它们到不同的核心(如果它们从中受益)。

谢谢Claude,没错,我想知道在启动多个Node.js进程时,这些进程是否确实在机器上使用了多个核心。在阅读这些答案之前,我认为Node.js进程只会在一个核心上运行;但实际上这只意味着一次只有一个核心(这是显而易见的),但并不意味着在进程的生命周期中它将被限制在一个核心上(这是我之前所想的)。但是,无论如何,我想知道当我使用集群模块或使用Node启动子进程时,它们是否充分利用了机器上的资源(核心)。 - Alexander Mills
1
因此,您应该能够以某种自动方式进行测试,对两者施加人工负载,然后以编程方式查看它们的组合CPU使用情况,但这对我来说似乎毫无用处---因为如果它们曾经是独立的,那么在随后的运行中它们仍将是独立的。实际上,可能会起作用的是比较进程ID,因为我非常确定,如果它们不同,则它们将独立运行(尽管从理论上讲,它们仍然可以使用锁定来永远无法超过100%的CPU)。请注意,反之则不成立:如果它们具有相同的pid,则它们仍可能是不同的线程,并且能够在两个核心上运行。 - Claude
2
顺便说一下,即使您找出了如何查询线程运行的核心,也无法保证两个程序在同一个时钟周期内执行此操作,因此它仍然无法告诉您任何信息 --- 在两个程序中的两个调用之间,它们可能已经多次切换核心。 - Claude
我认为,如果任何进程的峰值 CPU 使用率 > (100%/核心数),那么它实际上正在使用多个核心。 - JDPeckham
@JDPeckham:我认为我的系统报告每个核心的CPU使用率,因此100%的峰值CPU使用率意味着1个核心完全加载。多线程进程可以(在许多情况下)因此在我的系统上使用超过100%的CPU(至少在我的Mac和afaik上的Linux中使用top / htop;在其他操作系统/其他程序上可能会有所不同。这只是关于什么是100%CPU的定义)。因此,无需除以核心数。 - Claude

2
可能的 Linux 方法:
function getPSR( pid, callback ) {
    var exec = require('child_process').execSync;

    var command = 'ps -A -o pid,psr -p ' + pid + ' | grep ' + pid + ' | grep -v grep |head -n 1 | awk \'{print $2}\'';

    var result = exec( command );

    return result.toString("utf-8").trim();
}

function getTIDs( pid ) {
    var exec = require('child_process').execSync;

    var command = 'ps -mo tid,psr -p ' + pid + ' | grep -v grep | awk \'/[0-9]/ {print("{\\042id\\042 : ", $1, ",\\042psr\\042:", $2, " }," )}\'';
    var tids = '[ ' + exec(command) + '{"id": false} ]';

    return JSON.parse(tids);
}

function setPSR( pid, psr ) {
    var exec = require('child_process').execSync;
    var command = 'taskset -pc ' + psr + ' ' + pid  + '; kill -STOP ' + pid + '; kill -CONT ' + pid;
    var result = exec(command);

    return result.toString("utf-8").trim();
}

function setTIDsPSR( pid, psr ) {
    var tids = getTIDs(pid);
    console.log(tids);
    for (var i in tids) {
    if (tids[i].id) {
        console.log( setPSR( tids[i].id, psr ) );
    }
    }
}

2

尝试使用https://www.npmjs.com/package/nodeaffinity

此方法适用于Windows和Linux操作系统,但不包括OSX。

var nc = require('nodeaffinity');

//Returns the cpus/cores (affinity mask) on which current node process is allowed to run 
//Failure returns -1 
console.log(nc.getAffinity()); 

//Sets process CPU affinity, here 3 means 011 i.e. process will be allowed to run on cpu0 and cpu1 
// returns same mask id success , if failure retuen -1. 
console.log(nc.setAffinity(3));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接