sys_kernel_mm_ksm.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_KSM_NAME "/sys/kernel/mm/ksm"
  4. typedef struct ksm_name_value {
  5. char filename[FILENAME_MAX + 1];
  6. unsigned long long value;
  7. } KSM_NAME_VALUE;
  8. #define PAGES_SHARED 0
  9. #define PAGES_SHARING 1
  10. #define PAGES_UNSHARED 2
  11. #define PAGES_VOLATILE 3
  12. #define PAGES_TO_SCAN 4
  13. KSM_NAME_VALUE values[] = {
  14. [PAGES_SHARED] = { "/sys/kernel/mm/ksm/pages_shared", 0ULL },
  15. [PAGES_SHARING] = { "/sys/kernel/mm/ksm/pages_sharing", 0ULL },
  16. [PAGES_UNSHARED] = { "/sys/kernel/mm/ksm/pages_unshared", 0ULL },
  17. [PAGES_VOLATILE] = { "/sys/kernel/mm/ksm/pages_volatile", 0ULL },
  18. // [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
  19. };
  20. int do_sys_kernel_mm_ksm(int update_every, usec_t dt) {
  21. (void)dt;
  22. static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL/*, *ff_pages_to_scan = NULL*/;
  23. static unsigned long page_size = 0;
  24. if(unlikely(page_size == 0))
  25. page_size = (unsigned long)sysconf(_SC_PAGESIZE);
  26. if(unlikely(!ff_pages_shared)) {
  27. snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_shared");
  28. snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_shared", values[PAGES_SHARED].filename));
  29. ff_pages_shared = procfile_open(values[PAGES_SHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
  30. }
  31. if(unlikely(!ff_pages_sharing)) {
  32. snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_sharing");
  33. snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_sharing", values[PAGES_SHARING].filename));
  34. ff_pages_sharing = procfile_open(values[PAGES_SHARING].filename, " \t:", PROCFILE_FLAG_DEFAULT);
  35. }
  36. if(unlikely(!ff_pages_unshared)) {
  37. snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_unshared");
  38. snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_unshared", values[PAGES_UNSHARED].filename));
  39. ff_pages_unshared = procfile_open(values[PAGES_UNSHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
  40. }
  41. if(unlikely(!ff_pages_volatile)) {
  42. snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_volatile");
  43. snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_volatile", values[PAGES_VOLATILE].filename));
  44. ff_pages_volatile = procfile_open(values[PAGES_VOLATILE].filename, " \t:", PROCFILE_FLAG_DEFAULT);
  45. }
  46. //if(unlikely(!ff_pages_to_scan)) {
  47. // snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_to_scan");
  48. // snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_to_scan", values[PAGES_TO_SCAN].filename));
  49. // ff_pages_to_scan = procfile_open(values[PAGES_TO_SCAN].filename, " \t:", PROCFILE_FLAG_DEFAULT);
  50. //}
  51. if(unlikely(!ff_pages_shared || !ff_pages_sharing || !ff_pages_unshared || !ff_pages_volatile /*|| !ff_pages_to_scan */))
  52. return 1;
  53. unsigned long long pages_shared = 0, pages_sharing = 0, pages_unshared = 0, pages_volatile = 0, /*pages_to_scan = 0,*/ offered = 0, saved = 0;
  54. ff_pages_shared = procfile_readall(ff_pages_shared);
  55. if(unlikely(!ff_pages_shared)) return 0; // we return 0, so that we will retry to open it next time
  56. pages_shared = str2ull(procfile_lineword(ff_pages_shared, 0, 0));
  57. ff_pages_sharing = procfile_readall(ff_pages_sharing);
  58. if(unlikely(!ff_pages_sharing)) return 0; // we return 0, so that we will retry to open it next time
  59. pages_sharing = str2ull(procfile_lineword(ff_pages_sharing, 0, 0));
  60. ff_pages_unshared = procfile_readall(ff_pages_unshared);
  61. if(unlikely(!ff_pages_unshared)) return 0; // we return 0, so that we will retry to open it next time
  62. pages_unshared = str2ull(procfile_lineword(ff_pages_unshared, 0, 0));
  63. ff_pages_volatile = procfile_readall(ff_pages_volatile);
  64. if(unlikely(!ff_pages_volatile)) return 0; // we return 0, so that we will retry to open it next time
  65. pages_volatile = str2ull(procfile_lineword(ff_pages_volatile, 0, 0));
  66. //ff_pages_to_scan = procfile_readall(ff_pages_to_scan);
  67. //if(unlikely(!ff_pages_to_scan)) return 0; // we return 0, so that we will retry to open it next time
  68. //pages_to_scan = str2ull(procfile_lineword(ff_pages_to_scan, 0, 0));
  69. offered = pages_sharing + pages_shared + pages_unshared + pages_volatile;
  70. saved = pages_sharing;
  71. if(unlikely(!offered /*|| !pages_to_scan*/ && netdata_zero_metrics_enabled == CONFIG_BOOLEAN_NO)) return 0;
  72. // --------------------------------------------------------------------
  73. {
  74. static RRDSET *st_mem_ksm = NULL;
  75. static RRDDIM *rd_shared = NULL, *rd_unshared = NULL, *rd_sharing = NULL, *rd_volatile = NULL/*, *rd_to_scan = NULL*/;
  76. if (unlikely(!st_mem_ksm)) {
  77. st_mem_ksm = rrdset_create_localhost(
  78. "mem"
  79. , "ksm"
  80. , NULL
  81. , "ksm"
  82. , NULL
  83. , "Kernel Same Page Merging"
  84. , "MiB"
  85. , PLUGIN_PROC_NAME
  86. , PLUGIN_PROC_MODULE_KSM_NAME
  87. , NETDATA_CHART_PRIO_MEM_KSM
  88. , update_every
  89. , RRDSET_TYPE_STACKED
  90. );
  91. rd_shared = rrddim_add(st_mem_ksm, "shared", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  92. rd_unshared = rrddim_add(st_mem_ksm, "unshared", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  93. rd_sharing = rrddim_add(st_mem_ksm, "sharing", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  94. rd_volatile = rrddim_add(st_mem_ksm, "volatile", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  95. //rd_to_scan = rrddim_add(st_mem_ksm, "to_scan", "to scan", -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  96. }
  97. else
  98. rrdset_next(st_mem_ksm);
  99. rrddim_set_by_pointer(st_mem_ksm, rd_shared, pages_shared * page_size);
  100. rrddim_set_by_pointer(st_mem_ksm, rd_unshared, pages_unshared * page_size);
  101. rrddim_set_by_pointer(st_mem_ksm, rd_sharing, pages_sharing * page_size);
  102. rrddim_set_by_pointer(st_mem_ksm, rd_volatile, pages_volatile * page_size);
  103. //rrddim_set_by_pointer(st_mem_ksm, rd_to_scan, pages_to_scan * page_size);
  104. rrdset_done(st_mem_ksm);
  105. }
  106. // --------------------------------------------------------------------
  107. {
  108. static RRDSET *st_mem_ksm_savings = NULL;
  109. static RRDDIM *rd_savings = NULL, *rd_offered = NULL;
  110. if (unlikely(!st_mem_ksm_savings)) {
  111. st_mem_ksm_savings = rrdset_create_localhost(
  112. "mem"
  113. , "ksm_savings"
  114. , NULL
  115. , "ksm"
  116. , NULL
  117. , "Kernel Same Page Merging Savings"
  118. , "MiB"
  119. , PLUGIN_PROC_NAME
  120. , PLUGIN_PROC_MODULE_KSM_NAME
  121. , NETDATA_CHART_PRIO_MEM_KSM_SAVINGS
  122. , update_every
  123. , RRDSET_TYPE_AREA
  124. );
  125. rd_savings = rrddim_add(st_mem_ksm_savings, "savings", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  126. rd_offered = rrddim_add(st_mem_ksm_savings, "offered", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  127. }
  128. else
  129. rrdset_next(st_mem_ksm_savings);
  130. rrddim_set_by_pointer(st_mem_ksm_savings, rd_savings, saved * page_size);
  131. rrddim_set_by_pointer(st_mem_ksm_savings, rd_offered, offered * page_size);
  132. rrdset_done(st_mem_ksm_savings);
  133. }
  134. // --------------------------------------------------------------------
  135. {
  136. static RRDSET *st_mem_ksm_ratios = NULL;
  137. static RRDDIM *rd_savings = NULL;
  138. if (unlikely(!st_mem_ksm_ratios)) {
  139. st_mem_ksm_ratios = rrdset_create_localhost(
  140. "mem"
  141. , "ksm_ratios"
  142. , NULL
  143. , "ksm"
  144. , NULL
  145. , "Kernel Same Page Merging Effectiveness"
  146. , "percentage"
  147. , PLUGIN_PROC_NAME
  148. , PLUGIN_PROC_MODULE_KSM_NAME
  149. , NETDATA_CHART_PRIO_MEM_KSM_RATIOS
  150. , update_every
  151. , RRDSET_TYPE_LINE
  152. );
  153. rd_savings = rrddim_add(st_mem_ksm_ratios, "savings", NULL, 1, 10000, RRD_ALGORITHM_ABSOLUTE);
  154. }
  155. else
  156. rrdset_next(st_mem_ksm_ratios);
  157. rrddim_set_by_pointer(st_mem_ksm_ratios, rd_savings, offered ? (saved * 1000000) / offered : 0);
  158. rrdset_done(st_mem_ksm_ratios);
  159. }
  160. return 0;
  161. }