在巨大的日志文件中搜索数百种模式
searching for hundreds of patterns in huge Logfiles
我必须从web服务器的htdocs目录中获得大量的文件名,然后使用这个文件名列表来搜索大量的存档日志文件,以便最后访问这些文件。
我计划用Boost在c++中做这件事。我会先取最新的日志,然后倒着读,检查每一行是否有我得到的所有文件名。
如果文件名匹配,我从Logstring读取时间并保存它的最后一次访问。现在我不需要再查找这个文件了,因为我只想知道最后一次访问。
要搜索的文件名向量应该会迅速减少。
我想知道如何用多线程最有效地处理这种问题。
我分区日志文件,让每个线程从内存中搜索日志的一部分,如果一个线程有一个匹配,它从文件名向量中删除这个文件名,或者有一个更有效的方法来做到这一点?
尝试使用mmap,它将节省你相当多的脱发。我觉得自己很匆忙,而且心情有些奇怪,所以我写了一个简单的东西让你开始。希望这对你有帮助!
mmap的美妙之处在于它可以很容易地与OpenMP并行。这也是防止I/O瓶颈的好方法。让我先定义Logfile类,然后再讨论实现。
头文件(logfile.h)
#ifndef _LOGFILE_H_
#define _LOGFILE_H_
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
using std::string;
class Logfile {
public:
Logfile(string title);
char* open();
unsigned int get_size() const;
string get_name() const;
bool close();
private:
string name;
char* start;
unsigned int size;
int file_descriptor;
};
#endif
这是。cpp文件。
#include <iostream>
#include "logfile.h"
using namespace std;
Logfile::Logfile(string name){
this->name = name;
start = NULL;
size = 0;
file_descriptor = -1;
}
char* Logfile::open(){
// get file size
struct stat st;
stat(title.c_str(), &st);
size = st.st_size;
// get file descriptor
file_descriptor = open(title.c_str(), O_RDONLY);
if(file_descriptor < 0){
cerr << "Error obtaining file descriptor for: " << title.c_str() << endl;
return NULL;
}
// memory map part
start = (char*) mmap(NULL, size, PROT_READ, MAP_SHARED, file_descriptor, 0);
if(start == NULL){
cerr << "Error memory-mapping the filen";
close(file_descriptor);
return NULL;
}
return start;
}
unsigned int Logfile::get_size() const {
return size;
}
string Logfile::get_title() const {
return title;
}
bool Logfile::close(){
if( start == NULL){
cerr << "Error closing file. Was closetext() called without a matching opentext() ?n";
return false;
}
// unmap memory and close file
bool ret = munmap(start, size) != -1 && close(file_descriptor) != -1;
start = NULL;
return ret;
}
现在,使用这段代码,您可以使用OpenMP工作共享这些日志文件的解析,即
Logfile lf ("yourfile");
char * log = lf.open();
int size = (int) lf.get_size();
#pragma omp parallel shared(log, size) private(i)
{
#pragma omp for
for (i = 0 ; i < size ; i++) {
// do your routine
}
#pragma omp critical
// some methods that combine the thread results
}
将日志文件解析为数据库表(SQLite ftw)。其中一个字段将是路径。
在另一个表中,添加您正在查找的文件。
现在它是派生表上的一个简单连接。像这样。
SELECT l.file, l.last_access FROM toFind f
LEFT JOIN (
SELECT file, max(last_access) as last_access from logs group by file
) as l ON f.file = l.file
toFind中的所有文件都将在那里,并且对于那些在日志中没有找到的文件将具有last_access NULL。
好吧,这是几天前的事了,但我花了一些时间写代码,并在其他项目中使用SQLite。
我仍然想在性能方面比较db方法和MMAP解决方案。
当然,如果你可以使用sql查询来处理你解析的所有数据,它可以节省你很多的工作。但我真的不关心工作量,因为我还在学习很多东西,我从中学到的是:
这个mmap方法——如果你正确地实现它——在性能上绝对是优越的。这是令人难以置信的快,如果你实现"单词计数"的例子,你会注意到,这可以看作是MapReduce算法的"hello world"。
现在,如果你想进一步从sql语言中获益,正确的方法是实现你自己的sql包装器,它也使用Map-Reduce的方式在线程之间共享查询。
你也许可以在线程之间通过ID共享对象,每个线程处理它自己的DB-Connection。然后,它在自己的数据集中查询对象。
这将比通常的方式写东西到SQLite DB要快得多。
毕竟你可以说:
MMAP是处理字符串处理的最快方式SQL为解析器应用程序提供了强大的功能,但如果不实现处理SQL查询的包装器,它会减慢速度
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 在这种情况下我应该使用哪种设计模式
- 使用哪种模式来执行新代码,只需添加基类的新子类?
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 是否有一种设计模式或面向对象的基本原则来处理这种共享资源的情况?
- 哪种设计模式仅出于代理目的而组成的对象与之相关
- 在我的情况下,多重继承是一种好的设计模式吗?
- 类型擦除和一种模板方法模式
- 一种在 Mac 上强制关闭模式 QFileDialog 的方法
- 一种奇怪的构造模式
- 是否有一种模式可以使用协议缓冲区而不针对LibProtobuf链接
- C 双重调度,出厂模式或一种从接收到的序列数据创建派生对象的方法
- 对于可以具有不同状态的结构,我应该使用哪种设计模式
- 寻找一种设计模式以应用于C++
- C++:模式:哪种模式适合特定的代码执行,具体取决于命令行参数
- 如何在C++中有效地比较两种模式
- 如何检查两种类型是否具有相同的位模式和类型
- C++中的两种不同的mixin模式.(混合蛋白?CRTP?)
- 是否有一种模式来描述哪个对象控制另一个对象的生命周期?
- 在巨大的日志文件中搜索数百种模式