Skip to content

Commit 449417f

Browse files
authored
A few tiny changes to slightly improve performance (#450)
* Cache `ctx.current_ns` in the Analyzer and Generator whenever possible * Do not collect comprehensions into intermediate lists when they will just be put into some other iterable later * Use `str.translate` for munging, rather than manual translation Nothing here moves the needle dramatically, but every little bit that shaves a few milliseconds off of the startup time helps.
1 parent 2ebbf3b commit 449417f

File tree

5 files changed

+31
-33
lines changed

5 files changed

+31
-33
lines changed

src/basilisp/lang/compiler/analyzer.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -648,18 +648,21 @@ def _def_ast( # pylint: disable=too-many-branches,too-many-locals
648648
raise AnalyzerException("def docstring must be a string", form=doc)
649649
children = vec.v(INIT)
650650

651+
# Cache the current namespace
652+
current_ns = ctx.current_ns
653+
651654
# Attach metadata relevant for the current process below.
652-
def_loc = _loc(form)
655+
def_loc = _loc(form) or (None, None)
653656
def_node_env = ctx.get_node_env()
654657
def_meta = _clean_meta(
655658
name.meta.update(
656659
lmap.map(
657660
{
658-
COL_KW: def_loc[1] if def_loc is not None else None,
661+
COL_KW: def_loc[1],
659662
FILE_KW: def_node_env.file,
660-
LINE_KW: def_loc[0] if def_loc is not None else None,
663+
LINE_KW: def_loc[0],
661664
NAME_KW: name,
662-
NS_KW: ctx.current_ns,
665+
NS_KW: current_ns,
663666
}
664667
)
665668
)
@@ -688,7 +691,7 @@ def _def_ast( # pylint: disable=too-many-branches,too-many-locals
688691
# its meta may contain values which fail to compile.
689692
bare_name = sym.symbol(name.name)
690693

691-
ns_sym = sym.symbol(ctx.current_ns.name)
694+
ns_sym = sym.symbol(current_ns.name)
692695
var = Var.intern_unbound(
693696
ns_sym,
694697
bare_name,
@@ -729,7 +732,7 @@ def _def_ast( # pylint: disable=too-many-branches,too-many-locals
729732
sym.symbol("Namespace", "basilisp.lang.runtime"),
730733
sym.symbol("get"),
731734
),
732-
llist.l(SpecialForm.QUOTE, sym.symbol(ctx.current_ns.name)),
735+
llist.l(SpecialForm.QUOTE, sym.symbol(current_ns.name)),
733736
),
734737
}
735738
),
@@ -1448,7 +1451,7 @@ def _fn_ast( # pylint: disable=too-many-branches
14481451
fixed_arities.add(method.fixed_arity)
14491452

14501453
if fixed_arity_for_variadic is not None and any(
1451-
[fixed_arity_for_variadic < arity for arity in fixed_arities]
1454+
fixed_arity_for_variadic < arity for arity in fixed_arities
14521455
):
14531456
raise AnalyzerException(
14541457
"variadic arity may not have fewer fixed arity arguments than any other arities",
@@ -2016,7 +2019,7 @@ def _try_ast( # pylint: disable=too-many-branches
20162019
try_exprs.append(lisp_node)
20172020

20182021
assert all(
2019-
[isinstance(node, Catch) for node in catches]
2022+
isinstance(node, Catch) for node in catches
20202023
), "All catch statements must be catch ops"
20212024

20222025
*try_statements, try_ret = try_exprs
@@ -2242,8 +2245,9 @@ def __resolve_namespaced_symbol( # pylint: disable=too-many-branches
22422245
"""Resolve a namespaced symbol into a Python name or Basilisp Var."""
22432246
assert form.ns is not None
22442247

2245-
if form.ns == ctx.current_ns.name:
2246-
v = ctx.current_ns.find(sym.symbol(form.name))
2248+
current_ns = ctx.current_ns
2249+
if form.ns == current_ns.name:
2250+
v = current_ns.find(sym.symbol(form.name))
22472251
if v is not None:
22482252
return VarRef(form=form, var=v, env=ctx.get_node_env())
22492253
elif form.ns == _BUILTINS_NS:
@@ -2262,7 +2266,7 @@ def __resolve_namespaced_symbol( # pylint: disable=too-many-branches
22622266
"symbol names may not contain the '.' operator", form=form
22632267
)
22642268

2265-
resolved = __resolve_namespaced_symbol_in_ns(ctx, ctx.current_ns, form)
2269+
resolved = __resolve_namespaced_symbol_in_ns(ctx, current_ns, form)
22662270
if resolved is not None:
22672271
return resolved
22682272
elif ctx.current_macro_ns is not None:
@@ -2290,7 +2294,8 @@ def __resolve_bare_symbol(
22902294
assert form.ns is None
22912295

22922296
# Look up the symbol in the namespace mapping of the current namespace.
2293-
v = ctx.current_ns.find(form)
2297+
current_ns = ctx.current_ns
2298+
v = current_ns.find(form)
22942299
if v is not None:
22952300
return VarRef(form=form, var=v, env=ctx.get_node_env())
22962301

@@ -2317,7 +2322,7 @@ def __resolve_bare_symbol(
23172322
if ctx.should_allow_unresolved_symbols:
23182323
return _const_node(ctx, form)
23192324

2320-
assert munged not in vars(ctx.current_ns.module)
2325+
assert munged not in vars(current_ns.module)
23212326
raise AnalyzerException(
23222327
f"unable to resolve symbol '{form}' in this context", form=form
23232328
)

src/basilisp/lang/compiler/generator.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,12 @@ def __should_warn_on_redef(
593593
no_warn_on_redef = def_meta.val_at(SYM_NO_WARN_ON_REDEF_META_KEY, False)
594594
if no_warn_on_redef:
595595
return False
596-
elif safe_name in ctx.current_ns.module.__dict__:
596+
597+
current_ns = ctx.current_ns
598+
if safe_name in current_ns.module.__dict__:
597599
return True
598-
elif defsym in ctx.current_ns.interns:
599-
var = ctx.current_ns.find(defsym)
600+
elif defsym in current_ns.interns:
601+
var = current_ns.find(defsym)
600602
assert var is not None, f"Var {defsym} cannot be none here"
601603

602604
if var.meta is not None and var.meta.val_at(SYM_REDEF_META_KEY):

src/basilisp/lang/compiler/nodes.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def fix_missing_locations(
197197
loc = (self.env.line, self.env.col)
198198

199199
assert loc is not None and all(
200-
[e is not None for e in loc]
200+
e is not None for e in loc
201201
), "Must specify location information"
202202

203203
new_attrs: MutableMapping[str, Union[NodeEnv, Node, Iterable[Node]]] = {
@@ -210,10 +210,9 @@ def fix_missing_locations(
210210
if child_attr.endswith("s"):
211211
iter_child: Iterable[Node] = getattr(self, child_attr)
212212
assert iter_child is not None, "Listed child must not be none"
213-
new_children = []
214-
for item in iter_child:
215-
new_children.append(item.fix_missing_locations(start_loc))
216-
new_attrs[child_attr] = vec.vector(new_children)
213+
new_attrs[child_attr] = vec.vector(
214+
item.fix_missing_locations(start_loc) for item in iter_child
215+
)
217216
else:
218217
child: Node = getattr(self, child_attr)
219218
assert child is not None, "Listed child must not be none"

src/basilisp/lang/util.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@
2525
"&": "__AMP__",
2626
"$": "__DOLLAR__",
2727
}
28+
_MUNGE_TRANSLATE_TABLE = str.maketrans(_MUNGE_REPLACEMENTS)
2829

2930

3031
def count(seq: Iterable) -> int:
31-
return sum([1 for _ in seq])
32+
return sum(1 for _ in seq)
3233

3334

3435
def munge(s: str, allow_builtins: bool = False) -> str:
3536
"""Replace characters which are not valid in Python symbols
3637
with valid replacement strings."""
37-
new_str = []
38-
for c in s:
39-
new_str.append(_MUNGE_REPLACEMENTS.get(c, c))
40-
41-
new_s = "".join(new_str)
38+
new_s = s.translate(_MUNGE_TRANSLATE_TABLE)
4239

4340
if keyword.iskeyword(new_s):
4441
return f"{new_s}_"

tox.ini

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
envlist = py36,py37,py38,pypy3,coverage,mypy,format,lint,safety
33

44
[testenv]
5-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
5+
parallel_show_output = {env:TOX_SHOW_OUTPUT:true}
66
setenv =
77
BASILISP_DO_NOT_CACHE_NAMESPACES = true
88
deps =
@@ -17,7 +17,6 @@ commands =
1717
{posargs}
1818

1919
[testenv:coverage]
20-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
2120
depends = py36, py37, py38
2221
deps =
2322
coveralls
@@ -54,25 +53,21 @@ exclude_lines =
5453
if __name__ == .__main__.:
5554

5655
[testenv:format]
57-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
5856
deps = black
5957
commands =
6058
black --check .
6159

6260
[testenv:mypy]
63-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
6461
deps = mypy
6562
commands =
6663
mypy --config-file={toxinidir}/mypy.ini src/basilisp
6764

6865
[testenv:lint]
69-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
7066
deps = prospector==1.1.6.2
7167
commands =
7268
prospector --profile-path={toxinidir}
7369

7470
[testenv:safety]
75-
parallel_show_output = {env:TOX_SHOW_OUTPUT:false}
7671
deps = safety
7772
commands =
7873
safety check

0 commit comments

Comments
 (0)