Поскольку файловый поток буферизируется, то врядли есть смысл толкать данные в строку, а уже после осуществлять ее анализ. Вообщем, попробуйте более экономичный вариант:
У меня есть файл отчётов (~5 МБ), это простой текстовый файл, в котором содежжаться отчёты. Отчёты начинаются символом, с кодом 2 и заканчиваются символом с кодом 3. Написал простенький примерчик как подсчитать кол-во отчётов в этом файле:
Здравствуйте, Аноним, Вы писали:
А>Так вот вопрос, можно ли как-нить ускорить процесс подсчёта, а то мой пример работает примерно сек 15-20?
Я думаю, более эффективный способ — отображаемые на память файлы. Под виндой ищите информацию о CreateFileMapping/MapViewOfFile, под linux — mmap.
Re[2]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
24.07.05 09:36
Оценка:
Здравствуйте, Сергей, Вы писали:
С>Здравствуйте, Аноним, Вы писали:
А>>Так вот вопрос, можно ли как-нить ускорить процесс подсчёта, а то мой пример работает примерно сек 15-20?
С>Я думаю, более эффективный способ — отображаемые на память файлы. Под виндой ищите информацию о CreateFileMapping/MapViewOfFile, под linux — mmap.
Попробовал, но сразу встал в ступор. Как загнать из памяти данные в мой вектор строк?
int FirstWay(std::string FileName)
{
int nResult = -1;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMap = NULL;
PVOID pvFile = NULL;
__try
{
hFile = CreateFile(FileName.c_str(), GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
std::cout << "File could not be opened." << std::endl;
__leave;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize + sizeof(char), NULL);
if(!hFileMap)
{
std::cout << "File map could not be opened." << std::endl;
__leave;
}
pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
if(!pvFile)
{
std::cout << "Could not map view of file." << std::endl;
__leave;
}
// !!!! Как загнать данные из pvFile в мой вектор????
std::vector<std::string> MyVector;
}
__finally
{
if(pvFile)
{
UnmapViewOfFile(pvFile);
pvFile = NULL;
}
if(hFileMap)
{
CloseHandle(hFileMap);
hFileMap = NULL;
}
if(hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = NULL;
}
}
return nResult;
}
Здравствуйте, <Аноним>, Вы писали:
С>>Я думаю, более эффективный способ — отображаемые на память файлы. А>Попробовал, но сразу встал в ступор. Как загнать из памяти данные в мой вектор строк?
А зачем считывать данные из файла в вектор строк? Файл же проецируется в память. С памятью и работай. Можно написать свой класс, который будет при открытии сканировать файл и запоминать указатели на начала строк и длины строк. Для работы с содержимым файла (толко для чтения) можно предусмотреть функции типа
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, <Аноним>, Вы писали:
С>>>Я думаю, более эффективный способ — отображаемые на память файлы. А>>Попробовал, но сразу встал в ступор. Как загнать из памяти данные в мой вектор строк?
AD>А зачем считывать данные из файла в вектор строк? Файл же проецируется в память. С памятью и работай. Можно написать свой класс, который будет при открытии сканировать файл и запоминать указатели на начала строк и длины строк. Для работы с содержимым файла (толко для чтения) можно предусмотреть функции типа AD>
Хорошо а как тогда эти методы реализовать, дело в том что я еще плохо разбираюсь в стл, а писать нужно с использованием оной библиотеки. Может каккой метод есть у std::string или алгоритм какой?
On Sun, 24 Jul 2005 12:30:15 +0400, wrote:
> У меня есть файл отчётов (~5 МБ), это простой текстовый файл, в котором содежжаться отчёты. Отчёты начинаются символом, с кодом 2 и заканчиваются символом с кодом 3.
Если файл текстовый, то почему бы не представить отчет одной строкой?
Тогда в твоем распоряжении были бы все стандартные power tools, ориентированные на работу с текстовыми файлами: wc, grep, awk, ...
Небольшое дополнение — имеет смысл открывать файла как бинарный, поскольку представляют интерес только концевые маркеры — это еще больше повысит производительность, поскольку не будет тратится время на преобразование вида 0x0d0a -> '\n':
На файле 50 (!) МБ работает секунды 3 (Visual 7.1, release, Athlon 1700+). Согласен, что лучше открывать в бинарной моде, хотя разница оказалась невелика. Но очень советую перейти к проецированию в память, тут уже 50 МБ проскакивают незаметно, 250 за пару секунд, а дальше уже, видимо, тормозит, когда файл перестает влезать в оперативку...
Re[2]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
25.07.05 07:52
Оценка:
Здравствуйте, alex-t, Вы писали:
AT>На файле 50 (!) МБ работает секунды 3 (Visual 7.1, release, Athlon 1700+). Согласен, что лучше открывать в бинарной моде, хотя разница оказалась невелика. Но очень советую перейти к проецированию в память, тут уже 50 МБ проскакивают незаметно, 250 за пару секунд, а дальше уже, видимо, тормозит, когда файл перестает влезать в оперативку...
Да действительно быстрее. Только снова появились вопросы.
1. Можно ли переделать этот цикл, так чтобы он работал со строками?
Дело в том что мне нужно читать файл, потом выделять от туда один отчёт за другим и парсить их с помошью регспеков. Т.е. я хочу делать так. Если что-нить неправильно подправьте.
1. Открыть файл.
2. Считать первый отчёт в вектор строк и отправить в парсер.
3. Считать следующий отчёт в вектор строк и отправить в парсер.
и т.д...
Получилось нечно похожее на:
int ReadRepFile(std::string FileName)
{
std::ifstream iFile(FileName.c_str());
std::string str;
std::vector<std::string> MyVector;
long nRepCount = 0; // Кол-во отчётовlong nBadRepCount = 0; // Кол-во "бытых" отчётовbool bInRep = false;
while(std::getline(iFile, str))
{
if(str[0] == REP_BEGIN)
{
// Отчёт "битый", т.е. нет конца отчета (REP_END)
// следовательно, парсить мы его не будемif(bInRep)
{
++nBadRepCount;
MyVector.clear();
}
// Находимся в процессе чтения отчёта
bInRep = true;
continue;
}
// Дошли до конца отчёта, отправляем вектор строк с отчётом в парсерif((str[0] == REP_END))
{
if(bInRep)
{
bInRep = false;
++nRepCount;
ParseRep(MyVector);
MyVector.clear();
}
else// Опять "битый" отчет - нет REP_BEGIN
{
++nBadRepCount;
}
}
if(bInRep)
{
// Добавляем строку отчёта в вектор
MyVector.push_back(str);
}
}
iFile.close();
std::cout << "Reports count: " << nRepCount << std::endl;
std::cout << "Bad reports count: " << nBadRepCount << std::endl;
return nRepCount;
}
Как это оптимизировать по скорости?
Re[3]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
25.07.05 08:39
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Как это оптимизировать по скорости?
С std::мишурой оптимизировать особо не получится
Re[4]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
25.07.05 10:09
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Как это оптимизировать по скорости?
А>С std::мишурой оптимизировать особо не получится
Ну почему же тогда цикл:
работает в 2 раза быстрее чем мой, просто я не знаю как этот цикл заточить под строки?
Re[5]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
25.07.05 10:12
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Аноним, Вы писали:
А>>>Как это оптимизировать по скорости?
А>>С std::мишурой оптимизировать особо не получится А>Ну почему же тогда цикл:
А>
А>работает в 2 раза быстрее чем мой, просто я не знаю как этот цикл заточить под строки?
Потому и быстрее, что строк там нет. А если не будет stream'ов, так ещё в 4 раза быстрее заработает.
Re[6]: Можно ли ускорить подсчет?
От:
Аноним
Дата:
25.07.05 11:43
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Потому и быстрее, что строк там нет. А если не будет stream'ов, так ещё в 4 раза быстрее заработает.
Что ж печально, ну ладно...