Skip to content

Commit 4279e65

Browse files
atetubouzzzeek
authored andcommitted
optimize some code paths
Optimized some codepaths within the lexer/Python code generation process, improving performance for generation of templates prior to their being cached. Pull request courtesy Takuto Ikuta. This shows around 10% performance improvement in our use case (https://crbug.com/1214033#c32). Closes: #361 Pull-request: #361 Pull-request-sha: bcdee5c Change-Id: If647f77a52d5745019dcc46f82fd7a928f990757
1 parent 0d68060 commit 4279e65

3 files changed

Lines changed: 28 additions & 12 deletions

File tree

doc/build/unreleased/361.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.. change::
2+
:tags: performance
3+
:tickets: 361
4+
5+
Optimized some codepaths within the lexer/Python code generation process,
6+
improving performance for generation of templates prior to their being
7+
cached. Pull request courtesy Takuto Ikuta.

mako/lexer.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,11 @@ def match_reg(self, reg):
7474
(start, end) = match.span()
7575
self.match_position = end + 1 if end == start else end
7676
self.matched_lineno = self.lineno
77-
lines = re.findall(r"\n", self.text[mp : self.match_position])
7877
cp = mp - 1
79-
while cp >= 0 and cp < self.textlength and self.text[cp] != "\n":
80-
cp -= 1
78+
if cp >= 0 and cp < self.textlength:
79+
cp = self.text[: cp + 1].rfind("\n")
8180
self.matched_charpos = mp - cp
82-
self.lineno += len(lines)
81+
self.lineno += self.text[mp : self.match_position].count("\n")
8382
return match
8483

8584
def parse_until_text(self, watch_nesting, *text):

mako/pygen.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ def __init__(self, stream):
4343
# source lines
4444
self.source_map = {}
4545

46+
self._re_space_comment = re.compile(r"^\s*#")
47+
self._re_space = re.compile(r"^\s*$")
48+
self._re_indent = re.compile(r":[ \t]*(?:#.*)?$")
49+
self._re_compound = re.compile(r"^\s*(if|try|elif|while|for|with)")
50+
self._re_indent_keyword = re.compile(
51+
r"^\s*(def|class|else|elif|except|finally)"
52+
)
53+
self._re_unindentor = re.compile(r"^\s*(else|elif|except|finally).*\:")
54+
4655
def _update_lineno(self, num):
4756
self.lineno += num
4857

@@ -86,8 +95,8 @@ def writeline(self, line):
8695

8796
if (
8897
line is None
89-
or re.match(r"^\s*#", line)
90-
or re.match(r"^\s*$", line)
98+
or self._re_space_comment.match(line)
99+
or self._re_space.match(line)
91100
):
92101
hastext = False
93102
else:
@@ -121,12 +130,12 @@ def writeline(self, line):
121130
# note that a line can both decrase (before printing) and
122131
# then increase (after printing) the indentation level.
123132

124-
if re.search(r":[ \t]*(?:#.*)?$", line):
133+
if self._re_indent.search(line):
125134
# increment indentation count, and also
126135
# keep track of what the keyword was that indented us,
127136
# if it is a python compound statement keyword
128137
# where we might have to look for an "unindent" keyword
129-
match = re.match(r"^\s*(if|try|elif|while|for|with)", line)
138+
match = self._re_compound.match(line)
130139
if match:
131140
# its a "compound" keyword, so we will check for "unindentors"
132141
indentor = match.group(1)
@@ -137,9 +146,7 @@ def writeline(self, line):
137146
# its not a "compound" keyword. but lets also
138147
# test for valid Python keywords that might be indenting us,
139148
# else assume its a non-indenting line
140-
m2 = re.match(
141-
r"^\s*(def|class|else|elif|except|finally)", line
142-
)
149+
m2 = self._re_indent_keyword.match(line)
143150
if m2:
144151
self.indent += 1
145152
self.indent_detail.append(indentor)
@@ -167,7 +174,7 @@ def _is_unindentor(self, line):
167174

168175
# if the current line doesnt have one of the "unindentor" keywords,
169176
# return False
170-
match = re.match(r"^\s*(else|elif|except|finally).*\:", line)
177+
match = self._re_unindentor.match(line)
171178
# if True, whitespace matches up, we have a compound indentor,
172179
# and this line has an unindentor, this
173180
# is probably good enough
@@ -193,6 +200,9 @@ def _indent_line(self, line, stripspace=""):
193200
194201
stripspace is a string of space that will be truncated from the
195202
start of the line before indenting."""
203+
if stripspace == "":
204+
# Fast path optimization.
205+
return self.indentstring * self.indent + line
196206

197207
return re.sub(
198208
r"^%s" % stripspace, self.indentstring * self.indent, line

0 commit comments

Comments
 (0)