On Mon, Jun 19, 2023 at 05:40:04PM -0500, Scott Cheloha wrote:
> This patch moves the profil(2)- and GPROF-specific parts of
> statclock() out into their own dedicated clock interrupts.
> 
> Test instructions will follow in a reply to this mail.  This needs
> testing on every platform.  Please reply with dmesgs and results.
> Non-amd64 results are greatly appreciated.
> 
> [...]

Okay, here are the instructions.

The profclock() piece should have no negative interactions with
suspend/resume or hibernate/unhibernate, so even if you don't want to
actively test the patch, passively testing the patch by leaving it
applied to the kernel on your daily driver will help.

That said, I want to stress the following:

        Suspend/resume and hibernate/unhibernate are NOT compatible with
        GPROF profiling.  I assume there are many untested interactions
        between the two.

        Make sure to STOP all kernel profiling before attempting to
        suspend or hibernate your machine.  Otherwise I expect it
        will hang.

        GPROF is a kernel compile-time option.  If you don't enable it,
        you have nothing to worry about.

--

To actively test either the profclock or the GPROF parts, first do the
following:

1. Download and apply the work-in-progress moncontrol/gprof patch.
   The patch will make it much easier to test the profclock() parts.
   I sent the patch to tech@ recently:

From: Scott Cheloha <scottcheloha () gmail ! com>
Date: Mon, 19 Jun 2023 03:25:37 +0000
Subject: moncontrol(3), gprof(1): write, read gmon profiling data via utrace(2)

   Or get it from a list archive:

$ PATCH_URL='https://marc.info/?l=openbsd-tech&m=168714523619637&q=raw'
$ PATCH_PATH=/tmp/moncontrol-gprof-utrace.patch2
$ ftp -o $PATCH_PATH $PATCH_URL
$ cd /usr/src
$ patch -C < $PATCH_PATH && patch < $PATCH_PATH

2. Rebuild and reinstall both libc and gprof(1).

$ cd /usr/src/lib/libc && doas make clean && doas make && doas make install
$ cd /usr/src/usr.bin/gprof && doas make clean && doas make && doas make install

--

To test the profclock() parts:

1. In one terminal, start systat(1).  We'll use it to observe the
   clock interrupt rate.  Note the baseline clock interrupt rate.
   It is usually about ((Number-of-online-CPUs) x 200).

$ systat vmstat 2

2. Check your kernel's profhz.  It's normally 1000, though there are
   exceptions.

$ sysctl -n kern.clockrate
tick = 10000, hz = 100, profhz = 1000, stathz = 100
                        ^^^^^^^^^^^^^

3. In a second terminal, build a profiling binary, then run it with
   ktrace(1) to capture the profiling data.  I will use md5(1) here
   because it is easy to eyeball-test.

$ cd /usr/src/bin/md5
$ doas make clean
$ doas make CFLAGS=-pg LDFLAGS='-pg -static'
$ command time ktrace -f ktrace.md5.out1 -tu obj/md5 -ttt

4. Observe the clock interrupt rate in the first terminal.  When the
   profiled process is onproc, the rate should increase by the profhz
   value from step (2).  For example, if your baseline rate is ~1600
   and your kernel's profhz is 1000, the rate should increase to ~2600.

   The md5(1) time trial is mostly userspace computation.  On an otherwise
   idle system the clock interrupt rate should *stay* at that increased
   rate until the program exits.

   When the program exits, the clock interrupt rate should immediately
   return to the baseline rate from step (1).

5. Check the results with your patched gprof(1).  If you're familiar
   with gprof(1)'s output, check that the output is reasonable.

$ gprof obj/md5 ktrace.md5.out1 | less

--

To test the GPROF part:

1. Build and install a GPROF kernel.  This is briefly described in
   options(4).

   In short: first add the following to conf/GENERIC:

makeoptions     PROF="-pg"
option          GPROF

   Second: remake your kernel config.  Last: clean, rebuild, install,
   and reboot.

2. After rebooting, you can double-check you're running a GPROF kernel
   by looking for "Profiling kernel" in your dmesg.

$ dmesg | fgrep 'Profiling kernel'
Profiling kernel, textsize=33858968 [ffffffff80000000..ffffffff8204a598]

3. In one terminal start systat(1) as described above for the profclock()
   testing in steps (1) and (2).  Note the baseline interrupt rate, note
   your kernel's profhz value, etc.

4. In a second terminal, profile a CPU with kgmon(8).  I'm going to
   use CPU 2 in this example.

$ command time doas ksh -c "kgmon -c 2 -b && sleep 10 ; doas kgmon -c 2 -h -pr"
kgmon: kernel profiling is running for cpu 2.
kgmon: kernel profiling is off for cpu 2.
       10.089 real         0.000 user         0.060 sys

4. Observe the clock interrupt rate in the first terminal.

   The rate should increase by the profhz value from step (2).  For
   example, if your baseline rate is ~1600 and your kernel's profhz
   is 1000, the rate should increase to ~2600.  A profiled CPU is
   always "running", so the clock interrupt rate should remain at
   that elevated value until profiling is stopped with kgmon(8).

   Once profiling has stopped, the clock interrupt rate should
   immediately return to the baseline rate from step (2).

5. Check the results with your patched gprof(1).  Note that you
   need to use the '-g' flag to tell the patched gprof(1) that
   the input profiling file is raw gmon data.  If you're familiar
   with GPROF kernel profiling, skim the output to see if it is
   reasonable.

$ doas gprof -g /bsd.booted gmon-02.out | less

Reply via email to