info.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "info.h"
  2. #include "error.h"
  3. #include <cmath>
  4. #include <cstdlib>
  5. #if defined(_linux_) || defined(_cygwin_)
  6. #include <fcntl.h>
  7. #include <sys/sysinfo.h>
  8. #endif
  9. #if defined(_win_)
  10. #include "winint.h"
  11. #include <stdio.h>
  12. #else
  13. #include <unistd.h>
  14. #endif
  15. #if defined(_bionic_)
  16. //TODO
  17. #elif defined(_cygwin_)
  18. static int getloadavg(double* loadavg, int nelem) {
  19. for (int i = 0; i < nelem; ++i) {
  20. loadavg[i] = 0.0;
  21. }
  22. return nelem;
  23. }
  24. #elif defined(_unix_) || defined(_darwin_)
  25. #include <sys/types.h>
  26. #endif
  27. #if defined(_freebsd_) || defined(_darwin_)
  28. #include <sys/sysctl.h>
  29. #endif
  30. #include <util/string/ascii.h>
  31. #include <util/string/cast.h>
  32. #include <util/string/strip.h>
  33. #include <util/stream/file.h>
  34. #include <util/generic/yexception.h>
  35. #if defined(_linux_)
  36. /*
  37. This function olny works properly if you apply correct setting to your nanny/deploy project
  38. In nanny - Runtime -> Instance spec -> Advanced settings -> Cgroupfs settings: Mount mode = Read only
  39. In deploy - Stage - Edit stage - Box - Cgroupfs settings: Mount mode = Read only
  40. */
  41. static inline double CgroupCpus() {
  42. try {
  43. double q = FromString<int32_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_quota_us").ReadAll()));
  44. if (q <= 0) {
  45. return 0;
  46. }
  47. double p = FromString<int32_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_period_us").ReadAll()));
  48. if (p <= 0) {
  49. return 0;
  50. }
  51. return q / p;
  52. } catch (...) {
  53. return 0;
  54. }
  55. }
  56. #endif
  57. size_t NSystemInfo::NumberOfMillicores() {
  58. #if defined(_linux_)
  59. return CgroupCpus() * 1000;
  60. #else
  61. // fallback behaviour if cgroupfs is not available
  62. // returns number of millicores which is a multiple of an integer number of cpus
  63. return NSystemInfo::NumberOfCpus() * 1000;
  64. #endif
  65. }
  66. size_t NSystemInfo::NumberOfCpus() {
  67. #if defined(_linux_)
  68. if (auto res = CgroupCpus(); res) {
  69. return Max<ssize_t>(1, std::llround(res));
  70. }
  71. #endif
  72. #if defined(_win_)
  73. SYSTEM_INFO info;
  74. GetSystemInfo(&info);
  75. return info.dwNumberOfProcessors;
  76. #elif defined(_SC_NPROCESSORS_ONLN)
  77. return sysconf(_SC_NPROCESSORS_ONLN);
  78. #elif defined(_linux_)
  79. unsigned ret;
  80. int fd, nread, column;
  81. char buf[512];
  82. static const char matchstr[] = "processor\t:";
  83. fd = open("/proc/cpuinfo", O_RDONLY);
  84. if (fd == -1) {
  85. abort();
  86. }
  87. column = 0;
  88. ret = 0;
  89. while (true) {
  90. nread = read(fd, buf, sizeof(buf));
  91. if (nread <= 0) {
  92. break;
  93. }
  94. for (int i = 0; i < nread; ++i) {
  95. const char ch = buf[i];
  96. if (ch == '\n') {
  97. column = 0;
  98. } else if (column != -1) {
  99. if (AsciiToLower(ch) == matchstr[column]) {
  100. ++column;
  101. if (column == sizeof(matchstr) - 1) {
  102. column = -1;
  103. ++ret;
  104. }
  105. } else {
  106. column = -1;
  107. }
  108. }
  109. }
  110. }
  111. if (ret == 0) {
  112. abort();
  113. }
  114. close(fd);
  115. return ret;
  116. #elif defined(_freebsd_) || defined(_darwin_)
  117. int mib[2];
  118. size_t len;
  119. unsigned ncpus = 1;
  120. mib[0] = CTL_HW;
  121. mib[1] = HW_NCPU;
  122. len = sizeof(ncpus);
  123. if (sysctl(mib, 2, &ncpus, &len, nullptr, 0) == -1) {
  124. abort();
  125. }
  126. return ncpus;
  127. #else
  128. #error todo
  129. #endif
  130. }
  131. size_t NSystemInfo::LoadAverage(double* la, size_t len) {
  132. #if defined(_win_) || defined(_musl_) || defined(_bionic_)
  133. int ret = -1;
  134. #else
  135. for (size_t i = 0; i < len; ++i) {
  136. la[i] = 0;
  137. }
  138. int ret = getloadavg(la, len);
  139. #endif
  140. if (ret < 0) {
  141. for (size_t i = 0; i < len; ++i) {
  142. la[i] = 0;
  143. }
  144. ret = len;
  145. }
  146. return (size_t)ret;
  147. }
  148. static size_t NCpus;
  149. static size_t NMillicores;
  150. size_t NSystemInfo::CachedNumberOfCpus() {
  151. if (!NCpus) {
  152. NCpus = NumberOfCpus();
  153. }
  154. return NCpus;
  155. }
  156. size_t NSystemInfo::CachedNumberOfMillicores() {
  157. if (!NMillicores) {
  158. NMillicores = NumberOfMillicores();
  159. }
  160. return NMillicores;
  161. }
  162. size_t NSystemInfo::GetPageSize() noexcept {
  163. #if defined(_win_)
  164. SYSTEM_INFO sysInfo;
  165. GetSystemInfo(&sysInfo);
  166. return sysInfo.dwPageSize;
  167. #else
  168. return sysconf(_SC_PAGESIZE);
  169. #endif
  170. }
  171. size_t NSystemInfo::TotalMemorySize() {
  172. #if defined(_linux_) && defined(_64_)
  173. try {
  174. auto q = FromString<size_t>(StripString(TFileInput("/sys/fs/cgroup/memory/memory.limit_in_bytes").ReadAll()));
  175. if (q < (((size_t)1) << 60)) {
  176. return q;
  177. }
  178. } catch (...) {
  179. }
  180. #endif
  181. #if defined(_linux_) || defined(_cygwin_)
  182. struct sysinfo info;
  183. sysinfo(&info);
  184. return info.totalram;
  185. #elif defined(_darwin_)
  186. int mib[2];
  187. int64_t memSize;
  188. size_t length;
  189. // Get the Physical memory size
  190. mib[0] = CTL_HW;
  191. mib[1] = HW_MEMSIZE;
  192. length = sizeof(int64_t);
  193. if (sysctl(mib, 2, &memSize, &length, NULL, 0) != 0) {
  194. ythrow yexception() << "sysctl failed: " << LastSystemErrorText();
  195. }
  196. return (size_t)memSize;
  197. #elif defined(_win_)
  198. MEMORYSTATUSEX memoryStatusEx;
  199. memoryStatusEx.dwLength = sizeof(memoryStatusEx);
  200. if (!GlobalMemoryStatusEx(&memoryStatusEx)) {
  201. ythrow yexception() << "GlobalMemoryStatusEx failed: " << LastSystemErrorText();
  202. }
  203. return (size_t)memoryStatusEx.ullTotalPhys;
  204. #else
  205. return 0;
  206. #endif
  207. }
  208. size_t NSystemInfo::MaxOpenFiles() {
  209. #if defined(ANDROID) || defined(__ANDROID__)
  210. return sysconf(_SC_OPEN_MAX);
  211. #elif defined(_win_)
  212. return _getmaxstdio();
  213. #else
  214. return getdtablesize();
  215. #endif
  216. }