[Scons-dev] SubstitutionEnvironment performance

Mats Wichmann mats at wichmann.us
Sun Apr 21 14:19:10 EDT 2019


The SubstitutionEnvironment.__getitem__ method has a big 'ol comment:

# This is heavily used.  This implementation is the best we have
# according to the timings in bench/env.__setitem__.py.
#
# The "key in self._special_set_keys" test here seems to perform
# pretty well for the number of keys we have.  A hard-coded
# list works a little better in Python 2.5, but that has the
# disadvantage of maybe getting out of sync if we ever add more
# variable names.  Using self._special_set.has_key() works a
# little better in Python 2.4, but is worse than this test.
# So right now it seems like a good trade-off, but feel free to
# revisit this with bench/env.__setitem__.py as needed (and
# as newer versions of Python come out).

I tried to run said benchmark, with these results:

Environment __setitem__ benchmark using Python 2.7.15 on linux2 posix

Results for re-adding an existing variable name 100 times:
      0.267 s   Best __setitem__(), with has_key
      0.280 s   Greg's Folly: isalnum instead of probe
      0.305 s   Best __setitem__(), with a list
...
      0.625 s   _special_set.get():  use "key in attribute" instead
      0.642 s   is_valid_construction_var():  use a method

Results for adding 100 variable names, 50 existing and 50 new:
      0.295 s   Greg's Folly: isalnum instead of probe
      0.405 s   Best __setitem__(), with has_key
      0.442 s   Best __setitem__(), with a list
...
      0.654 s   _special_set.get():  use "key in attribute" instead
      0.865 s   avoid is_valid_construction_var():  use try:-except:

Results for adding 100 new, unique variable names:
      0.311 s   Greg's Folly: isalnum instead of probe
      0.544 s   Best __setitem__(), with has_key
      0.574 s   is_valid_construction_var():  use a global regex
      0.577 s   Best __setitem__(), with a list
...
      0.745 s   avoid is_valid_construction_var():  use not .has_key()
      1.393 s   avoid is_valid_construction_var():  use try:-except:


The current algorithm is, by a small margin, the winner
on the 100-replace test, but falls to second by a noticable
margin to the "Greg's Folly" algorithm for the other two.

I'm not sure if that's enough to make the switch, especially
since I get nothing from Python3, arguably the more important
result now as it gains in prominence:

Traceback (most recent call last):
  File "bench/env.__setitem__.py", line 333, in <module>
    for n in locals().keys():
RuntimeError: dictionary changed size during iteration


More information about the Scons-dev mailing list