Skip to content

Commit e661101

Browse files
committed
Improving change list parsing speed
1 parent 7fa0eb2 commit e661101

1 file changed

Lines changed: 102 additions & 34 deletions

File tree

mt-kahypar/dynamic/dynamic_io.h

Lines changed: 102 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <charconv>
34
#include <mt-kahypar/io/hypergraph_factory.h>
45
#include <filesystem>
56
#include <fstream>
@@ -49,15 +50,31 @@ namespace mt_kahypar::dyn {
4950
std::cout.flush();
5051
}
5152

52-
inline std::vector<HypernodeID> parseIDs(const std::string& line) {
53-
std::vector<HypernodeID> ids;
54-
std::stringstream ss(line);
55-
int id;
56-
while (ss >> id) {
57-
ids.push_back(id);
58-
}
59-
return ids;
53+
inline std::vector<HypernodeID> parseIDs(const std::string& line) {
54+
std::vector<HypernodeID> ids;
55+
ids.reserve(2);
56+
57+
const char* p = line.data();
58+
const char* end = p + line.size();
59+
60+
while (p < end) {
61+
// skip whitespace
62+
while (p < end && *p <= ' ') ++p;
63+
if (p >= end) break;
64+
65+
HypernodeID id;
66+
auto [np, ec] = std::from_chars(p, end, id);
67+
if (ec == std::errc()) {
68+
ids.push_back(id);
69+
p = np;
70+
} else {
71+
// skip malformed token
72+
while (p < end && *p > ' ') ++p;
6073
}
74+
}
75+
76+
return ids;
77+
}
6178

6279
inline std::vector<PinChange> parsePins(const std::string& line) {
6380
std::vector<PinChange> pins;
@@ -78,6 +95,47 @@ namespace mt_kahypar::dyn {
7895
return pins;
7996
}
8097

98+
inline std::vector<PinChange> parsePins_fast(const std::string& line) {
99+
std::vector<PinChange> pins;
100+
pins.reserve(16);
101+
102+
const char* p = line.data();
103+
const char* end = p + line.size();
104+
105+
while (p < end) {
106+
// Skip whitespace
107+
while (p < end && *p <= ' ') ++p;
108+
if (p >= end) break;
109+
110+
if (*p != '(') {
111+
// Malformed token, skip
112+
while (p < end && *p > ' ') ++p;
113+
continue;
114+
}
115+
++p; // skip '('
116+
117+
HypernodeID node;
118+
auto [p1, ec1] = std::from_chars(p, end, node);
119+
if (ec1 != std::errc()) break;
120+
p = p1;
121+
122+
if (p >= end || *p != ',') break;
123+
++p; // skip ','
124+
125+
HyperedgeID edge;
126+
auto [p2, ec2] = std::from_chars(p, end, edge);
127+
if (ec2 != std::errc()) break;
128+
p = p2;
129+
130+
if (p >= end || *p != ')') break;
131+
++p; // skip ')'
132+
133+
pins.push_back({node, edge});
134+
}
135+
136+
return pins;
137+
}
138+
81139
inline std::string getNextNonCommentLine(std::ifstream& file) {
82140
std::string line;
83141
while (std::getline(file, line)) {
@@ -98,7 +156,6 @@ namespace mt_kahypar::dyn {
98156
// removed_edges_id1 removed_edges_id2, ...
99157
// (removed_pins1.hypernode,removed_pins1.hyperedge) (removed_pins2.hypernode,removed_pins2.hyperedge), ...
100158
inline std::vector<Change> parseChanges(const std::string& filename) {
101-
std::vector<Change> changes;
102159
std::ifstream file(filename);
103160
if (!file.is_open()) {
104161
throw std::runtime_error("Could not open file: " + filename);
@@ -110,35 +167,46 @@ namespace mt_kahypar::dyn {
110167
size_t num_changes = std::stoi(line);
111168
// file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Move to the next line
112169

113-
for (size_t i = 0; i < num_changes; ++i) {
114-
Change change;
115-
116-
// Parse added nodes
117-
line = getNextNonCommentLine(file);
118-
change.added_nodes = parseIDs(line);
119-
120-
// Parse added edges
121-
line = getNextNonCommentLine(file);
122-
change.added_edges = parseIDs(line);
123-
124-
// Parse added pins
125-
line = getNextNonCommentLine(file);
126-
change.added_pins = parsePins(line);
170+
std::vector<Change> changes;
171+
changes.reserve(num_changes);
172+
for (size_t i = 0; i < num_changes; ++i) { // Parse added nodes
127173

128-
// Parse removed nodes
129-
line = getNextNonCommentLine(file);
130-
change.removed_nodes = parseIDs(line);
174+
// line = getNextNonCommentLine(file);
175+
// change.added_nodes = parseIDs(line);
176+
//
177+
// // Parse added edges
178+
// line = getNextNonCommentLine(file);
179+
// change.added_edges = parseIDs(line);
180+
//
181+
// // Parse added pins
182+
// line = getNextNonCommentLine(file);
183+
// change.added_pins = parsePins_fast(line);
184+
//
185+
// // Parse removed nodes
186+
// line = getNextNonCommentLine(file);
187+
// change.removed_nodes = parseIDs(line);
188+
//
189+
// // Parse removed edges
190+
// line = getNextNonCommentLine(file);
191+
// change.removed_edges = parseIDs(line);
192+
//
193+
// // Parse removed pins
194+
// line = getNextNonCommentLine(file);
195+
// change.removed_pins = parsePins_fast(line);
131196

132-
// Parse removed edges
133-
line = getNextNonCommentLine(file);
134-
change.removed_edges = parseIDs(line);
197+
changes.emplace_back(Change{
198+
parseIDs(getNextNonCommentLine(file)), // added nodes
199+
parseIDs(getNextNonCommentLine(file)), // added edges
200+
parsePins_fast(getNextNonCommentLine(file)), // added pins
201+
parseIDs(getNextNonCommentLine(file)), // removed nodes
202+
parseIDs(getNextNonCommentLine(file)), // removed edges
203+
parsePins_fast(getNextNonCommentLine(file)) // removed pins
204+
});
135205

136-
// Parse removed pins
137-
line = getNextNonCommentLine(file);
138-
change.removed_pins = parsePins(line);
206+
if (i % 1000000 == 0) {
207+
std::cout << "Parsed " << i << "/" << num_changes << " changes\r" << std::flush;
208+
}
139209

140-
// Add the parsed change to the list
141-
changes.push_back(change);
142210
}
143211

144212
file.close();

0 commit comments

Comments
 (0)