SystemInfo.cpp 9.0 KB
Newer Older
J
jinhai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

S
starlord 已提交
18
#include "metrics/SystemInfo.h"
Y
yu yunfeng 已提交
19

S
starlord 已提交
20
#include <nvml.h>
Y
yu yunfeng 已提交
21 22 23
#include <sys/types.h>
#include <unistd.h>
#include <fstream>
S
starlord 已提交
24
#include <iostream>
S
starlord 已提交
25 26
#include <string>
#include <utility>
Y
yu yunfeng 已提交
27 28

namespace zilliz {
J
jinhai 已提交
29
namespace milvus {
Y
yu yunfeng 已提交
30 31
namespace server {

S
starlord 已提交
32 33 34
void
SystemInfo::Init() {
    if (initialized_) return;
Y
yu yunfeng 已提交
35 36 37

    initialized_ = true;

Y
yu yunfeng 已提交
38
    // initialize CPU information
S
starlord 已提交
39
    FILE* file;
Y
yu yunfeng 已提交
40
    struct tms time_sample;
Y
yu yunfeng 已提交
41
    char line[128];
Y
yu yunfeng 已提交
42 43 44
    last_cpu_ = times(&time_sample);
    last_sys_cpu_ = time_sample.tms_stime;
    last_user_cpu_ = time_sample.tms_utime;
Y
yu yunfeng 已提交
45
    file = fopen("/proc/cpuinfo", "r");
Y
yu yunfeng 已提交
46
    num_processors_ = 0;
S
starlord 已提交
47
    while (fgets(line, 128, file) != NULL) {
Y
yu yunfeng 已提交
48
        if (strncmp(line, "processor", 9) == 0) num_processors_++;
K
kun yu 已提交
49 50 51
        if (strncmp(line, "physical", 8) == 0) {
            num_physical_processors_ = ParseLine(line);
        }
Y
yu yunfeng 已提交
52
    }
Y
yu yunfeng 已提交
53
    total_ram_ = GetPhysicalMemory();
Y
yu yunfeng 已提交
54 55
    fclose(file);

S
starlord 已提交
56
    // initialize GPU information
Y
yu yunfeng 已提交
57 58
    nvmlReturn_t nvmlresult;
    nvmlresult = nvmlInit();
S
starlord 已提交
59
    if (NVML_SUCCESS != nvmlresult) {
Y
yu yunfeng 已提交
60
        printf("System information initilization failed");
S
starlord 已提交
61
        return;
Y
yu yunfeng 已提交
62
    }
Y
yu yunfeng 已提交
63
    nvmlresult = nvmlDeviceGetCount(&num_device_);
S
starlord 已提交
64
    if (NVML_SUCCESS != nvmlresult) {
Y
yu yunfeng 已提交
65
        printf("Unable to get devidce number");
S
starlord 已提交
66
        return;
Y
yu yunfeng 已提交
67 68
    }

S
starlord 已提交
69
    // initialize network traffic information
S
starlord 已提交
70
    std::pair<uint64_t, uint64_t> in_and_out_octets = Octets();
Y
yu yunfeng 已提交
71 72 73
    in_octets_ = in_and_out_octets.first;
    out_octets_ = in_and_out_octets.second;
    net_time_ = std::chrono::system_clock::now();
Y
yu yunfeng 已提交
74 75
}

S
starlord 已提交
76
uint64_t
S
starlord 已提交
77
SystemInfo::ParseLine(char* line) {
Y
yu yunfeng 已提交
78 79
    // This assumes that a digit will be found and the line ends in " Kb".
    int i = strlen(line);
S
starlord 已提交
80
    const char* p = line;
Y
yu yunfeng 已提交
81 82 83
    while (*p < '0' || *p > '9') p++;
    line[i - 3] = '\0';
    i = atoi(p);
S
starlord 已提交
84
    return static_cast<uint64_t>(i);
Y
yu yunfeng 已提交
85 86
}

S
starlord 已提交
87
uint64_t
Y
yu yunfeng 已提交
88 89
SystemInfo::GetPhysicalMemory() {
    struct sysinfo memInfo;
S
starlord 已提交
90 91
    sysinfo(&memInfo);
    uint64_t totalPhysMem = memInfo.totalram;
S
starlord 已提交
92
    // Multiply in next statement to avoid int overflow on right hand side...
Y
yu yunfeng 已提交
93 94 95 96
    totalPhysMem *= memInfo.mem_unit;
    return totalPhysMem;
}

S
starlord 已提交
97
uint64_t
Y
yu yunfeng 已提交
98
SystemInfo::GetProcessUsedMemory() {
S
starlord 已提交
99 100
    // Note: this value is in KB!
    FILE* file = fopen("/proc/self/status", "r");
S
starlord 已提交
101 102 103
    constexpr uint64_t line_length = 128;
    uint64_t result = -1;
    constexpr uint64_t KB_SIZE = 1024;
Y
fix  
yu yunfeng 已提交
104
    char line[line_length];
Y
yu yunfeng 已提交
105

S
starlord 已提交
106 107
    while (fgets(line, line_length, file) != NULL) {
        if (strncmp(line, "VmRSS:", 6) == 0) {
Y
fix  
yu yunfeng 已提交
108
            result = ParseLine(line);
Y
yu yunfeng 已提交
109 110 111 112 113
            break;
        }
    }
    fclose(file);
    // return value in Byte
S
starlord 已提交
114
    return (result * KB_SIZE);
Y
yu yunfeng 已提交
115 116 117 118
}

double
SystemInfo::MemoryPercent() {
Y
yu yunfeng 已提交
119
    if (!initialized_) Init();
S
starlord 已提交
120
    return (double)(GetProcessUsedMemory() * 100) / (double)total_ram_;
Y
yu yunfeng 已提交
121 122
}

K
kun yu 已提交
123 124
std::vector<double>
SystemInfo::CPUCorePercent() {
S
starlord 已提交
125 126
    std::vector<uint64_t> prev_work_time_array;
    std::vector<uint64_t> prev_total_time_array = getTotalCpuTime(prev_work_time_array);
K
kun yu 已提交
127
    usleep(100000);
S
starlord 已提交
128 129
    std::vector<uint64_t> cur_work_time_array;
    std::vector<uint64_t> cur_total_time_array = getTotalCpuTime(cur_work_time_array);
K
kun yu 已提交
130 131

    std::vector<double> cpu_core_percent;
K
kun yu 已提交
132
    for (int i = 1; i < num_processors_; i++) {
K
kun yu 已提交
133 134 135 136 137 138 139
        double total_cpu_time = cur_total_time_array[i] - prev_total_time_array[i];
        double cpu_work_time = cur_work_time_array[i] - prev_work_time_array[i];
        cpu_core_percent.push_back((cpu_work_time / total_cpu_time) * 100);
    }
    return cpu_core_percent;
}

S
starlord 已提交
140
std::vector<uint64_t>
S
starlord 已提交
141
SystemInfo::getTotalCpuTime(std::vector<uint64_t>& work_time_array) {
S
starlord 已提交
142
    std::vector<uint64_t> total_time_array;
S
starlord 已提交
143
    FILE* file = fopen("/proc/stat", "r");
K
kun yu 已提交
144 145 146 147 148
    if (file == NULL) {
        perror("Could not open stat file");
        return total_time_array;
    }

S
starlord 已提交
149 150
    uint64_t user = 0, nice = 0, system = 0, idle = 0;
    uint64_t iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guestnice = 0;
K
kun yu 已提交
151 152 153

    for (int i = 0; i < num_processors_; i++) {
        char buffer[1024];
S
starlord 已提交
154
        char* ret = fgets(buffer, sizeof(buffer) - 1, file);
K
kun yu 已提交
155 156 157 158 159 160
        if (ret == NULL) {
            perror("Could not read stat file");
            fclose(file);
            return total_time_array;
        }

S
starlord 已提交
161 162
        sscanf(buffer, "cpu  %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu", &user, &nice, &system, &idle,
               &iowait, &irq, &softirq, &steal, &guest, &guestnice);
K
kun yu 已提交
163 164 165 166 167 168 169 170 171

        work_time_array.push_back(user + nice + system);
        total_time_array.push_back(user + nice + system + idle + iowait + irq + softirq + steal);
    }

    fclose(file);
    return total_time_array;
}

Y
yu yunfeng 已提交
172 173
double
SystemInfo::CPUPercent() {
Y
yu yunfeng 已提交
174 175
    if (!initialized_) Init();
    struct tms time_sample;
Y
yu yunfeng 已提交
176 177 178
    clock_t now;
    double percent;

Y
yu yunfeng 已提交
179
    now = times(&time_sample);
S
starlord 已提交
180 181
    if (now <= last_cpu_ || time_sample.tms_stime < last_sys_cpu_ || time_sample.tms_utime < last_user_cpu_) {
        // Overflow detection. Just skip this value.
Y
yu yunfeng 已提交
182
        percent = -1.0;
S
starlord 已提交
183
    } else {
S
starlord 已提交
184
        percent = (time_sample.tms_stime - last_sys_cpu_) + (time_sample.tms_utime - last_user_cpu_);
Y
yu yunfeng 已提交
185
        percent /= (now - last_cpu_);
Y
yu yunfeng 已提交
186 187
        percent *= 100;
    }
Y
yu yunfeng 已提交
188 189 190
    last_cpu_ = now;
    last_sys_cpu_ = time_sample.tms_stime;
    last_user_cpu_ = time_sample.tms_utime;
Y
yu yunfeng 已提交
191 192 193 194

    return percent;
}

S
starlord 已提交
195
std::vector<uint64_t>
K
kun yu 已提交
196
SystemInfo::GPUMemoryTotal() {
Y
yu yunfeng 已提交
197
    // get GPU usage percent
S
starlord 已提交
198 199
    if (!initialized_) Init();
    std::vector<uint64_t> result;
K
kun yu 已提交
200
    nvmlMemory_t nvmlMemory;
Y
yu yunfeng 已提交
201
    for (int i = 0; i < num_device_; ++i) {
Y
yu yunfeng 已提交
202 203
        nvmlDevice_t device;
        nvmlDeviceGetHandleByIndex(i, &device);
K
kun yu 已提交
204 205
        nvmlDeviceGetMemoryInfo(device, &nvmlMemory);
        result.push_back(nvmlMemory.total);
Y
yu yunfeng 已提交
206 207 208 209
    }
    return result;
}

S
starlord 已提交
210 211 212 213
std::vector<uint64_t>
SystemInfo::GPUTemperature() {
    if (!initialized_) Init();
    std::vector<uint64_t> result;
K
kun yu 已提交
214 215 216 217
    for (int i = 0; i < num_device_; i++) {
        nvmlDevice_t device;
        nvmlDeviceGetHandleByIndex(i, &device);
        unsigned int temp;
S
starlord 已提交
218
        nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temp);
K
kun yu 已提交
219 220 221 222
        result.push_back(temp);
    }
    return result;
}
S
starlord 已提交
223

K
kun yu 已提交
224
std::vector<float>
S
starlord 已提交
225
SystemInfo::CPUTemperature() {
K
kun yu 已提交
226 227 228
    std::vector<float> result;
    for (int i = 0; i <= num_physical_processors_; ++i) {
        std::string path = "/sys/class/thermal/thermal_zone" + std::to_string(i) + "/temp";
S
starlord 已提交
229
        FILE* file = fopen(path.data(), "r");
K
kun yu 已提交
230 231 232 233 234 235 236
        if (file == NULL) {
            perror("Could not open thermal file");
            return result;
        }
        float temp;
        fscanf(file, "%f", &temp);
        result.push_back(temp / 1000);
Y
Yu Kun 已提交
237
        fclose(file);
K
kun yu 已提交
238 239 240
    }
}

S
starlord 已提交
241
std::vector<uint64_t>
Y
yu yunfeng 已提交
242 243
SystemInfo::GPUMemoryUsed() {
    // get GPU memory used
S
starlord 已提交
244
    if (!initialized_) Init();
Y
yu yunfeng 已提交
245

S
starlord 已提交
246
    std::vector<uint64_t> result;
Y
yu yunfeng 已提交
247
    nvmlMemory_t nvmlMemory;
Y
yu yunfeng 已提交
248
    for (int i = 0; i < num_device_; ++i) {
Y
yu yunfeng 已提交
249 250 251 252 253 254 255 256
        nvmlDevice_t device;
        nvmlDeviceGetHandleByIndex(i, &device);
        nvmlDeviceGetMemoryInfo(device, &nvmlMemory);
        result.push_back(nvmlMemory.used);
    }
    return result;
}

S
starlord 已提交
257 258
std::pair<uint64_t, uint64_t>
SystemInfo::Octets() {
Y
yu yunfeng 已提交
259
    pid_t pid = getpid();
S
starlord 已提交
260
    //    const std::string filename = "/proc/"+std::to_string(pid)+"/net/netstat";
Y
yu yunfeng 已提交
261 262 263 264
    const std::string filename = "/proc/net/netstat";
    std::ifstream file(filename);
    std::string lastline = "";
    std::string line = "";
S
starlord 已提交
265
    while (file) {
Y
yu yunfeng 已提交
266
        getline(file, line);
S
starlord 已提交
267
        if (file.fail()) {
Y
yu yunfeng 已提交
268 269 270 271 272 273
            break;
        }
        lastline = line;
    }
    std::vector<size_t> space_position;
    size_t space_pos = lastline.find(" ");
S
starlord 已提交
274
    while (space_pos != std::string::npos) {
Y
yu yunfeng 已提交
275
        space_position.push_back(space_pos);
S
starlord 已提交
276
        space_pos = lastline.find(" ", space_pos + 1);
Y
yu yunfeng 已提交
277 278
    }
    // InOctets is between 6th and 7th " " and OutOctets is between 7th and 8th " "
S
starlord 已提交
279 280 281 282 283 284 285 286 287 288
    size_t inoctets_begin = space_position[6] + 1;
    size_t inoctets_length = space_position[7] - inoctets_begin;
    size_t outoctets_begin = space_position[7] + 1;
    size_t outoctets_length = space_position[8] - outoctets_begin;
    std::string inoctets = lastline.substr(inoctets_begin, inoctets_length);
    std::string outoctets = lastline.substr(outoctets_begin, outoctets_length);

    uint64_t inoctets_bytes = std::stoull(inoctets);
    uint64_t outoctets_bytes = std::stoull(outoctets);
    std::pair<uint64_t, uint64_t> res(inoctets_bytes, outoctets_bytes);
Y
yu yunfeng 已提交
289 290 291
    return res;
}

S
starlord 已提交
292 293 294
}  // namespace server
}  // namespace milvus
}  // namespace zilliz