Я пытаюсь извлечь длинные данные int только из / proc / meminfo. Образец файла ниже. Я могу сделать это, но давно известная мантра в Linux гласит: делай одну вещь, и делай это хорошо . Меня раздражает, что я делаю это не так эффективно, как мог бы.
Я не хочу читать / собирать / хранить данные о символах до и после длинных целых. Я не хочу, чтобы программа проверяла символы, чтобы убедиться, что они такие или нет. Я только хочу, чтобы данные long int обрабатывались и сохранялись как переменные, и я хочу, чтобы это делалось с помощью файловых позиций, которые просто пропускают все бесполезные данные char.
Кроме того, я хочу, чтобы данные захватывались как long int и сохранялись как long int. Есть несколько программ, которые делают все, что я сказал, но они начинают хранить информацию в виде строки символов. Эту строку придется преобразовать обратно, сводя на нет большую часть выгоды.
Я бы хотел сделать это, переместив положение файла прямо перед длинным int, а затем сохранив его, но я не понял, как это сделать эффективно. Единственный способ заставить это работать - всегда начинать с начала файла и использовать все большие и большие позиции в файле, чтобы добраться до каждого последующего long int. Результатом было очень медленное выполнение - намного медленнее, чем мой код ниже (~ 30% медленнее). Возможно, программу пришлось перезапустить с самого начала и пройти весь файл, чтобы найти свою позицию?
Я хочу перейти к 766744 , захватить его, сохранить его, а затем перейти (начиная с этой новой текущей позиции) к 191680 , захватить его, сохранить его и прыгнуть 468276 ... Вы поняли.
Позиция файла переходит (за исключением самого первого перехода к 766744 , что составляет 18 символов), начиная с конца длинного целого, проходя после «kB», вниз по строке и заканчивающиеся следующим числом, всегда 22 символа.
/ Proc / MemInfo:
MemTotal: 766744 kB
MemFree: 191680 kB
MemAvailable: 468276 kB
Buffers: 30180 kB
Cached: 272476 kB
Вот две мои лучшие попытки сделать это. Они работают хорошо, но они не так эффективны, как могли бы; они сканируют и проверяют определенные данные и тратят ресурсы на это:
mem.cpp:
/*
Compile using:
g++ -Wall -O2 mem.cpp -o mem
*/
#include<fstream>
#include<unistd.h> // Needed for usleep func.
#include<limits>
int mem()
{
unsigned int memTotal, memFree, buffers, cached;
std::ifstream file("/proc/meminfo");
file.ignore(18, ' ');
file >> memTotal;
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
file.ignore(18, ' ');
file >> memFree;
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Skip 'MemAvailable:' line:
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
file.ignore(18, ' ');
file >> buffers;
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
file.ignore(18, ' ');
file >> cached;
file.close();
return ((memTotal - memFree) - (buffers + cached)) / 1024;
}
int main()
{
do{
// Everyday use:
printf("mem: %im\n", mem());
sleep(1);
// For benchmarking:
// mem();
// usleep(55);
}while(1);
return 0;
}
Компиляция с использованием:
[code] g ++ -Wall -O2 mem.cpp -o mem [/ code]
mem.c
/*
Compile using:
g++ -Wall -O2 mem.c -o mem
*/
#include<fstream>
#include<unistd.h> // Needed for 'usleep' func.
unsigned int mem()
{
unsigned int memTotal, memFree, buffers, cached;
FILE * const file = fopen( "/proc/meminfo", "r" );
fscanf(file, "%*19s %i %*2s %*19s %i %*2s %*19s %*i %*2s %*19s %i %*2s %*19s %i", &memTotal, &memFree, &buffers, &cached);
fclose(file);
return ((memTotal - memFree) - (buffers + cached)) / 1024;
}
int main()
{
do{
printf("mem: %im\n", mem());
sleep(1);
//For benchmarking:
//mem();
//usleep(55);
}while(1);
return 0;
}
Компиляция с использованием:
g ++ -Wall -O2 mem.c -o mem
* РЕДАКТИРОВАТЬ *
При попытке воссоздать мой код, который у меня изначально был с использованием позиций файла, я заставил его работать так, как просили, но код на самом деле МЕНЬШЕ (на 2%), чем оба кода выше:
mem3.c
/*
// -O3 seems to be .6% more efficient
g++ -Wall -O3 mem3.c -o mem3
cpu 47.7% @ 55 microseconds
*/
#include<fstream>
#include<unistd.h> // Needed for usleep func.
int mem()
{
unsigned long memTotal, memFree, buffers, cached;
FILE * file;
file = fopen("/proc/meminfo", "r");
fseek(file, 18, SEEK_SET);
fscanf(file, "%lu", &memTotal);
fseek(file, 22, SEEK_CUR);
fscanf(file, "%lu", &memFree);
fseek(file, 40, SEEK_CUR);
fscanf(file, "%lu", &buffers);
fseek(file, 22, SEEK_CUR);
fscanf(file, "%lu", &cached);
fclose (file);
return ((memTotal - memFree) - (buffers + cached)) / 1024;
}
int main()
{
do{
printf("mem: %im\n", mem());
sleep(1);
// For testing:
// mem();
// usleep(55);
}while(1);
return 0;
}
Нет хранения бесполезных данных. Никакой дополнительной проверки, но приведенный выше код работает медленнее ?? Очевидно, что я что-то не так делаю, и я как-то вызываю повышенную нагрузку.
Спасибо за чтение. Ищу предложения.
* РЕДАКТИРОВАТЬ 2 *
Мне удалось получить приличный прирост эффективности на 7% благодаря использованию пользовательской функции. Примечания в коде.
mem.c:
/*
// -O3 seems to give .6% increased efficiency
g++ -Wall -O3 mem.c -o mem
43.7% CPU usage @ usleep(55)
*/
#include<fstream>
#include<unistd.h> // Needed for 'usleep' func.
/* Function courtesy of: https://stackoverflow.com/questions/16826422/c-most-efficient-way-to-convert-string-to-int-faster-than-atoi. With a personal modification to allow for conversion of an int between strings. */
void naive(const char *p, unsigned int &x)
{
x = 0;
do{
// Nifty little trick with uint8_t... which I saw on stack! :D
if (uint8_t(*p - '0') < 10)
x = (x*10) + (*p - '0');
}while(*++p != '\0');
}
unsigned int mem()
{
unsigned int memTotal, memFree, buffers, cached;
FILE * file;
char str [30]; // Length of each file line
file = fopen ("/proc/meminfo" , "r");
/* Looking into finding a way to gather all the below info at once; likely, the 5 'fget' file calls are slowing things down. */
fgets(str, 30, file);
naive(str, memTotal);
fgets(str, 30, file);
naive(str, memFree);
fgets(str, 30, file);
fgets(str, 30, file);
naive(str, buffers);
fgets(str, 30 , file);
naive(str, cached);
fclose(file);
return ((memTotal - memFree) - (buffers + cached)) / 1024;
}
int main()
{
do{
// Everyday usage:
//printf("mem: %im\n", mem());
//sleep(1);
// For testing:
mem();
usleep(55);
}while(1);
return 0;
}