繁体   English   中英

为什么锁定会降低此顺序文件解析器的速度?

[英]Why does locking slow down this sequential file parser?

我为图形文件格式编写了一个简单的阅读器和解析器。 问题是它非常慢。 以下是相关方法:

Graph METISGraphReader::read(std::string path) {
    METISParser parser(path);
    std::pair<int64_t, int64_t> header = parser.getHeader();
    int64_t n = header.first;
    int64_t m = header.second;

    Graph G(n);

    node u = 0;
    while (parser.hasNext()) {
        u += 1;
        std::vector<node> adjacencies = parser.getNext();
        for (node v : adjacencies) {
            if (! G.hasEdge(u, v)) { 
                G.insertEdge(u, v);
            }
        }
    }
    return G;
}

std::vector<node> METISParser::getNext() {
    std::string line;
    bool comment = false;
    do {
        comment = false;
        std::getline(this->graphFile, line);
        // check for comment line starting with '%'
        if (line[0] == '%') {
            comment = true;
            TRACE("comment line found");
        } else {
            return parseLine(line);
        }

    } while (comment);
}

static std::vector<node> parseLine(std::string line) {
    std::stringstream stream(line);
    std::string token;
    char delim = ' ';
    std::vector<node> adjacencies;

    // split string and push adjacent nodes
    while (std::getline(stream, token, delim)) {
        node v = atoi(token.c_str());
        adjacencies.push_back(v);
    }
    return adjacencies;
}

为了诊断它为什么这么慢,我在一个分析器(Apple Instruments)中运行它。 结果令人惊讶:由于锁定开销,它很慢。 该程序将超过90%的时间花在pthread_mutex_lock_pthread_cond_wait

仪器

我不知道锁定开销来自哪里,但我需要摆脱它。 你能建议下一步吗?

编辑:查看为_pthread_con_wait扩展的调用堆栈。 通过查看这个,我无法弄清楚锁定开销的来源:

在此输入图像描述

展开_pthread_cond_wait和pthread_mutex_lock调用上的调用堆栈,以找出调用锁定调用的位置。

作为一个猜测,我会说它在你所做的所有不必要的堆分配中。 堆是一个线程安全的资源,在这个平台上,线程安全可以通过互斥锁提供。

istream读取数据的所有函数都将锁定mutex,streambuf读取数据并解锁mutex 要消除这种开销,请直接从streambuf而不是istream读取文件,不要使用stringstream来解析数据。

这是一个使用streambuf而不是istreamgetline版本

bool fastGetline(streambuf* sb, std::string& t)
{
    t.clear();
    for(;;) {
        int c = sb->sbumpc();
        switch (c) {
        case '\n':
            return true;
        case '\r':
            if(sb->sgetc() == '\n')
                sb->sbumpc();
            return true;
        case EOF:
            return !t.empty();
        default:
            t += (char)c;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM