Power Profiling Tool

Project description

Currently, FreeBSD only provides whole-system power statistics via ACPI, making it difficult to pinpoint individual processes or components responsible for high power usage. I propose to develop a FreeBSD-native power profiling framework inspired by Linux's Performance Co-Pilot (PCP) and integrate RAPL (Running Average Power Limit) support.

Approach to solving the problem

The project idea initially was proposed to port PowerTop from Linux to FreeBSD. Through discussions with mentor Aymeric Wibo, we determined that building a FreeBSD-native solution would be more effective than directly porting PowerTop from Linux, which is largely Intel-centric. Instead of aiming for a fully modular PCP like framework with multiple PMDAs, this project will focus on a simpler, daemon-based architecture that collects historical power metrics. This modular and extensible framework will include a kernel-level component to collect power-related metrics and a user-space monitoring daemon along with a command-line utility for data interpretation. The project will provide users with granular insights into power consumption and establish a foundation for future enhancements in FreeBSD's power management ecosystem.

Deliverables

Milestones

The Final Code

https://github.com/cheeseburger9309/freebsd-src/tree/gsoc2025-powerprofilingtool

The Final Report

https://docs.google.com/document/d/1QEjb4zzkisj4IMA0X8J-irQwLiM8KEQXnNUL6_P45dE/edit?usp=sharing

Notes

Week 1: 2 June - 8 June, Created a Git branch, went through previous RAPL implementation, setup Wiki account. Plan for next week as discussed on Friday, 6/6/25:

  1. Setup FreeBSD on test machine.
  2. Run the RAPL code and see what metrics it provides.
  3. Perform stress tests on the machine with tools like OpenSSL Speed to analyse how useful RAPL information is.
  4. Go through Intel Documentation for RAPL, few papers on RAPL, and other sources. (Listed below)
  5. The tool can be made in two ways -
    1. For user utility, where processes can be sorted by the order of CPU power used.
    2. A dtrace flamegraph that shows power consumption information.

6/9/2025 - Tried to install FreeBSD in the test machine. Unplugged the external hard disk by mistake in the final step of the installation, while installing the FreeBSD handbook:(. The disk is corrupted, so I'm cleaning the disk completely, flashing it again with the iso file, and will image the laptop once again. 6/10/2025 - Installed FreeBSD successfully. Will run the RAPL code and go through the documentations next.

Week 2: 9 June - 15 June, 6/14/2025 - Built the kernel by modifying the /usr/src/sys/conf/newvers.sh file to change the output of the command uname from FreeBSD to 'gsoc2025', as advised by Aymeric during the weekly meeting on Friday, 6/13/25. The total kernel build took 28 minutes. Ran the RAPL code after setting up ssh from my system into the test machine and figuring out some permission issues. "kldload cpuctl" has to be run first before running the rapl executable(compile it with -lm because the pow() function is a part of the code and it requires the math.h header), in order to have access to the /dev/cpuctl folder for raw MSR (Model Specific Registers) access. Will try to use OpenSSL Speed to stress test the machine and check how RAPL can be useful. Going through the documentations simultaneously. Will post an update tomorrow :)

Week 3: 16 June - 22 June, 6/18/2025 - Ran OpenSSL Speed stress test, going through other ways to stress test the machine. Understanding the dev/cpuctl folder that gives access to the hardware on the system. Going through the documentations and other similar tools provided by Intel like Intel PCM (Performance Counter Monitor) to better understand how the data read from the hardware can be manipulated. Off topic, been feeling slightly under the weather for the past 2 days.

Plan for next week as discussed on Friday, 6/20/25,

  1. Understand how Top works.
  2. Dtrace is not a viable option because of the overhead it brings and also has to be integrated into the kernel space. We can use RAPL from the user space itself. So, it would be better to build the tool as a daemon which does historical tracking of the active processes in a given span of time and uses RAPL to get the power related information.
  3. The next task is to print a list of processes that are active and how much power is being used by each of them, to the terminal.

Week 4: 23nd June to 29th June,

6/23/25: Understanding how PowerTop works. Plan for next week as discussed on Friday, 6/27/25, 1. Tom suggested to use cscope to find things. I have to get better at finding things, and understanding the directories. Try to understand things. My mentors also suggested not to hesitate to ask things, if they're taking a long time. 2. Top uses the kvm_getprocs() function in the machine.c file in src/usr/usr.bin/top/ to get the process information. I have to find how it fetches process information. 3. Print a list of processes using kvm_getprocs() and multiply the number of ticks with the power usage from rapl. 4. Tom and Aymeric suggested that they can have a live coding session on Tuesday, to help me get some progress in understanding things. They also suggested some commands like which, and grep to find things easily.

6/29/25: Found a blog at https://patmaddox.com/doc/trunk/www/programming-freebsd-reading-process-information/, which tries to find out how kvm_getprocs() and kvm_openfiles() prints process information. So, tried to execute the same code. Went looking using cscope to find the function implementations. The kvm_getprocs() function is defined in the lib/libkvm/kvm_proc.c file.

The kvm_getprocs() function returns a pointer to a struct of type kinfo_proc, and takes kd which is pointer of type kvm_t as an argument. struct kinfo_proc *kvm_getprocs(kvm_t *kd, .....){ }

I searched for the kvm_t global definition and found this in the lib/libkvm/kvm.h file: typedef struct kvm kvm_t; struct kvm is defined in lib/libkvm/kvm_private.h struct kinfo_proc is defined in sys/sys/user.h The kvm_openfiles() function is defined in lib/libkvm/kvm.c It returns a pointer of type kvm_t which is defined in kvm.h file.

Ran into a linker error when I tried to execute the code: ld: error: undefined symbol: kvm_getprocs ld: error: undefined symbol: kvm_openfiles

Then learnt from Tom that -lkvm has to be included in the command while compiling to link the library. Learnt that we have to look at the man page to know what to include in the command to link the library.

Week 5: 30th June to 6th July,

6/30/25: Was able to statically print the processes after resolving the linking errors. 7/01/25: Had a live coding session with Aymeric, where he patiently guided me to go digging into how the percentage of ticks are being printed by top. It is a struct called ki_pctcpu. And the function to calculate the percentage of cpu is a helper function in top, not a seperate kernel function. Then went digging to check where the type of the struct is defined (It is a fixed point number). Further, went to check where the struct was being assigned a value from the kernel. Was able to print the pctcpu along with the pid, and name of the processes. Aymeric also helped me with various other things like installing vim (neovim), chaging permissions for the directory and told me about setting up LSP to make development better. Thanks to Aymeric for being patient with my delays and network issues. 7/04/25: Tried to shift the bits in the result provided by ki_pctcpu using the FSCALE value to make it look like a percent value. Worked on understanding the runtime and the pctcpu values, by using openssl speed while running the program. The idle process was consuming close to 8.00 i.e. 8 cpu's worth of energy and then when openssl speed was run using 8 cores, the idle value came down to 0.5. Had a one and a half hour meet with Aymeric and Tom. Worked on printing the difference between the runtimes after every time the kvm_getprocs function is called.

Plan for next week as discussed on 7/04/25: 1. Work on the program. Try to print the percentage for a meaningful time period. Try to use runtime and print the percentages. 2. Try to understand how a library is made in FreeBSD. Understand the gpio library because it is very simple. Try to make an rapl library so that the power information can be called from the rapl library, and multiplied with the percentage of cpu using kvm_getprocs. 3. Questions that have to thought about and answered:

  1. Why is the cpu usage gradually increasing/decreasing in our program?
  2. Why is there a delay between our program's output and top?

Week 6: 7th July to 13th July, Worked on understanding the issues in my program.

Week 7: 14th July to 20st July, The percentage that we were trying to print was incorrect. So, went over the different arguments: KERN_PROC_PROC, KERN_PROC_ALL for kvm_getprocs. Accurately got the percentage for KERN_PROC_PROC in the 1 second of interval. Next trying to get it working for KERN_PROC_ALL.

Week 8: 21nd July to 27th July, Aymeric helped me write the code for creating an array of structs for storing the thread_id, and runtime in the structs. When we use KERN_PROC_ALL as an argument for kvm_getprocs, the function outputs different instances for the same process in a single run. This is because it outputs all the processes on different threads (cores) in our machine. Each of the process instances have unique thread ids. So, to access the runtime of each of the processes on different cores, we need to store them in an array of structs with the unique identifying factor being the thread_id. Aymeric helped me create two functions add_thread and find_thread to facilitate this. Aymeric did this for me and told me to implement the same and ask him in case I face any issues. Was able to implement it properly except for updating the thread_id in the main function.

Week 9: 28th July to 3rd August, Worked on printing the percentages for each process in each of the cores with unique thread id's; when using KERN_PROC_ALL as an argument for kvm_getprocs. Worked with Aymeric and Tom on Friday to get the code entirely working. Plan for next week as discussed on 8/01/25: 1. Make a library for the rapl program so that it can be accessed by my code printing the percentage of runtimes for each of the processes. 2. Get the library working and then try to multiply the rapl power output with the percentage of each of the process. 3. Now we are running the code manually for 50 times using a loop and having an interval of 1 second between the runs. The next step is to make this a daemon which runs till the command is stopped.

Week 10: 4th August to 10th August, 8/05/2025: Going through the rapl-read.c file and understanding how to build a library (the functions are static). 8/06/2025: Working on building librapl 8/07/2025: Using libgpio as a reference to build librapl. Also looked at libc to understand how to add libraries referenced by the .c file in our library into the Makefile as a dependency. I also tried getting it directly rather than recording it as a build dependency, and was not successful.

Plan for next week as discussed on Friday, 8/08/25: 1. Read the RAPL code properly. 2. Look to see if there is any per-core information being accessed/printed in the rapl code. 3. Rewrite the rapl_msr function to return/populate a structure with the five values rather than 0 or 1. 4. Write a seperate function that returns the static part of the output. 5. Use the power measurements in the process code. 6. Write a draft of the final report. 7. Update the code onto Github.

Week 11: 11th August to 17th August, Worked on the rapl code (rapl_msr function and other fucntions), was able to populate a structure with the required values.

Week 12: 18th August to 24th August, Finally was able to print the per-process energy usage using rapl. Also, started drafting the report.

Week 13: 25th August to 31st September, Finished the report and submitted all the deliverables including the code on Github, a report, the wiki page (this one), and the GSoC Final Submission.

* Week 1: https://papers.freebsd.org/2018/bsdcan/percival-profiling_the_freebsd_kernel_boot/ https://greencompute.uk/Measurement/RAPL https://dl.acm.org/doi/10.1145/3177754 https://github.com/mhirki/rapl-tools https://github.com/mhirki/rapl-tools/blob/master/trace-energy.cc

* Week 3: https://wiki.freebsd.org/DTrace/Tutorial#:~:text=Count%20Process%2DLevel%20Events,99%20Hertz%20on%20all%20CPUs.

* Week 4: https://man.freebsd.org/cgi/man.cgi?query=libprocstat&sektion=3&manpath=FreeBSD+14.3-RELEASE+and+Ports https://patmaddox.com/doc/trunk/www/programming-freebsd-reading-process-information/ https://queue.acm.org/detail.cfm?id=945136 - Code Spelunking: Exploring Cavernous Code Bases by GEORGE V. NEVILLE-NEIL https://queue.acm.org/detail.cfm?id=1483108 - Code Spelunking Redux by George V. Neville-Neil

* Week 5: https://docs.freebsd.org/en/articles/freebsd-src-lsp/


CategoryGsoc

SummerOfCode2025Projects/FreeBSDPowerProfilingTool (last edited 2025-09-09T03:53:45+0000 by SaiKasyapJannabhatla)