使用 LSF/bsub 基础架构运行 Tcl_DoOneEvent 时利用率高 CPU(~100%)
High CPU Utilization(~100%) while runing Tcl_DoOneEvent using LSF/bsub infrastructure
我已经在 Tcl 中创建了自己的事件循环,如下所示。当我 运行 下面的代码交互使用 tclsh 时,CPU 利用率接近 0% 而当我 运行 同样 运行 使用 bsub 时,CPU 利用率下降高达 100%。
我什至尝试使用下面的方法阻止读取调用,但这也无济于事。
int flag = fcntl(0, F_GETFL);
flag = flag & (~O_NONBLOCK);
(void) fcntl(0, F_SETFL, (long)flag);
这是什么原因,我该如何解决这个问题?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <tcl.h>
#include <errno.h>
#include <fcntl.h>
void fwStdinKeyHandler(ClientData clientData, int mask)
{
unsigned char c = 0;
int rc = read(STDIN_FILENO, &c, 1);
//printf("rc is : %d\n",rc);
while (rc < 1 && errno == EINTR) {}
}
static void MainLoop(void)
{
Tcl_CreateFileHandler(STDIN_FILENO, TCL_READABLE, fwStdinKeyHandler, NULL);
while (1) {
Tcl_DoOneEvent(0);
}
fprintf(stdout,"Exit MainLoop\n");
fflush(stdout);
}
static int Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tcl_SetMainLoop(MainLoop);
return TCL_OK;
}
/*
* Hello_Init -- Called when Tcl loads your extension.
*/
int DLLEXPORT Cmd_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "doone_loop", Hello_Cmd, NULL, NULL);
return TCL_OK;
}
如何制作?
1. 文件保存在,比方说,hello.c
2. gcc -fpic -c hello.c -I/usr/local/include
3. gcc -shared hello.o -o libcmd.so
如何运行?
运行我的文件包含:
加载libcmd.so
doone_loop
/usr/bin/tclsh 运行me => CPU 利用率接近 0%
bsub -q interactive -m "/usr/bin/tclsh 运行me" => CPU 利用率接近 100%
我认为问题是当命令在 运行 内部(系统)bsub
(与之交谈)时,它是非交互的 运行。特别是,stdin 可能来自一个文件或 /dev/null
,这两者都是 always 通知程序可读的(这是一堆低级系统的驯服版本调用)。这意味着您的代码被大量回调,几乎就像它在忙循环一样,产生大量 CPU 用法。
由于这是操作系统级别的行为,您的方法根本行不通。您需要检测自己是否处于这种情况(也许 isatty()
?) 如果事件处理程序无法正常工作,则不安装它。
对于非交互式 shell,没有终端,因此也没有标准输入通道,因此读取调用 returns 为零。因此,我们需要在读取 returns 0.
后在 fwStdinkeyhandler 中添加以下代码
if(rc==0) {
Tcl_DeleteFileHandler(0);
}
我已经在 Tcl 中创建了自己的事件循环,如下所示。当我 运行 下面的代码交互使用 tclsh 时,CPU 利用率接近 0% 而当我 运行 同样 运行 使用 bsub 时,CPU 利用率下降高达 100%。
我什至尝试使用下面的方法阻止读取调用,但这也无济于事。
int flag = fcntl(0, F_GETFL);
flag = flag & (~O_NONBLOCK);
(void) fcntl(0, F_SETFL, (long)flag);
这是什么原因,我该如何解决这个问题?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <tcl.h>
#include <errno.h>
#include <fcntl.h>
void fwStdinKeyHandler(ClientData clientData, int mask)
{
unsigned char c = 0;
int rc = read(STDIN_FILENO, &c, 1);
//printf("rc is : %d\n",rc);
while (rc < 1 && errno == EINTR) {}
}
static void MainLoop(void)
{
Tcl_CreateFileHandler(STDIN_FILENO, TCL_READABLE, fwStdinKeyHandler, NULL);
while (1) {
Tcl_DoOneEvent(0);
}
fprintf(stdout,"Exit MainLoop\n");
fflush(stdout);
}
static int Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tcl_SetMainLoop(MainLoop);
return TCL_OK;
}
/*
* Hello_Init -- Called when Tcl loads your extension.
*/
int DLLEXPORT Cmd_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "doone_loop", Hello_Cmd, NULL, NULL);
return TCL_OK;
}
如何制作?
1. 文件保存在,比方说,hello.c
2. gcc -fpic -c hello.c -I/usr/local/include
3. gcc -shared hello.o -o libcmd.so
如何运行?
运行我的文件包含:
加载libcmd.so
doone_loop
/usr/bin/tclsh 运行me => CPU 利用率接近 0%
bsub -q interactive -m "/usr/bin/tclsh 运行me" => CPU 利用率接近 100%
我认为问题是当命令在 运行 内部(系统)bsub
(与之交谈)时,它是非交互的 运行。特别是,stdin 可能来自一个文件或 /dev/null
,这两者都是 always 通知程序可读的(这是一堆低级系统的驯服版本调用)。这意味着您的代码被大量回调,几乎就像它在忙循环一样,产生大量 CPU 用法。
由于这是操作系统级别的行为,您的方法根本行不通。您需要检测自己是否处于这种情况(也许 isatty()
?) 如果事件处理程序无法正常工作,则不安装它。
对于非交互式 shell,没有终端,因此也没有标准输入通道,因此读取调用 returns 为零。因此,我们需要在读取 returns 0.
后在 fwStdinkeyhandler 中添加以下代码if(rc==0) {
Tcl_DeleteFileHandler(0);
}