diff --git a/examples/m2l-timing.py b/examples/m2l-timing.py
deleted file mode 100644
index 8596f8914a17a9d2028447b3043a3c7c79d47d36..0000000000000000000000000000000000000000
--- a/examples/m2l-timing.py
+++ /dev/null
@@ -1,30 +0,0 @@
-
-def test_m2l_creation(ctx, mpole_expn_class, local_expn_class, knl, order):
-    from sympy.core.cache import clear_cache
-    clear_cache()
-    m_expn = mpole_expn_class(knl, order=order)
-    l_expn = local_expn_class(knl, order=order)
-    from sumpy.e2e import E2EFromCSR
-    m2l = E2EFromCSR(ctx, m_expn, l_expn)
-    import time
-    start = time.time()
-    m2l.run_translation_and_cse()
-    return time.time() - start
-
-if __name__ == "__main__":
-    import logging
-    logging.basicConfig(level=logging.INFO)
-    from sumpy.kernel import HelmholtzKernel, LaplaceKernel
-
-    import pyopencl as cl
-    ctx = cl._csc()
-    from sumpy.expansion.local import HelmholtzConformingVolumeTaylorLocalExpansion as LExpn
-    from sumpy.expansion.multipole import HelmholtzConformingVolumeTaylorMultipoleExpansion as MExpn
-    #from sumpy.expansion.local import H2DLocalExpansion as LExpn
-    #from sumpy.expansion.multipole import H2DMultipoleExpansion as MExpn
-    results = []
-    for order in range(1, 2):
-        results.append((order, test_m2l_creation(ctx, MExpn, LExpn, HelmholtzKernel(2, 'k'), order)))
-    print("order\ttime (s)")
-    for order, time in results:
-        print("{}\t{:.2f}".format(order, time))
diff --git a/sumpy/assignment_collection.py b/sumpy/assignment_collection.py
index 00c0266ba89b5f584ea7133b59308c2adbb96038..2bfdbc2af243cd1f5b429f32902366cd3c2b87ef 100644
--- a/sumpy/assignment_collection.py
+++ b/sumpy/assignment_collection.py
@@ -41,26 +41,29 @@ Manipulating batches of assignments
 """
 
 
-def _generate_unique_possibilities(prefix):
-    yield prefix
-
-    try_num = 0
-    while True:
-        yield "%s_%d" % (prefix, try_num)
-        try_num += 1
-
-
 class _SymbolGenerator(object):
+
     def __init__(self, taken_symbols):
         self.taken_symbols = taken_symbols
-        self.generated_names = set()
+        from collections import defaultdict
+        self.base_to_count = defaultdict(lambda: 0)
 
     def __call__(self, base="expr"):
-        for id_str in _generate_unique_possibilities(base):
-            if id_str not in self.taken_symbols \
-                    and id_str not in self.generated_names:
-                self.generated_names.add(id_str)
-                return sp.Symbol(id_str)
+        count = self.base_to_count[base]
+
+        def make_id_str(base, count):
+            return "{base}{suffix}".format(
+                    base=base,
+                    suffix="" if count == 0 else "_" + str(count - 1))
+
+        id_str = make_id_str(base, count)
+        while id_str in self.taken_symbols:
+            count += 1
+            id_str = make_id_str(base, count)
+
+        self.base_to_count[base] = count + 1
+
+        return sp.Symbol(id_str)
 
     def __iter__(self):
         return self
@@ -149,9 +152,7 @@ class SymbolicAssignmentCollection(object):
         """Assign *expr* to a new variable whose name is based on *name_base*.
         Return the new variable name.
         """
-        for new_name in _generate_unique_possibilities(name_base):
-            if new_name not in self.assignments:
-                break
+        new_name = self.symbol_generator(name_base).name
 
         self.add_assignment(new_name, expr)
         self.user_symbols.add(new_name)
@@ -160,7 +161,7 @@ class SymbolicAssignmentCollection(object):
     def run_global_cse(self, extra_exprs=[]):
         logger.info("common subexpression elimination: start")
 
-        assign_names = sorted(self.assign_names)
+        assign_names = sorted(self.assignments)
         assign_exprs = [self.assignments[name] for name in assign_names]
 
         # Options here: