我为图形文件格式编写了一个简单的阅读器和解析器。问题是它非常慢。以下是相关方法:
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
展开的调用堆栈。我不能通过查看这个来找出锁定开销的来源:
答案 0 :(得分:2)
在_pthread_cond_wait和pthread_mutex_lock调用上展开调用堆栈,以找出调用锁定调用的位置。
作为一种猜测,我会说它在你正在进行的所有不必要的堆分配中。堆是一个线程安全的资源,在这个平台上,线程安全可以通过互斥锁提供。
答案 1 :(得分:1)
所有从istream
读取数据的函数都会锁定mutex,
的{{1}}个读取数据并解锁streambuf
。要消除这种开销,请直接从mutex
而不是streambuf
读取文件,不要使用istream
来解析数据。
以下是使用stringstream
代替getline
streambuf
版本
istream