Skip to content

Commit c8251af

Browse files
Merge pull request #839 from discopop-project/perf/patch_generator
Perf/patch generator
2 parents ddc12f6 + 95a9c35 commit c8251af

1 file changed

Lines changed: 18 additions & 9 deletions

File tree

library/discopop_library/CodeGenerator/classes/ContentBuffer.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,13 @@ def add_pragma(
103103
if pragma.file_id != self.file_id:
104104
return True # incorrect target file, ignore the pragma
105105

106-
# create backup of ContentBuffer
107-
backup_lines = copy.deepcopy(self.lines)
106+
# Create a backup of the ContentBuffer so a failed insertion can be rolled back.
107+
# Both rollback paths below require a compilation check to have run: child pragmas are always
108+
# added with skip_compilation_check=True and can therefore never report failure, so a call
109+
# that skips the check cannot return False either. Deep-copying every Line of the file on
110+
# every single insertion dominated the patch generator (measured on LULESH with task
111+
# patterns: 22.9s of a 32.0s run), so the backup is only taken when it can be consumed.
112+
backup_lines = copy.deepcopy(self.lines) if not skip_compilation_check else None
108113
backup_max_line_num = self.max_line_num
109114
backup_file_id = self.file_id
110115
backup_next_free_region_id = self.next_free_region_id
@@ -119,7 +124,7 @@ def add_pragma(
119124
pragma_line.content = ""
120125

121126
pragma_line.content += pragma.pragma_str
122-
pragma_line.belongs_to_regions = copy.deepcopy(parent_regions)
127+
pragma_line.belongs_to_regions = list(parent_regions)
123128
# create new region if necessary
124129
if len(pragma.children) > 0:
125130
region_id = self.__get_next_free_region_id()
@@ -142,12 +147,14 @@ def add_pragma(
142147
pragma.start_line if pragma.pragma_position == PragmaPosition.BEFORE_START else pragma.start_line + 1
143148
)
144149
tmp_end_line = pragma.end_line + 1
145-
for line_num in range(tmp_start_line, tmp_end_line):
146-
for line in self.lines:
147-
if line.line_num == line_num:
148-
line.belongs_to_regions += [
149-
n for n in pragma_line.belongs_to_regions if n not in line.belongs_to_regions
150-
]
150+
# A single pass over self.lines, instead of rescanning all of them once per line number in
151+
# the pragma's span. The nested variant was O(span * |lines|) - 33.8M iterations, ~7.4s, on
152+
# LULESH with task patterns, whose spans average 251 lines. Lines inserted for pragmas carry
153+
# line_num=None and were never matched by the previous equality check either, hence the guard.
154+
new_regions = pragma_line.belongs_to_regions
155+
for line in self.lines:
156+
if line.line_num is not None and tmp_start_line <= line.line_num < tmp_end_line:
157+
line.belongs_to_regions += [n for n in new_regions if n not in line.belongs_to_regions]
151158

152159
# append children to lines (mark as contained in region)
153160
for child_pragma in pragma.children:
@@ -166,6 +173,7 @@ def add_pragma(
166173

167174
if not successful:
168175
print(self.compile_result_buffer)
176+
assert backup_lines is not None, "rollback requested, but no backup was taken"
169177
self.lines = backup_lines
170178
self.next_free_region_id = backup_next_free_region_id
171179
self.file_id = backup_file_id
@@ -241,6 +249,7 @@ def add_pragma(
241249

242250
# if not, reset ContentBuffer to the backup and return False
243251
if not compilation_successful:
252+
assert backup_lines is not None, "rollback requested, but no backup was taken"
244253
self.lines = backup_lines
245254
self.next_free_region_id = backup_next_free_region_id
246255
self.file_id = backup_file_id

0 commit comments

Comments
 (0)