cgroup.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. const memoize = require('./memoize');
  2. const each = require('./each');
  3. const trim = require('./trim');
  4. const toNum = require('./toNum');
  5. const contain = require('./contain');
  6. const concat = require('./concat');
  7. const range = require('./range');
  8. const startWith = require('./startWith');
  9. const fs = require('fs');
  10. const cpu = {
  11. stat() {
  12. let usage = 0;
  13. if (isV2()) {
  14. const data = parseKeyValue(read('cpu.stat'));
  15. usage = toNum(data['usage_usec']);
  16. } else {
  17. usage = Math.round(toNum(read('cpuacct/cpuacct.usage')) / 1000);
  18. }
  19. return {
  20. usage
  21. };
  22. },
  23. max() {
  24. let max = Infinity;
  25. if (isV2()) {
  26. let data = read('cpu.max');
  27. if (!startWith(data, 'max')) {
  28. data = data.split(' ');
  29. const quota = toNum(data[0]);
  30. const period = toNum(data[1]);
  31. max = quota / period;
  32. }
  33. } else {
  34. const quota = toNum(read('cpu/cpu.cfs_quota_us'));
  35. if (quota !== -1) {
  36. const period = toNum(read('cpu/cpu.cfs_period_us'));
  37. max = quota / period;
  38. }
  39. }
  40. return max;
  41. }
  42. };
  43. const cpuset = {
  44. cpus() {
  45. let effective = [];
  46. let p = 'cpuset/cpuset.effective_cpus';
  47. if (isV2()) {
  48. p = 'cpuset.cpus.effective';
  49. }
  50. effective = parseRange(read(p));
  51. return {
  52. effective
  53. };
  54. }
  55. };
  56. const memory = {
  57. max() {
  58. let max = Infinity;
  59. if (isV2()) {
  60. const data = read('memory.max');
  61. if (data !== 'max') {
  62. max = toNum(data);
  63. }
  64. } else {
  65. max = toNum(read('memory/memory.limit_in_bytes'));
  66. }
  67. return max;
  68. },
  69. current() {
  70. let p = 'memory/memory.usage_in_bytes';
  71. if (isV2()) {
  72. p = 'memory.current';
  73. }
  74. return toNum(read(p));
  75. }
  76. };
  77. const isV2 = memoize(function() {
  78. return fs.existsSync(resolve('cgroup.controllers'));
  79. });
  80. function read(p) {
  81. return fs.readFileSync(resolve(p), 'utf8');
  82. }
  83. /* a 1
  84. * b 2
  85. */
  86. function parseKeyValue(data) {
  87. const ret = {};
  88. each(data.split('\n'), line => {
  89. line = trim(line);
  90. if (line) {
  91. line = line.split(' ');
  92. ret[line[0]] = line[1];
  93. }
  94. });
  95. return ret;
  96. }
  97. /* 1-2,4-5 */
  98. function parseRange(data) {
  99. let ret = [];
  100. each(data.split(','), r => {
  101. if (!contain(r, '-')) {
  102. ret.push(toNum(r));
  103. } else {
  104. r = r.split('-');
  105. ret = concat(ret, range(toNum(r[0]), toNum(r[1]) + 1));
  106. }
  107. });
  108. return ret;
  109. }
  110. function resolve(p) {
  111. return `/sys/fs/cgroup/${p}`;
  112. }
  113. exports = {
  114. cpu,
  115. cpuset,
  116. memory,
  117. version() {
  118. return isV2() ? 2 : 1;
  119. }
  120. };
  121. module.exports = exports;