Я пытаюсь извлечь данные long int только из / proc / meminfo. Образец файла ниже. Я могу это сделать, но давно известная мантра Linux: делай одно и делай это хорошо. Меня раздражает, что я делаю это не так эффективно, как мог бы.
Я не хочу читать / собирать / хранить данные char до и после длинных int. Я не хочу, чтобы программа проверяла символы, чтобы убедиться, что они такие-то или нет. Я хочу, чтобы данные long int обрабатывались и сохранялись как переменная, и я хочу, чтобы это выполнялось через позиции файлов, которые просто пропускают все бесполезные данные char.
Кроме того, я хочу, чтобы данные были захвачены как long int и сохранены как long int. Есть несколько программ, делающих все, что я сказал, но они начинают с хранения информации в виде строки символов. Эта строка должна быть преобразована обратно, что сводит на нет большую часть преимуществ.
Я хотел бы сделать это, переместив положение файла прямо перед длинным int, а затем сохранив его, но я не понял, как это сделать эффективно. Единственный способ заставить это работать - всегда начинать с начала файла и использовать все большие и большие позиции файла для перехода к каждому последующему длинному int. Результатом было очень медленное выполнение - намного медленнее, чем мой код ниже (примерно на 30% медленнее). Возможно, программе пришлось перезапустить с самого начала и просмотреть весь файл, чтобы найти его позицию?
Я хочу перейти к 766744, захватить его, сохранить, а затем перейти (начиная с этой новой текущей позиции) до 191680, захватить его, сохранить и перейти к 468276 ... Вы уловили идею.
Позиция файла перескакивает (кроме самого первого перехода к 766744, который составляет 18 символов), начиная с конца длинного int, проходя через '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;
}
std::ifstream
, который не имеет репутации эффективного. Скорее, вы будете использовать функции POSIXopen()
,lseek()
иread()
, а затем самостоятельно анализировать целочисленные значения вместо того, чтобы использовать для этого библиотеку C ++, которая также сжигает невероятное количество электронов, принимая во внимание такие вещи, как текущая локаль. , о котором вы действительно не заботитесь. Собственно, проlseek()
забудь. Одинread()
, чтобы все проглотить, потом разобрать в памяти. - person Sam Varshavchik   schedule 17.03.2019