Skip to content

Help debugging performance issue. #1313

@taviso

Description

@taviso

Hello, I'm trying to run Lotus Agenda 2.0b in DOSEMU2 in terminal mode. It works perfectly, but uses significant CPU while idle. That's stopping my CPU from entering power saving modes, so was hoping I can fix it.

I have other applications I use under DOSEMU that use barely any resources while not actively using them.

If I use -D9+D, I see the log is full of these:

INT21 at ff10:01e8: AX=2afc, BX=0500, CX=0016, DX=cde4, DS=4f9a, ES=b800
INT21 at ff10:01e8: AX=2c02, BX=0500, CX=07e4, DX=0a0d, DS=4f9a, ES=4f9a
INT21 at ff10:01e8: AX=2a36, BX=ffff, CX=3202, DX=2c02, DS=4f9a, ES=6f78
INT21 at ff10:01e8: AX=2c02, BX=ffff, CX=07e4, DX=0a0d, DS=4f9a, ES=4f9a
INT21 at ff10:01e8: AX=2a9a, BX=ce1c, CX=0000, DX=77f7, DS=4f9a, ES=4f9a
INT21 at ff10:01e8: AX=2c02, BX=ce1c, CX=07e4, DX=0a0d, DS=4f9a, ES=4f9a
INT21 at ff10:01e8: AX=2afc, BX=0500, CX=0016, DX=cde4, DS=4f9a, ES=b800
INT21 at ff10:01e8: AX=2c02, BX=0500, CX=07e4, DX=0a0d, DS=4f9a, ES=4f9a
INT21 at ff10:01e8: AX=2a36, BX=ffff, CX=3202, DX=2c02, DS=4f9a, ES=6f78
INT21 at ff10:01e8: AX=2c02, BX=ffff, CX=07e4, DX=0a0d, DS=4f9a, ES=4f9a

I'm not a DOS programmer, do those AH=2A/2C mean Agenda is doing get system time / get system date in some timer interrupt handler?

If I strace the dosemu process, I see it looks like this:

--- SIGALRM {si_signo=SIGALRM, si_code=SI_USER, si_pid=0, si_uid=0} ---
rt_sigreturn({mask=[]})                 = 0
futex(0x7fe2835c30a0, FUTEX_WAKE_PRIVATE, 1) = 1
select(1, [0], NULL, NULL, {tv_sec=0, tv_usec=0}) = 0 (Timeout)
clock_gettime(CLOCK_MONOTONIC, {tv_sec=387555, tv_nsec=594799400}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=387555, tv_nsec=594929700}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=387555, tv_nsec=595059600}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=387555, tv_nsec=595189300}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=387555, tv_nsec=595319200}) = 0

There are lots of calls to clock_gettime(), I think that's because rdtsc isn't used on SMP systems, config_post_process() disables it. However, if you have a CPU with invariant/synchronized tsc it should be safe, right?

I tried patching the code to allow rdtsc, and it does seem to work okay.

That got rid of the clock_gettime(), calls and now it looks like this:

--- SIGALRM {si_signo=SIGALRM, si_code=SI_USER, si_pid=0, si_uid=0} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
futex(0x7f2ff2f730a0, FUTEX_WAKE_PRIVATE, 1) = 1
select(1, [0], NULL, NULL, {tv_sec=0, tv_usec=0}) = 0 (Timeout)
gettimeofday({tv_sec=1602606610, tv_usec=615213}, NULL) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2836, ...}) = 0
gettimeofday({tv_sec=1602606610, tv_usec=615615}, NULL) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2836, ...}) = 0
gettimeofday({tv_sec=1602606610, tv_usec=615969}, NULL) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2836, ...}) = 0
gettimeofday({tv_sec=1602606610, tv_usec=616364}, NULL) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2836, ...}) = 0

I think the stat()s must be the localtime() in get_linux_ticks() checking if the timezone has changed, I can get rid of those by setting the TZ environment variable (e.g. TZ=America/Los_Angeles dosemu -term).

Now it looks like this:

--- SIGALRM {si_signo=SIGALRM, si_code=SI_USER, si_pid=0, si_uid=0} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
futex(0x7f48babe20a0, FUTEX_WAKE_PRIVATE, 1) = 1
select(1, [0], NULL, NULL, {tv_sec=0, tv_usec=0}) = 0 (Timeout)
gettimeofday({tv_sec=1602606824, tv_usec=623312}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=623535}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=623716}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=623895}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=624093}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=624522}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=624725}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=624949}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=625151}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=625353}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=625550}, NULL) = 0
gettimeofday({tv_sec=1602606824, tv_usec=625970}, NULL) = 0

It's a little better, but still using a lot of CPU while idle. Do you have any advice?

Perhaps I can limit how often this timer interrupt fires?

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions