Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: hibernate: make compression threads configurable

The number of compression/decompression threads has a direct impact on
hibernate image generation and resume latency. Using more threads can
reduce overall resume time, but on systems with fewer CPU cores it may
also introduce contention and reduce efficiency.

Performance was evaluated on an 8-core ARM system, averaged over 10 runs:

Threads Hibernate(s) Resume(s)
--------------------------------
3 12.14 18.86
4 12.28 17.48
5 11.09 16.77
6 11.08 16.44

With 5–6 threads, resume latency improves by approximately 12% compared
to the default 3-thread configuration, with negligible impact on
hibernate time.

Introduce a new kernel parameter `hibernate_compression_threads=` that
allows users and integrators to tune the number of
compression/decompression threads at boot. This provides a way to
balance performance and CPU utilization across a wide range of hardware
without recompiling the kernel.

Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
Link: https://patch.msgid.link/f24b3ca6416e230a515a154ed4c121d72a7e05a6.1761046167.git.luoxueqin@kylinos.cn
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Xueqin Luo and committed by
Rafael J. Wysocki
090bf5a0 e114e2eb

+31 -4
+10
Documentation/admin-guide/kernel-parameters.txt
··· 1907 1907 /sys/power/pm_test). Only available when CONFIG_PM_DEBUG 1908 1908 is set. Default value is 5. 1909 1909 1910 + hibernate_compression_threads= 1911 + [HIBERNATION] 1912 + Set the number of threads used for compressing or decompressing 1913 + hibernation images. 1914 + 1915 + Format: <integer> 1916 + Default: 3 1917 + Minimum: 1 1918 + Example: hibernate_compression_threads=4 1919 + 1910 1920 highmem=nn[KMG] [KNL,BOOT,EARLY] forces the highmem zone to have an exact 1911 1921 size of <nn>. This works even on boxes that have no 1912 1922 highmem otherwise. This also works to reduce highmem
+21 -4
kernel/power/swap.c
··· 519 519 CMP_HEADER, PAGE_SIZE) 520 520 #define CMP_SIZE (CMP_PAGES * PAGE_SIZE) 521 521 522 - /* Maximum number of threads for compression/decompression. */ 523 - #define CMP_THREADS 3 522 + /* Default number of threads for compression/decompression. */ 523 + #define CMP_THREADS 3 524 + static unsigned int hibernate_compression_threads = CMP_THREADS; 524 525 525 526 /* Minimum/maximum number of pages for read buffering. */ 526 527 #define CMP_MIN_RD_PAGES 1024 ··· 742 741 * footprint. 743 742 */ 744 743 nr_threads = num_online_cpus() - 1; 745 - nr_threads = clamp_val(nr_threads, 1, CMP_THREADS); 744 + nr_threads = clamp_val(nr_threads, 1, hibernate_compression_threads); 746 745 747 746 page = (void *)__get_free_page(GFP_NOIO | __GFP_HIGH); 748 747 if (!page) { ··· 1258 1257 * footprint. 1259 1258 */ 1260 1259 nr_threads = num_online_cpus() - 1; 1261 - nr_threads = clamp_val(nr_threads, 1, CMP_THREADS); 1260 + nr_threads = clamp_val(nr_threads, 1, hibernate_compression_threads); 1262 1261 1263 1262 page = vmalloc_array(CMP_MAX_RD_PAGES, sizeof(*page)); 1264 1263 if (!page) { ··· 1698 1697 } 1699 1698 1700 1699 core_initcall(swsusp_header_init); 1700 + 1701 + static int __init hibernate_compression_threads_setup(char *str) 1702 + { 1703 + int rc = kstrtouint(str, 0, &hibernate_compression_threads); 1704 + 1705 + if (rc) 1706 + return rc; 1707 + 1708 + if (hibernate_compression_threads < 1) 1709 + hibernate_compression_threads = CMP_THREADS; 1710 + 1711 + return 1; 1712 + 1713 + } 1714 + 1715 + __setup("hibernate_compression_threads=", hibernate_compression_threads_setup);