Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在巨大的日志文件中搜索数百个模式_C++_Partitioning - Fatal编程技术网

C++ 在巨大的日志文件中搜索数百个模式

C++ 在巨大的日志文件中搜索数百个模式,c++,partitioning,C++,Partitioning,我必须从Web服务器的htdocs目录中获取大量文件名,然后使用此文件名列表来搜索大量存档日志文件,以便最后访问这些文件 我计划用C++在C++中做这件事。我会先把最新的日志倒过来读,检查每一行中我得到的所有文件名 如果文件名匹配,我会从日志字符串中读取时间并保存它的最后一次访问。现在我不需要再寻找这个文件了,因为我只想知道最后一次访问 要搜索的文件名向量应该会迅速减少 我想知道如何用多线程最有效地处理此类问题 我是否对日志文件进行分区,让每个线程从内存中搜索日志的一部分,如果某个线程有匹配项,

我必须从Web服务器的htdocs目录中获取大量文件名,然后使用此文件名列表来搜索大量存档日志文件,以便最后访问这些文件

我计划用C++在C++中做这件事。我会先把最新的日志倒过来读,检查每一行中我得到的所有文件名

如果文件名匹配,我会从日志字符串中读取时间并保存它的最后一次访问。现在我不需要再寻找这个文件了,因为我只想知道最后一次访问

要搜索的文件名向量应该会迅速减少

我想知道如何用多线程最有效地处理此类问题


我是否对日志文件进行分区,让每个线程从内存中搜索日志的一部分,如果某个线程有匹配项,它会将该文件名从文件名向量中删除,还是有更有效的方法来执行此操作?

将日志文件解析为数据库表(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。

尝试使用mmap,这将为您节省大量的头发损失。我感觉很快,在某种奇怪的心情下回忆起我的mmap知识,所以我写了一个简单的东西让你开始。希望这有帮助

mmap的优点在于它可以轻松地与OpenMP并行。这也是防止I/O瓶颈的一个非常好的方法。让我先定义Logfile类,然后再讨论实现

这是头文件(logfile.h)

\ifndef\u日志文件_
#定义日志文件_
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用std::string;
类日志文件{
公众:
日志文件(字符串标题);
char*open();
无符号int get_size()常量;
字符串get_name()常量;
bool-close();
私人:
字符串名;
字符*开始;
无符号整数大小;
int文件描述符;
};
#恩迪夫
这是.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 file\n";
        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;

}
#包括
#包括“logfile.h”
使用名称空间std;
日志文件::日志文件(字符串名称){
此->名称=名称;
start=NULL;
尺寸=0;
文件描述符=-1;
}
char*Logfile::open(){
//获取文件大小
结构统计;
统计数据(标题c_str(),&st);
尺寸=标准尺寸;
//获取文件描述符
file_descriptor=open(title.c_str(),O_RDONLY);
if(文件描述符<0){

cerr好的,这已经是几天前的事了,但我花了一些时间编写代码,并在其他项目中使用SQLite

我仍然想比较DB方法和MMAP解决方案的性能

当然,如果您可以使用SQL查询来处理您解析的所有数据,这会为您节省大量的工作。但我真的不在乎工作量,因为我仍在学习很多,我从中学到的是:

这种MMAP方法——如果您正确实现的话——在性能上绝对优越。如果您实现“字数统计”示例,您会注意到它的速度令人难以置信,这可以看作是MapReduce算法的“hello world”

现在,如果您还想从SQL语言中获益,正确的方法是通过在线程之间共享查询的方式实现您自己的SQL包装器,该包装器也使用某种Map Reduce

您可以在线程之间通过ID共享对象,每个线程处理自己的DB连接,然后查询数据集中自己部分的对象

这将比仅仅以通常的方式将内容写入SQLite DB快得多

毕竟你可以说:

MMAP是处理字符串处理的最快方法
SQL为解析器应用程序提供了强大的功能,但如果您不实现用于处理SQL查询的包装器,它会降低速度

这可能是一个IO绑定操作,因此我认为线程在这里不会有任何帮助。如果您有Mathematica,您可以很快编写一些东西来完成此操作。不要您不认为将日志文件读入内存并将字符串拆分为4或8个线程以同时从内存中搜索它们会提高性能吗?这将是一种类似于Map-Reduce的方法,在这种方法中,您使用多个线程来处理内存映射数据,但您将读取和处理阶段分开数据。这样你就不必处理任何同步。这会非常快吗?是的。你需要为l.file和f.file添加一个索引。如果需要,你还可以进行进一步的数据操作。导入将是最慢的部分,但正如Joey所说,这将是IO绑定的。这看起来就像我所想的该做了。所以omp将在我将数据映射到内存后为我对循环进行parralellize。这节省了我大量的工作,也正是我想要的,非常感谢!!没问题,很高兴我能提供帮助!我只是想补充一点,您应该将size变量属性为firstprivate(size),而不是shared,以避免循环中出现数据争用情况。
#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 file\n";
        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;

}
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
}