lmmentel / mendeleev

A python package for accessing various properties of elements, ions and isotopes in the periodic table of elements.
https://mendeleev.readthedocs.io
MIT License
225 stars 43 forks source link

Significant performance overhead from SQLite #7

Closed cobalamin closed 4 years ago

cobalamin commented 5 years ago

First of all, thank you for creating this library and making it public! There is lots of useful data here.

We were recently wondering why our cheminformatics code was taking a seemingly unnecessarily long time to run. Through profiling our functions, we found that this was mainly due to calls to SQLite, {method 'execute' of 'sqlite3.Cursor' objects}, and then found out that these calls were being made from mendeleev, when retrieving (unchanging) data about electronegativity.

When gathering this data once, we only need e.g. dictionary access, and this increases the performance of these calls themselves by a factor of roughly 400,000 (from ms to ns)! When called a lot of times, this terribly slows down performance. At the end of this post, there are some measurements from a machine with an SSD; for our purposes the impact is even worse, since the Python installation we're using lives on an NFS. Especially SQLite incurs a lot of disk access, which is bad news on an NFS for numerous reasons.

By simply prefetching this data, we could get the call runtime of our larger more complex functions to go down from ~1s to ~30ms per call, or by a factor of ~33.

One could argue that users should then just do prefetching, but IMO some of this data could be kept purely in memory by mendeleev itself and increase performance significantly, which is especially useful for users who don't know how to find performance bottlenecks :)


import mendeleev

symbols = [x.symbol for x in mendeleev.get_all_elements()]
ens = {sym: mendeleev.element(sym).electronegativity(scale='pauling') for sym in symbols}
%timeit ens['Au']

51.8 ns ± 0.404 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit mendeleev.element('Au').electronegativity(scale='pauling')

20.5 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

20.5e-3 / 51.8e-9

395752.89575289574


cobalamin commented 5 years ago

Profiler output for prefetched retrieval:

%prun ens['Au']

         3 function calls in 0.000 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Profiler output for mendeleev call:

%prun mendeleev.element('Au').electronegativity(scale='pauling')

         25669 function calls (24659 primitive calls) in 0.048 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      103    0.011    0.000    0.011    0.000 state.py:89(__init__)
       11    0.003    0.000    0.003    0.000 {method 'execute' of 'sqlite3.Cursor' objects}
     1982    0.001    0.000    0.001    0.000 {built-in method builtins.isinstance}
      127    0.001    0.000    0.003    0.000 compiler.py:789(visit_label)
      156    0.001    0.000    0.001    0.000 compiler.py:843(visit_column)
      127    0.001    0.000    0.007    0.000 compiler.py:1776(_label_select_column)
       35    0.001    0.000    0.004    0.000 selectable.py:513(corresponding_column)
   365/10    0.000    0.000    0.010    0.001 visitors.py:86(_compiler_dispatch)
  248/116    0.000    0.000    0.001    0.000 langhelpers.py:273(get_cls_kwargs)
      217    0.000    0.000    0.001    0.000 compiler.py:3514(_requires_quotes)
    103/1    0.000    0.000    0.025    0.025 loading.py:492(_instance)
  846/802    0.000    0.000    0.001    0.000 {built-in method builtins.getattr}
  326/277    0.000    0.000    0.004    0.000 langhelpers.py:852(__get__)
      225    0.000    0.000    0.003    0.000 type_api.py:515(_dialect_info)
      457    0.000    0.000    0.001    0.000 compiler.py:3566(quote)
    103/1    0.000    0.000    0.025    0.025 loading.py:677(_populate_full)
        8    0.000    0.000    0.000    0.000 {method 'fetchall' of 'sqlite3.Cursor' objects}
      113    0.000    0.000    0.000    0.000 type_api.py:1463(adapt_type)
      248    0.000    0.000    0.000    0.000 {method 'match' of 're.Pattern' objects}
        7    0.000    0.000    0.012    0.002 strategies.py:987(setup_query)
       14    0.000    0.000    0.001    0.000 schema.py:1028(__init__)
      184    0.000    0.000    0.000    0.000 compiler.py:1557(_truncated_identifier)
      456    0.000    0.000    0.000    0.000 weakref.py:395(__getitem__)
  182/168    0.000    0.000    0.001    0.000 {built-in method builtins.hasattr}
      204    0.000    0.000    0.000    0.000 loading.py:54(filter_fn)
      274    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
        8    0.000    0.000    0.001    0.000 loading.py:337(_instance_processor)
       14    0.000    0.000    0.002    0.000 schema.py:1573(_make_proxy)
       14    0.000    0.000    0.001    0.000 query.py:4473(__init__)
       17    0.000    0.000    0.001    0.000 selectable.py:2738(__init__)
      113    0.000    0.000    0.002    0.000 langhelpers.py:1139(constructor_copy)
    111/2    0.000    0.000    0.026    0.013 loading.py:35(instances)
      159    0.000    0.000    0.000    0.000 inspection.py:38(inspect)
      135    0.000    0.000    0.003    0.000 type_api.py:450(dialect_impl)
        1    0.000    0.000    0.000    0.000 {built-in method posix.listdir}
       64    0.000    0.000    0.008    0.000 base.py:215(generate)
        8    0.000    0.000    0.013    0.002 loading.py:287(_setup_entity_query)
      118    0.000    0.000    0.000    0.000 type_api.py:493(_cached_result_processor)
      125    0.000    0.000    0.000    0.000 interfaces.py:516(_get_context_loader)
       94    0.000    0.000    0.000    0.000 langhelpers.py:253(_inspect_func_args)
    28/14    0.000    0.000    0.005    0.000 visitors.py:452(clone)
      873    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
    17/10    0.000    0.000    0.010    0.001 compiler.py:2022(visit_select)
       47    0.000    0.000    0.001    0.000 _collections.py:755(unique_list)
       17    0.000    0.000    0.000    0.000 selectable.py:3010(_froms)
      118    0.000    0.000    0.013    0.000 interfaces.py:546(setup)
      350    0.000    0.000    0.000    0.000 weakref.py:435(__contains__)
        7    0.000    0.000    0.003    0.000 strategies.py:1110(_generate_from_original_query)
      411    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x10717cf70}
       15    0.000    0.000    0.002    0.000 query.py:3990(_simple_statement)
      407    0.000    0.000    0.000    0.000 langhelpers.py:1148(<genexpr>)
       28    0.000    0.000    0.000    0.000 elements.py:715(__getattr__)
     15/8    0.000    0.000    0.014    0.002 query.py:3865(_compile_context)
      103    0.000    0.000    0.012    0.000 instrumentation.py:340(new_instance)
    53/52    0.000    0.000    0.002    0.000 deprecations.py:115(warned)
      759    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
       15    0.000    0.000    0.000    0.000 query.py:4693(__init__)
        1    0.000    0.000    0.000    0.000 {built-in method _sqlite3.connect}
       80    0.000    0.000    0.000    0.000 registry.py:53(_collection_gced)
       13    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1356(find_spec)
      612    0.000    0.000    0.000    0.000 loading.py:56(<genexpr>)
       28    0.000    0.000    0.000    0.000 elements.py:4347(__add__)
       90    0.000    0.000    0.000    0.000 elements.py:4394(_expand_cloned)
        1    0.000    0.000    0.048    0.048 <string>:1(<module>)
       17    0.000    0.000    0.008    0.000 compiler.py:2105(<listcomp>)
        7    0.000    0.000    0.003    0.000 query.py:2282(_join)
      125    0.000    0.000    0.000    0.000 selectable.py:3709(name_for_col)
        8    0.000    0.000    0.000    0.000 default.py:666(_init_compiled)
       22    0.000    0.000    0.000    0.000 query.py:202(_set_entity_selectables)
        8    0.000    0.000    0.000    0.000 result.py:317(<listcomp>)
    41/20    0.000    0.000    0.000    0.000 langhelpers.py:925(__getattr__)
       28    0.000    0.000    0.004    0.000 visitors.py:227(replace)
      113    0.000    0.000    0.002    0.000 type_api.py:534(adapt)
       14    0.000    0.000    0.000    0.000 attributes.py:225(__getattr__)
        7    0.000    0.000    0.002    0.000 util.py:969(__init__)
      111    0.000    0.000    0.000    0.000 strategies.py:175(setup_query)
        7    0.000    0.000    0.000    0.000 strategies.py:1317(<listcomp>)
       80    0.000    0.000    0.000    0.000 elements.py:4201(__new__)
        7    0.000    0.000    0.000    0.000 query.py:2664(_join_check_and_adapt_right_side)
        8    0.000    0.000    0.005    0.001 base.py:1163(_execute_context)
      103    0.000    0.000    0.000    0.000 state.py:379(_cleanup)
      138    0.000    0.000    0.000    0.000 weakref.py:408(__setitem__)
        7    0.000    0.000    0.013    0.002 loading.py:88(<listcomp>)
       71    0.000    0.000    0.000    0.000 query.py:518(_clone)
       42    0.000    0.000    0.004    0.000 util.py:808(replace)
      113    0.000    0.000    0.000    0.000 default.py:437(type_descriptor)
      257    0.000    0.000    0.000    0.000 {method 'get' of 'mappingproxy' objects}
       35    0.000    0.000    0.004    0.000 util.py:789(_corresponding_column)
       13    0.000    0.000    0.000    0.000 elements.py:3107(__init__)
       35    0.000    0.000    0.000    0.000 base.py:613(contains_column)
       14    0.000    0.000    0.000    0.000 elements.py:4028(_gen_label)
      127    0.000    0.000    0.000    0.000 compiler.py:410(__init__)
    17/10    0.000    0.000    0.001    0.000 compiler.py:2210(_compose_select_body)
        7    0.000    0.000    0.002    0.000 relationships.py:3093(join_targets)
      174    0.000    0.000    0.000    0.000 {method 'copy' of 'dict' objects}
      459    0.000    0.000    0.000    0.000 {method 'add' of 'set' objects}
        8    0.000    0.000    0.001    0.000 result.py:215(__init__)
       15    0.000    0.000    0.001    0.000 query.py:170(_set_entities)
       45    0.000    0.000    0.000    0.000 _collections.py:802(to_list)
        8    0.000    0.000    0.001    0.000 _collections.py:762(<listcomp>)
       13    0.000    0.000    0.000    0.000 {built-in method posix.stat}
       17    0.000    0.000    0.001    0.000 <string>:1(select)
      271    0.000    0.000    0.000    0.000 {method 'update' of 'set' objects}
       13    0.000    0.000    0.000    0.000 default_comparator.py:41(_boolean_compare)
        7    0.000    0.000    0.001    0.000 strategies.py:1175(_prep_for_joins)
       49    0.000    0.000    0.000    0.000 base.py:39(<listcomp>)
       14    0.000    0.000    0.000    0.000 query.py:4644(setup_context)
      237    0.000    0.000    0.000    0.000 {method 'intersection' of 'set' objects}
       17    0.000    0.000    0.001    0.000 selectable.py:3039(_get_display_froms)
        1    0.000    0.000    0.046    0.046 query.py:3246(one_or_none)
       31    0.000    0.000    0.000    0.000 _collections.py:361(__init__)
        7    0.000    0.000    0.000    0.000 selectable.py:1298(_init)
       10    0.000    0.000    0.010    0.001 compiler.py:509(__init__)
       17    0.000    0.000    0.001    0.000 compiler.py:2181(_setup_select_stack)
       14    0.000    0.000    0.000    0.000 _collections.py:253(__init__)
       30    0.000    0.000    0.000    0.000 base.py:77(__init__)
       30    0.000    0.000    0.001    0.000 base.py:295(__get__)
        8    0.000    0.000    0.001    0.000 result.py:408(<listcomp>)
       21    0.000    0.000    0.000    0.000 util.py:770(__init__)
       38    0.000    0.000    0.000    0.000 elements.py:4246(__new__)
       14    0.000    0.000    0.000    0.000 selectable.py:653(_init_collections)
      118    0.000    0.000    0.001    0.000 default.py:1081(get_result_processor)
      134    0.000    0.000    0.000    0.000 {method 'difference' of 'set' objects}
       39    0.000    0.000    0.000    0.000 _collections.py:759(<listcomp>)
       35    0.000    0.000    0.000    0.000 base.py:601(__contains__)
       15    0.000    0.000    0.000    0.000 compiler.py:1333(_generate_generic_binary)
      103    0.000    0.000    0.000    0.000 identity.py:216(_fast_discard)
       14    0.000    0.000    0.005    0.000 visitors.py:425(replacement_traverse)
       24    0.000    0.000    0.000    0.000 attr.py:166(update_subclass)
      6/5    0.000    0.000    0.000    0.000 registry.py:193(listen)
       14    0.000    0.000    0.000    0.000 attributes.py:193(adapt_to_entity)
       29    0.000    0.000    0.000    0.000 selectable.py:55(_interpret_as_from)
        8    0.000    0.000    0.014    0.002 base.py:1056(_execute_clauseelement)
      118    0.000    0.000    0.000    0.000 result.py:641(_getter)
       33    0.000    0.000    0.000    0.000 elements.py:682(self_group)
     21/7    0.000    0.000    0.003    0.000 selectable.py:611(columns)
      113    0.000    0.000    0.000    0.000 type_api.py:317(_has_column_expression)
      113    0.000    0.000    0.000    0.000 type_api.py:531(_gen_dialect_impl)
       17    0.000    0.000    0.000    0.000 compiler.py:1579(_process_anon)
       49    0.000    0.000    0.000    0.000 base.py:38(_from_objects)
      169    0.000    0.000    0.000    0.000 elements.py:3989(_get_table)
       17    0.000    0.000    0.001    0.000 selectable.py:3704(_columns_plus_names)
       13    0.000    0.000    0.000    0.000 type_api.py:64(operate)
      120    0.000    0.000    0.000    0.000 compiler.py:1773(_add_to_result_map)
       14    0.000    0.000    0.001    0.000 util.py:493(__getattr__)
       37    0.000    0.000    0.000    0.000 langhelpers.py:897(expire_instance)
       90    0.000    0.000    0.000    0.000 elements.py:4399(<listcomp>)
      127    0.000    0.000    0.001    0.000 compiler.py:3635(format_label)
       14    0.000    0.000    0.000    0.000 query.py:4609(setup_entity)
        5    0.000    0.000    0.000    0.000 registry.py:67(_stored_in_collection)
      118    0.000    0.000    0.000    0.000 result.py:722(_getter)
      103    0.000    0.000    0.000    0.000 identity.py:161(_add_unpresent)
       45    0.000    0.000    0.000    0.000 {built-in method _abc._abc_instancecheck}
       12    0.000    0.000    0.000    0.000 elements.py:3127(__bool__)
       36    0.000    0.000    0.000    0.000 base.py:94(__getattr__)
        7    0.000    0.000    0.000    0.000 query.py:1532(_options)
        1    0.000    0.000    0.001    0.001 strategies.py:52(create)
        4    0.000    0.000    0.000    0.000 schema.py:1676(__init__)
      100    0.000    0.000    0.000    0.000 collections.py:1112(append)
       22    0.000    0.000    0.000    0.000 query.py:4082(__new__)
      247    0.000    0.000    0.000    0.000 {built-in method builtins.len}
       30    0.000    0.000    0.000    0.000 base.py:116(_for_class)
        7    0.000    0.000    0.002    0.000 query.py:2425(_join_left_to_right)
       22    0.000    0.000    0.000    0.000 path_registry.py:63(set)
       14    0.000    0.000    0.000    0.000 elements.py:254(_annotate)
       24    0.000    0.000    0.000    0.000 elements.py:4361(apply_map)
    28/13    0.000    0.000    0.001    0.000 operators.py:358(__eq__)
        7    0.000    0.000    0.000    0.000 util.py:568(__init__)
        8    0.000    0.000    0.000    0.000 query.py:4116(setup_entity)
       14    0.000    0.000    0.000    0.000 base.py:477(__init__)
       21    0.000    0.000    0.000    0.000 base.py:621(__init__)
       21    0.000    0.000    0.000    0.000 attributes.py:78(__init__)
        7    0.000    0.000    0.001    0.000 query.py:1485(add_columns)
        7    0.000    0.000    0.003    0.000 strategies.py:1222(_apply_joins)
      103    0.000    0.000    0.000    0.000 {method 'issuperset' of 'frozenset' objects}
        8    0.000    0.000    0.016    0.002 query.py:3362(_execute_and_instances)
      142    0.000    0.000    0.000    0.000 langhelpers.py:938(memo)
       14    0.000    0.000    0.004    0.000 elements.py:4483(_literal_as_label_reference)
        7    0.000    0.000    0.001    0.000 selectable.py:3730(_populate_column_collection)
        7    0.000    0.000    0.000    0.000 util.py:454(__init__)
      193    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.048    0.048 {built-in method builtins.exec}
       14    0.000    0.000    0.000    0.000 annotation.py:52(__init__)
       24    0.000    0.000    0.000    0.000 attr.py:227(__init__)
        7    0.000    0.000    0.000    0.000 util.py:326(clause_is_present)
       14    0.000    0.000    0.000    0.000 util.py:367(surface_column_elements)
        7    0.000    0.000    0.000    0.000 path_registry.py:90(contains_mapper)
      103    0.000    0.000    0.000    0.000 <string>:1(set)
       53    0.000    0.000    0.000    0.000 {method 'pop' of 'list' objects}
      294    0.000    0.000    0.000    0.000 {built-in method builtins.id}
       16    0.000    0.000    0.000    0.000 elements.py:3880(__init__)
      168    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
       65    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:56(_path_join)
      102    0.000    0.000    0.000    0.000 _collections.py:112(__new__)
       21    0.000    0.000    0.000    0.000 base.py:616(as_immutable)
       30    0.000    0.000    0.000    0.000 elements.py:3992(_set_table)
       40    0.000    0.000    0.000    0.000 attr.py:269(__bool__)
       65    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:58(<listcomp>)
        1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap_external>:1240(_get_spec)
        7    0.000    0.000    0.000    0.000 elements.py:1885(__init__)
      127    0.000    0.000    0.000    0.000 elements.py:4621(_interpret_as_column_or_from)
        7    0.000    0.000    0.000    0.000 util.py:854(__init__)
       14    0.000    0.000    0.004    0.000 query.py:312(<listcomp>)
        4    0.000    0.000    0.001    0.000 base.py:454(_set_parent_with_dispatch)
        7    0.000    0.000    0.000    0.000 elements.py:198(_clone)
       17    0.000    0.000    0.000    0.000 elements.py:4407(<listcomp>)
       22    0.000    0.000    0.000    0.000 annotation.py:78(_compiler_dispatch)
        8    0.000    0.000    0.000    0.000 compiler.py:1460(visit_bindparam)
       29    0.000    0.000    0.000    0.000 query.py:326(_adapt_clause)
        7    0.000    0.000    0.000    0.000 query.py:2598(_join_place_explicit_left_side)
        1    0.000    0.000    0.000    0.000 econf.py:119(parse)
       13    0.000    0.000    0.001    0.000 annotation.py:102(__eq__)
       17    0.000    0.000    0.000    0.000 selectable.py:2147(__init__)
       32    0.000    0.000    0.000    0.000 sqltypes.py:141(__init__)
        7    0.000    0.000    0.001    0.000 compiler.py:2364(visit_join)
        7    0.000    0.000    0.000    0.000 relationships.py:945(adapt_to_entity)
        7    0.000    0.000    0.000    0.000 strategies.py:1274(_setup_options)
      106    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
       15    0.000    0.000    0.000    0.000 selectable.py:3721(<listcomp>)
        8    0.000    0.000    0.000    0.000 query.py:4020(_adjust_for_single_inheritance)
        8    0.000    0.000    0.001    0.000 query.py:4196(row_processor)
        7    0.000    0.000    0.000    0.000 strategies.py:1325(create_row_processor)
       50    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}
       10    0.000    0.000    0.010    0.001 <string>:1(<lambda>)
        8    0.000    0.000    0.000    0.000 result.py:266(<listcomp>)
        8    0.000    0.000    0.001    0.000 result.py:738(_init_metadata)
        7    0.000    0.000    0.025    0.004 strategies.py:1315(_load)
        7    0.000    0.000    0.002    0.000 selectable.py:1343(_populate_column_collection)
       14    0.000    0.000    0.000    0.000 base.py:326(_class_to_mapper)
    27/25    0.000    0.000    0.001    0.000 {built-in method _operator.eq}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1404(_fill_cache)
        7    0.000    0.000    0.000    0.000 base.py:42(_generative)
        7    0.000    0.000    0.000    0.000 elements.py:4680(__init__)
        5    0.000    0.000    0.000    0.000 attr.py:355(__init__)
       10    0.000    0.000    0.010    0.001 compiler.py:274(__init__)
        7    0.000    0.000    0.004    0.001 util.py:667(_adapt_element)
        7    0.000    0.000    0.000    0.000 strategies.py:1086(_get_leftmost)
       21    0.000    0.000    0.000    0.000 langhelpers.py:858(_reset)
       84    0.000    0.000    0.000    0.000 visitors.py:161(visitor_iterator)
        7    0.000    0.000    0.003    0.000 util.py:907(traverse)
       15    0.000    0.000    0.000    0.000 compiler.py:2335(visit_table)
        7    0.000    0.000    0.000    0.000 query.py:239(_set_select_from)
      245    0.000    0.000    0.000    0.000 {method 'discard' of 'set' objects}
        5    0.000    0.000    0.000    0.000 registry.py:267(append_to_list)
      120    0.000    0.000    0.000    0.000 compiler.py:419(type)
       15    0.000    0.000    0.000    0.000 compiler.py:1276(visit_binary)
        7    0.000    0.000    0.001    0.000 query.py:540(subquery)
       15    0.000    0.000    0.000    0.000 query.py:3488(_select_args)
      103    0.000    0.000    0.000    0.000 identity.py:166(get)
       35    0.000    0.000    0.000    0.000 _collections.py:173(__init__)
       15    0.000    0.000    0.000    0.000 elements.py:3139(_from_objects)
        7    0.000    0.000    0.001    0.000 elements.py:3143(_copy_internals)
       31    0.000    0.000    0.000    0.000 type_api.py:1453(to_instance)
        8    0.000    0.000    0.001    0.000 result.py:334(_merge_cursor_description)
       14    0.000    0.000    0.004    0.000 attributes.py:179(__clause_element__)
        8    0.000    0.000    0.000    0.000 {method 'issuperset' of 'set' objects}
       14    0.000    0.000    0.000    0.000 langhelpers.py:1392(set_creation_order)
       15    0.000    0.000    0.000    0.000 base.py:346(_is_mapped_class)
       23    0.000    0.000    0.000    0.000 __init__.py:1361(debug)
       14    0.000    0.000    0.000    0.000 _collections.py:333(__setitem__)
       14    0.000    0.000    0.005    0.000 visitors.py:224(traverse)
      127    0.000    0.000    0.000    0.000 elements.py:749(_select_iterable)
        7    0.000    0.000    0.000    0.000 selectable.py:4003(__init__)
        5    0.000    0.000    0.000    0.000 api.py:23(_event_key)
        1    0.000    0.000    0.000    0.000 base.py:87(<dictcomp>)
       15    0.000    0.000    0.000    0.000 compiler.py:1183(_get_operator_dispatch)
      103    0.000    0.000    0.000    0.000 loading.py:508(<listcomp>)
        7    0.000    0.000    0.003    0.000 query.py:1983(join)
        8    0.000    0.000    0.013    0.002 query.py:4231(setup_context)
        1    0.000    0.000    0.000    0.000 {built-in method posix.getcwd}
       45    0.000    0.000    0.000    0.000 abc.py:137(__instancecheck__)
       14    0.000    0.000    0.000    0.000 annotation.py:38(__new__)
       24    0.000    0.000    0.000    0.000 attr.py:160(_assign_cls_collection)
        7    0.000    0.000    0.001    0.000 compiler.py:1720(visit_alias)
       14    0.000    0.000    0.000    0.000 path_registry.py:176(__add__)
        7    0.000    0.000    0.002    0.000 relationships.py:2146(_create_joins)
      146    0.000    0.000    0.000    0.000 {function EntityRegistry.__getitem__ at 0x11741d598}
       35    0.000    0.000    0.000    0.000 _collections.py:214(__contains__)
       24    0.000    0.000    0.004    0.000 _collections.py:733(__missing__)
        7    0.000    0.000    0.004    0.001 langhelpers.py:935(oneshot)
        7    0.000    0.000    0.000    0.000 visitors.py:170(chain)
       28    0.000    0.000    0.000    0.000 elements.py:232(_cloned_set)
     14/7    0.000    0.000    0.000    0.000 elements.py:757(proxy_set)
       20    0.000    0.000    0.000    0.000 operators.py:1409(is_boolean)
        7    0.000    0.000    0.000    0.000 selectable.py:727(__init__)
        7    0.000    0.000    0.000    0.000 query.py:3423(<listcomp>)
        1    0.000    0.000    0.000    0.000 session.py:3159(__init__)
       10    0.000    0.000    0.010    0.001 elements.py:464(_compiler)
        4    0.000    0.000    0.000    0.000 schema.py:2080(_set_table)
        7    0.000    0.000    0.003    0.000 util.py:913(_locate_col)
        8    0.000    0.000    0.000    0.000 result.py:1190(<listcomp>)
       14    0.000    0.000    0.000    0.000 base.py:539(__setitem__)
       17    0.000    0.000    0.000    0.000 elements.py:4402(_select_iterables)
        7    0.000    0.000    0.000    0.000 selectable.py:2109(_generate)
       17    0.000    0.000    0.000    0.000 selectable.py:3053(<listcomp>)
        6    0.000    0.000    0.000    0.000 registry.py:154(__init__)
     15/8    0.000    0.000    0.001    0.000 compiler.py:2230(<listcomp>)
        5    0.000    0.000    0.000    0.000 collections.py:657(append_multiple_without_event)
       21    0.000    0.000    0.000    0.000 path_registry.py:322(__getitem__)
       15    0.000    0.000    0.000    0.000 query.py:379(_entity_zero)
       14    0.000    0.000    0.000    0.000 elements.py:4020(_label)
       30    0.000    0.000    0.000    0.000 base.py:119(_for_instance)
        8    0.000    0.000    0.000    0.000 result.py:404(<listcomp>)
       30    0.000    0.000    0.000    0.000 base.py:228(manager_of_class)
       14    0.000    0.000    0.000    0.000 path_registry.py:85(pairs)
        8    0.000    0.000    0.030    0.004 query.py:3337(__iter__)
        7    0.000    0.000    0.000    0.000 query.py:4627(row_processor)
        8    0.000    0.000    0.001    0.000 session.py:407(_connection_for_bind)
       22    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
       68    0.000    0.000    0.000    0.000 {built-in method builtins.setattr}
       14    0.000    0.000    0.000    0.000 {built-in method _functools.reduce}
       14    0.000    0.000    0.000    0.000 schema.py:1585(<listcomp>)
        5    0.000    0.000    0.000    0.000 base.py:243(_listen)
        7    0.000    0.000    0.000    0.000 compiler.py:972(visit_clauselist)
        8    0.000    0.000    0.000    0.000 result.py:1193(fetchall)
        7    0.000    0.000    0.000    0.000 attributes.py:203(of_type)
        5    0.000    0.000    0.000    0.000 attributes.py:1211(_initialize_collection)
        5    0.000    0.000    0.000    0.000 attributes.py:1331(set_committed_value)
        7    0.000    0.000    0.000    0.000 strategies.py:1102(<listcomp>)
       14    0.000    0.000    0.000    0.000 base.py:520(add)
       14    0.000    0.000    0.000    0.000 selectable.py:531(embedded)
       54    0.000    0.000    0.000    0.000 sqltypes.py:725(__init__)
       64    0.000    0.000    0.000    0.000 mapper.py:2263(selectable)
        7    0.000    0.000    0.000    0.000 state.py:771(_commit)
        7    0.000    0.000    0.004    0.001 properties.py:287(_memoized_method___clause_element__)
        7    0.000    0.000    0.001    0.000 query.py:524(statement)
        7    0.000    0.000    0.004    0.001 query.py:1804(order_by)
        7    0.000    0.000    0.000    0.000 query.py:2270(_update_joinpoint)
        8    0.000    0.000    0.000    0.000 session.py:1540(query)
        7    0.000    0.000    0.000    0.000 strategies.py:1217(<listcomp>)
      102    0.000    0.000    0.000    0.000 strategies.py:1318(<lambda>)
        1    0.000    0.000    0.048    0.048 mendeleev.py:123(_get_element)
       30    0.000    0.000    0.000    0.000 elements.py:4529(_literal_as_text)
        7    0.000    0.000    0.000    0.000 annotation.py:168(_shallow_annotate)
       14    0.000    0.000    0.000    0.000 attributes.py:240(__str__)
       14    0.000    0.000    0.004    0.000 query.py:310(_adapt_col_list)
        8    0.000    0.000    0.001    0.000 query.py:3377(_get_bind_args)
        7    0.000    0.000    0.000    0.000 query.py:4559(<listcomp>)
      131    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
       38    0.000    0.000    0.000    0.000 {built-in method builtins.hash}
        1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap>:882(_find_spec)
       54    0.000    0.000    0.000    0.000 sqltypes.py:754(result_processor)
        1    0.000    0.000    0.000    0.000 default.py:190(__init__)
        9    0.000    0.000    0.000    0.000 base.py:409(_inspect_mapped_class)
        7    0.000    0.000    0.000    0.000 query.py:1071(correlate)
        7    0.000    0.000    0.000    0.000 relationships.py:1012(of_type)
        8    0.000    0.000    0.001    0.000 session.py:1048(connection)
        7    0.000    0.000    0.000    0.000 strategies.py:1284(_setup_outermost_orderby)
        5    0.000    0.000    0.023    0.005 strategies.py:1372(load_collection_from_subq)
        2    0.000    0.000    0.000    0.000 posixpath.py:338(normpath)
       11    0.000    0.000    0.000    0.000 {method 'cursor' of 'sqlite3.Connection' objects}
        7    0.000    0.000    0.000    0.000 _collections.py:854(flatten_iterator)
        2    0.000    0.000    0.000    0.000 compat.py:60(inspect_getfullargspec)
       11    0.000    0.000    0.000    0.000 elements.py:703(comparator)
       13    0.000    0.000    0.001    0.000 elements.py:724(operate)
       30    0.000    0.000    0.000    0.000 elements.py:4513(_literal_as)
        8    0.000    0.000    0.000    0.000 operators.py:1497(is_precedent)
        4    0.000    0.000    0.000    0.000 schema.py:1993(_set_target_column)
        5    0.000    0.000    0.001    0.000 api.py:34(listen)
        5    0.000    0.000    0.000    0.000 registry.py:246(base_listen)
       13    0.000    0.000    0.000    0.000 default_comparator.py:359(_check_literal)
        1    0.000    0.000    0.001    0.001 base.py:631(__connect)
        8    0.000    0.000    0.000    0.000 result.py:867(_soft_close)
       29    0.000    0.000    0.000    0.000 path_registry.py:71(get)
        7    0.000    0.000    0.000    0.000 query.py:3382(column_descriptions)
        1    0.000    0.000    0.000    0.000 session.py:646(__init__)
       14    0.000    0.000    0.014    0.001 strategies.py:1317(<genexpr>)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1433(<setcomp>)
       21    0.000    0.000    0.000    0.000 langhelpers.py:861(reset)
       14    0.000    0.000    0.000    0.000 visitors.py:450(<setcomp>)
       10    0.000    0.000    0.010    0.001 elements.py:399(compile)
      118    0.000    0.000    0.000    0.000 elements.py:4254(apply_map)
        7    0.000    0.000    0.000    0.000 schema.py:1626(get_children)
       25    0.000    0.000    0.000    0.000 attr.py:257(__call__)
        6    0.000    0.000    0.001    0.000 attr.py:316(__call__)
        2    0.000    0.000    0.000    0.000 base.py:69(__init__)
        1    0.000    0.000    0.000    0.000 base.py:63(__init__)
        8    0.000    0.000    0.001    0.000 result.py:712(__init__)
        7    0.000    0.000    0.000    0.000 mapper.py:2596(common_parent)
       65    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:222(_verbose_message)
       26    0.000    0.000    0.000    0.000 __init__.py:1619(isEnabledFor)
       17    0.000    0.000    0.000    0.000 _collections.py:730(__init__)
        9    0.000    0.000    0.000    0.000 langhelpers.py:1160(_next)
        1    0.000    0.000    0.000    0.000 elements.py:926(__init__)
        7    0.000    0.000    0.000    0.000 elements.py:4493(_literal_and_labels_as_label_reference)
       11    0.000    0.000    0.000    0.000 type_api.py:60(__init__)
       33    0.000    0.000    0.000    0.000 annotation.py:99(__hash__)
        7    0.000    0.000    0.000    0.000 selectable.py:1205(_from_objects)
       30    0.000    0.000    0.000    0.000 selectable.py:2965(<genexpr>)
        7    0.000    0.000    0.000    0.000 schema.py:2915(__iter__)
       14    0.000    0.000    0.000    0.000 util.py:342(surface_selectables)
        1    0.000    0.000    0.001    0.001 default.py:289(initialize)
        8    0.000    0.000    0.000    0.000 compiler.py:650(construct_params)
        8    0.000    0.000    0.000    0.000 default.py:1064(create_cursor)
        7    0.000    0.000    0.000    0.000 properties.py:307(_fallback_getattr)
        7    0.000    0.000    0.000    0.000 query.py:396(_joinpoint_zero)
       14    0.000    0.000    0.000    0.000 relationships.py:1438(property)
        2    0.000    0.000    0.000    0.000 posixpath.py:64(isabs)
        4    0.000    0.000    0.000    0.000 schema.py:2058(_set_parent)
        5    0.000    0.000    0.000    0.000 attr.py:234(for_modify)
        1    0.000    0.000    0.001    0.001 default.py:359(_check_unicode_returns)
        2    0.000    0.000    0.001    0.000 default.py:370(check_unicode)
        7    0.000    0.000    0.000    0.000 path_registry.py:287(__init__)
        8    0.000    0.000    0.001    0.000 query.py:3356(_connection_from_session)
        7    0.000    0.000    0.000    0.000 _collections.py:890(get)
        8    0.000    0.000    0.015    0.002 elements.py:285(_execute_on_connection)
        8    0.000    0.000    0.000    0.000 elements.py:3168(self_group)
        7    0.000    0.000    0.000    0.000 selectable.py:419(alias)
        4    0.000    0.000    0.000    0.000 base.py:222(_accept_with)
        8    0.000    0.000    0.000    0.000 result.py:1176(process_rows)
        5    0.000    0.000    0.000    0.000 collections.py:618(__init__)
       15    0.000    0.000    0.000    0.000 query.py:486(_no_limit_offset)
        8    0.000    0.000    0.000    0.000 query.py:4104(__init__)
       10    0.000    0.000    0.000    0.000 _collections.py:370(add)
        7    0.000    0.000    0.000    0.000 _collections.py:951(lightweight_named_tuple)
        7    0.000    0.000    0.000    0.000 selectable.py:606(_reset_exported)
       20    0.000    0.000    0.000    0.000 operators.py:1386(is_comparison)
       14    0.000    0.000    0.000    0.000 annotation.py:69(_deannotate)
       10    0.000    0.000    0.010    0.001 compiler.py:349(process)
        8    0.000    0.000    0.000    0.000 compiler.py:629(_bind_processors)
        8    0.000    0.000    0.000    0.000 compiler.py:1544(_truncate_bindparam)
        8    0.000    0.000    0.000    0.000 {built-in method sqlalchemy.cutils._distill_params}
        1    0.000    0.000    0.000    0.000 url.py:234(_parse_rfc1738_args)
       10    0.000    0.000    0.003    0.000 default.py:579(do_execute)
        8    0.000    0.000    0.001    0.000 default.py:1122(get_result_proxy)
      102    0.000    0.000    0.000    0.000 mapper.py:731(mapper)
       38    0.000    0.000    0.000    0.000 attributes.py:274(__get__)
       21    0.000    0.000    0.000    0.000 path_registry.py:177(<lambda>)
        7    0.000    0.000    0.002    0.000 util.py:1094(join)
       15    0.000    0.000    0.000    0.000 query.py:474(_no_statement_condition)
        7    0.000    0.000    0.000    0.000 query.py:1529(_conditional_options)
       16    0.000    0.000    0.000    0.000 query.py:4176(_get_entity_clauses)
        7    0.000    0.000    0.001    0.000 <string>:1(add_columns)
        7    0.000    0.000    0.004    0.001 <string>:1(order_by)
       35    0.000    0.000    0.000    0.000 relationships.py:3238(__call__)
        9    0.000    0.000    0.000    0.000 api.py:815(_inspect_decl_meta)
       14    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1203(_path_importer_cache)
        5    0.000    0.000    0.000    0.000 weakref.py:356(__init__)
       17    0.000    0.000    0.000    0.000 _collections.py:396(__iter__)
        7    0.000    0.000    0.000    0.000 selectable.py:1246(_construct)
       14    0.000    0.000    0.001    0.000 schema.py:102(_init_items)
        4    0.000    0.000    0.000    0.000 schema.py:1530(_on_table_attach)
        8    0.000    0.000    0.015    0.002 base.py:922(execute)
        8    0.000    0.000    0.000    0.000 compiler.py:632(<genexpr>)
       16    0.000    0.000    0.000    0.000 compiler.py:634(<genexpr>)
       17    0.000    0.000    0.000    0.000 compiler.py:2103(<listcomp>)
        3    0.000    0.000    0.000    0.000 log.py:174(instance_logger)
       14    0.000    0.000    0.000    0.000 mapper.py:2609(isa)
        7    0.000    0.000    0.000    0.000 interfaces.py:377(adapt_to_entity)
       14    0.000    0.000    0.000    0.000 interfaces.py:389(adapter)
        7    0.000    0.000    0.000    0.000 path_registry.py:276(__getitem__)
        8    0.000    0.000    0.001    0.000 loading.py:64(<listcomp>)
        8    0.000    0.000    0.000    0.000 session.py:1417(get_bind)
      103    0.000    0.000    0.000    0.000 {method 'values' of 'dict' objects}
        4    0.000    0.000    0.000    0.000 re.py:271(_compile)
        7    0.000    0.000    0.000    0.000 elements.py:1895(<listcomp>)
       16    0.000    0.000    0.000    0.000 elements.py:3998(_from_objects)
        7    0.000    0.000    0.000    0.000 <string>:1(correlate)
       14    0.000    0.000    0.000    0.000 schema.py:1396(_extra_kwargs)
        4    0.000    0.000    0.000    0.000 base.py:224(dispatch_is)
       14    0.000    0.000    0.000    0.000 compiler.py:980(<genexpr>)
        8    0.000    0.000    0.000    0.000 compiler.py:1585(bindparam_string)
        7    0.000    0.000    0.000    0.000 compiler.py:2307(order_by_clause)
        8    0.000    0.000    0.000    0.000 default.py:710(<listcomp>)
        8    0.000    0.000    0.000    0.000 default.py:977(should_autocommit)
        8    0.000    0.000    0.000    0.000 query.py:399(_bind_mapper)
        5    0.000    0.000    0.000    0.000 strategies.py:1369(_create_collection_loader)
        1    0.000    0.000    0.000    0.000 econf.py:134(<listcomp>)
        1    0.000    0.000    0.000    0.000 {method 'sub' of 're.Pattern' objects}
        1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap>:978(_find_and_load)
       14    0.000    0.000    0.000    0.000 schema.py:2920(<genexpr>)
        5    0.000    0.000    0.000    0.000 attr.py:49(_memoized_attr_ref)
       15    0.000    0.000    0.000    0.000 mapper.py:2132(_with_polymorphic_mappers)
      100    0.000    0.000    0.000    0.000 collections.py:1068(__set)
        7    0.000    0.000    0.000    0.000 interfaces.py:556(create_row_processor)
        5    0.000    0.000    0.000    0.000 instrumentation.py:318(initialize_collection)
       35    0.000    0.000    0.000    0.000 util.py:736(<lambda>)
       14    0.000    0.000    0.000    0.000 relationships.py:932(__init__)
        8    0.000    0.000    0.000    0.000 query.py:141(__init__)
        7    0.000    0.000    0.000    0.000 query.py:4576(<listcomp>)
        7    0.000    0.000    0.000    0.000 <string>:1(_set_enable_single_crit)
        7    0.000    0.000    0.000    0.000 <string>:1(_options)
        1    0.000    0.000    0.000    0.000 session.py:220(__init__)
       14    0.000    0.000    0.000    0.000 strategies.py:1154(<genexpr>)
        7    0.000    0.000    0.025    0.004 strategies.py:1310(get)
       15    0.000    0.000    0.000    0.000 {method 'group' of 're.Match' objects}
        9    0.000    0.000    0.000    0.000 {method 'acquire' of '_thread.lock' objects}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:157(_get_module_lock)
        1    0.000    0.000    0.000    0.000 posixpath.py:154(dirname)
       21    0.000    0.000    0.000    0.000 elements.py:4370(_as_truncated)
        8    0.000    0.000    0.000    0.000 type_api.py:483(_cached_bind_processor)
       28    0.000    0.000    0.000    0.000 sqltypes.py:295(result_processor)
        6    0.000    0.000    0.000    0.000 attr.py:208(_adjust_fn_spec)
        9    0.000    0.000    0.000    0.000 instrumentation.py:102(is_mapped)
        7    0.000    0.000    0.000    0.000 query.py:3434(<listcomp>)
        7    0.000    0.000    0.000    0.000 <string>:1(_with_current_path)
        7    0.000    0.000    0.000    0.000 <string>:1(with_labels)
        7    0.000    0.000    0.003    0.000 <string>:1(_join)
        1    0.000    0.000    0.000    0.000 pysqlite.py:418(create_connect_args)
       29    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
       13    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:74(_path_stat)
       14    0.000    0.000    0.000    0.000 _collections.py:271(__init__)
        4    0.000    0.000    0.000    0.000 type_api.py:730(adapt)
        8    0.000    0.000    0.000    0.000 base.py:1332(_safe_close_cursor)
        7    0.000    0.000    0.000    0.000 attributes.py:182(_query_clause_element)
        7    0.000    0.000    0.000    0.000 path_registry.py:194(__getitem__)
        7    0.000    0.000    0.000    0.000 state.py:446(get_impl)
        7    0.000    0.000    0.000    0.000 query.py:4170(corresponds_to)
        8    0.000    0.000    0.001    0.000 session.py:1127(_connection_for_bind)
        1    0.000    0.000    0.000    0.000 session.py:3207(__call__)
        2    0.000    0.000    0.002    0.001 strategies.py:1395(load_scalar_from_subq)
        1    0.000    0.000    0.000    0.000 base.py:1512(get_isolation_level)
        3    0.000    0.000    0.000    0.000 __init__.py:1221(getLogger)
       14    0.000    0.000    0.000    0.000 base.py:278(_validate_dialect_kwargs)
        2    0.000    0.000    0.000    0.000 elements.py:2428(__init__)
        4    0.000    0.000    0.000    0.000 type_api.py:719(adapt_to_emulated)
        7    0.000    0.000    0.000    0.000 selectable.py:1199(_hide_froms)
        7    0.000    0.000    0.000    0.000 selectable.py:3526(correlate)
        2    0.000    0.000    0.000    0.000 sqltypes.py:412(__init__)
        5    0.000    0.000    0.000    0.000 attr.py:399(append)
        7    0.000    0.000    0.000    0.000 registry.py:169(with_wrapper)
        1    0.000    0.000    0.001    0.001 strategies.py:194(first_connect)
       14    0.000    0.000    0.000    0.000 compiler.py:982(<genexpr>)
       17    0.000    0.000    0.000    0.000 compiler.py:2291(get_select_precolumns)
        1    0.000    0.000    0.001    0.001 base.py:490(checkout)
        8    0.000    0.000    0.000    0.000 base.py:958(cursor)
        8    0.000    0.000    0.000    0.000 result.py:263(<listcomp>)
        8    0.000    0.000    0.000    0.000 result.py:862(_cursor_description)
        8    0.000    0.000    0.000    0.000 result.py:1159(_fetchall_impl)
        8    0.000    0.000    0.000    0.000 loading.py:880(for_context)
        7    0.000    0.000    0.000    0.000 util.py:1218(_entity_corresponds_to)
        7    0.000    0.000    0.000    0.000 <string>:1(enable_eagerloads)
        1    0.000    0.000    0.000    0.000 base.py:1429(__init__)
        1    0.000    0.000    0.001    0.001 pysqlite.py:397(dbapi)
       17    0.000    0.000    0.000    0.000 {method 'union' of 'set' objects}
        1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap>:948(_find_and_load_unlocked)
        2    0.000    0.000    0.000    0.000 posixpath.py:376(abspath)
        1    0.000    0.000    0.002    0.002 mendeleev.py:63(get_session)
       25    0.000    0.000    0.000    0.000 base.py:105(_event_descriptors)
        5    0.000    0.000    0.000    0.000 base.py:112(_listen)
        6    0.000    0.000    0.000    0.000 attr.py:98(_adjust_fn_spec)
       24    0.000    0.000    0.000    0.000 registry.py:263(_listen_fn)
        1    0.000    0.000    0.001    0.001 __init__.py:85(create_engine)
        2    0.000    0.000    0.000    0.000 base.py:1292(_cursor_execute)
        1    0.000    0.000    0.000    0.000 base.py:1857(__init__)
        7    0.000    0.000    0.000    0.000 attributes.py:243(property)
        7    0.000    0.000    0.000    0.000 interfaces.py:363(__init__)
        7    0.000    0.000    0.000    0.000 interfaces.py:371(_query_clause_element)
        5    0.000    0.000    0.000    0.000 state.py:412(dict)
        7    0.000    0.000    0.000    0.000 query.py:760(_with_current_path)
        7    0.000    0.000    0.000    0.000 query.py:4568(<listcomp>)
       14    0.000    0.000    0.000    0.000 relationships.py:3235(__init__)
        8    0.000    0.000    0.000    0.000 session.py:267(_assert_active)
        1    0.000    0.000    0.000    0.000 session.py:337(_take_snapshot)
        1    0.000    0.000    0.000    0.000 econf.py:78(conf)
        1    0.000    0.000    0.000    0.000 econf.py:131(<listcomp>)
        7    0.000    0.000    0.000    0.000 {method 'union' of 'frozenset' objects}
        4    0.000    0.000    0.000    0.000 {built-in method builtins.all}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:78(acquire)
        1    0.000    0.000    0.000    0.000 weakref.py:165(__setitem__)
        1    0.000    0.000    0.048    0.048 mendeleev.py:71(element)
        2    0.000    0.000    0.000    0.000 <string>:1(__new__)
        2    0.000    0.000    0.000    0.000 elements.py:879(anon_label)
        7    0.000    0.000    0.000    0.000 selectable.py:1202(<listcomp>)
       21    0.000    0.000    0.000    0.000 selectable.py:1376(_from_objects)
       29    0.000    0.000    0.000    0.000 selectable.py:1960(_from_objects)
        1    0.000    0.000    0.000    0.000 <string>:1(__init__)
        1    0.000    0.000    0.001    0.001 attr.py:281(_exec_once_impl)
        2    0.000    0.000    0.000    0.000 compiler.py:1012(visit_cast)
        1    0.000    0.000    0.000    0.000 url.py:152(_instantiate_plugins)
        1    0.000    0.000    0.000    0.000 base.py:240(_should_wrap_creator)
        1    0.000    0.000    0.001    0.001 base.py:757(_checkout)
        1    0.000    0.000    0.000    0.000 tables.py:301(init_on_load)
        1    0.000    0.000    0.000    0.000 mapper.py:3343(_event_on_load)
        7    0.000    0.000    0.000    0.000 query.py:1405(_set_enable_single_crit)
        7    0.000    0.000    0.000    0.000 relationships.py:982(_source_selectable)
        8    0.000    0.000    0.000    0.000 session.py:1574(_autoflush)
        2    0.000    0.000    0.000    0.000 base.py:969(visit_cast)
        9    0.000    0.000    0.000    0.000 {method 'release' of '_thread.lock' objects}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:103(release)
        1    0.000    0.000    0.000    0.000 posixpath.py:75(join)
        1    0.000    0.000    0.000    0.000 re.py:185(sub)
        3    0.000    0.000    0.000    0.000 __init__.py:212(_acquireLock)
        1    0.000    0.000    0.001    0.001 mendeleev.py:53(get_engine)
        7    0.000    0.000    0.000    0.000 _collections.py:886(_inc_counter)
       14    0.000    0.000    0.000    0.000 elements.py:220(_constructor)
       15    0.000    0.000    0.000    0.000 selectable.py:143(selectable)
        7    0.000    0.000    0.000    0.000 elements.py:4013(_key_label)
        1    0.000    0.000    0.000    0.000 elements.py:4067(_bind_param)
       25    0.000    0.000    0.000    0.000 type_api.py:279(result_processor)
        7    0.000    0.000    0.000    0.000 selectable.py:3067(<listcomp>)
        5    0.000    0.000    0.000    0.000 registry.py:165(_key)
        4    0.000    0.000    0.000    0.000 sqltypes.py:1727(__init__)
        1    0.000    0.000    0.000    0.000 strategies.py:106(connect)
        1    0.000    0.000    0.001    0.001 base.py:2236(_contextual_connect)
        1    0.000    0.000    0.000    0.000 compiler.py:3420(__init__)
        8    0.000    0.000    0.000    0.000 default.py:1032(_use_server_side_cursor)
       15    0.000    0.000    0.000    0.000 query.py:371(_query_entity_zero)
        2    0.000    0.000    0.000    0.000 strategies.py:1392(_create_scalar_loader)
        1    0.000    0.000    0.000    0.000 econf.py:67(__init__)
       10    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 {method 'format' of 'str' objects}
        8    0.000    0.000    0.000    0.000 {built-in method posix.fspath}
        7    0.000    0.000    0.000    0.000 {method 'popleft' of 'collections.deque' objects}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:58(__init__)
        2    0.000    0.000    0.000    0.000 weakref.py:358(remove)
        3    0.000    0.000    0.000    0.000 __init__.py:1930(getLogger)
        1    0.000    0.000    0.001    0.001 langhelpers.py:1478(go)
        7    0.000    0.000    0.000    0.000 elements.py:373(self_group)
        7    0.000    0.000    0.000    0.000 elements.py:4024(_render_label_in_columns_clause)
        1    0.000    0.000    0.000    0.000 type_api.py:544(coerce_compared_value)
        8    0.000    0.000    0.000    0.000 base.py:225(<genexpr>)
        1    0.000    0.000    0.001    0.001 attr.py:301(exec_once_unless_exception)
        1    0.000    0.000    0.000    0.000 base.py:1745(__init__)
        2    0.000    0.000    0.000    0.000 compiler.py:892(visit_typeclause)
        7    0.000    0.000    0.000    0.000 compiler.py:1770(get_render_as_alias_suffix)
        1    0.000    0.000    0.000    0.000 url.py:161(_get_entrypoint)
       14    0.000    0.000    0.000    0.000 mapper.py:740(entity)
        2    0.000    0.000    0.000    0.000 attributes.py:778(set_committed_value)
        7    0.000    0.000    0.000    0.000 path_registry.py:91(<listcomp>)
        1    0.000    0.000    0.000    0.000 properties.py:314(operate)
        1    0.000    0.000    0.000    0.000 query.py:1738(filter)
        1    0.000    0.000    0.000    0.000 tables.py:507(electronegativity)
       28    0.000    0.000    0.000    0.000 econf.py:106(shellre)
        8    0.000    0.000    0.000    0.000 {method 'keys' of 'dict' objects}
        9    0.000    0.000    0.000    0.000 {built-in method builtins.next}
        6    0.000    0.000    0.000    0.000 {built-in method _imp.release_lock}
        1    0.000    0.000    0.000    0.000 {method 'groupdict' of 're.Match' objects}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:176(cb)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:369(__init__)
        4    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:855(__enter__)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:873(_find_spec_legacy)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:1009(_handle_fromlist)
        1    0.000    0.000    0.000    0.000 codecs.py:945(getencoder)
        3    0.000    0.000    0.000    0.000 re.py:232(compile)
        1    0.000    0.000    0.000    0.000 weakref.py:341(__init__)
        3    0.000    0.000    0.000    0.000 __init__.py:221(_releaseLock)
        3    0.000    0.000    0.000    0.000 {method 'fetchone' of 'sqlite3.Cursor' objects}
       11    0.000    0.000    0.000    0.000 {method 'close' of 'sqlite3.Cursor' objects}
        1    0.000    0.000    0.000    0.000 mendeleev.py:46(get_package_dbpath)
        1    0.000    0.000    0.000    0.000 langhelpers.py:220(load)
        1    0.000    0.000    0.000    0.000 langhelpers.py:1353(parse_user_argument)
        7    0.000    0.000    0.000    0.000 elements.py:359(get_children)
        2    0.000    0.000    0.000    0.000 elements.py:2367(literal_column)
        2    0.000    0.000    0.000    0.000 elements.py:2492(_from_objects)
        2    0.000    0.000    0.000    0.000 <string>:1(cast)
        1    0.000    0.000    0.000    0.000 base.py:123(_join)
        4    0.000    0.000    0.000    0.000 sqltypes.py:1809(result_processor)
        1    0.000    0.000    0.000    0.000 processors.py:151(to_unicode_processor_factory)
        1    0.000    0.000    0.000    0.000 default.py:273(_type_memos)
        1    0.000    0.000    0.000    0.000 default.py:480(connect)
        7    0.000    0.000    0.000    0.000 base.py:370(connection)
        1    0.000    0.000    0.000    0.000 base.py:713(_begin_impl)
       10    0.000    0.000    0.000    0.000 compiler.py:352(__str__)
        2    0.000    0.000    0.000    0.000 compiler.py:399(process)
        2    0.000    0.000    0.000    0.000 compiler.py:3299(_render_string_type)
        7    0.000    0.000    0.000    0.000 compiler.py:3638(format_alias)
        1    0.000    0.000    0.000    0.000 log.py:56(_should_log_debug)
        1    0.000    0.000    0.000    0.000 base.py:235(_creator)
        1    0.000    0.000    0.001    0.001 base.py:354(connect)
        1    0.000    0.000    0.001    0.001 base.py:434(__init__)
        1    0.000    0.000    0.000    0.000 base.py:589(get_connection)
        1    0.000    0.000    0.001    0.001 default.py:407(<setcomp>)
        1    0.000    0.000    0.000    0.000 default.py:529(do_rollback)
        1    0.000    0.000    0.000    0.000 attributes.py:216(operate)
        7    0.000    0.000    0.000    0.000 path_registry.py:97(contains)
        5    0.000    0.000    0.000    0.000 instrumentation.py:331(get_impl)
        7    0.000    0.000    0.000    0.000 query.py:674(enable_eagerloads)
        7    0.000    0.000    0.000    0.000 query.py:701(with_labels)
        1    0.000    0.000    0.046    0.046 query.py:3281(one)
        7    0.000    0.000    0.000    0.000 query.py:4162(type)
       15    0.000    0.000    0.000    0.000 query.py:4727(<genexpr>)
        1    0.000    0.000    0.000    0.000 session.py:884(begin)
        1    0.000    0.000    0.000    0.000 session.py:2436(flush)
        1    0.000    0.000    0.000    0.000 identity.py:17(__init__)
        7    0.000    0.000    0.000    0.000 strategies.py:1131(<listcomp>)
        5    0.000    0.000    0.000    0.000 strategies.py:1374(<listcomp>)
        1    0.000    0.000    0.000    0.000 pysqlite.py:382(__init__)
        1    0.000    0.000    0.000    0.000 econf.py:98(atomre)
        1    0.000    0.000    0.000    0.000 econf.py:137(<listcomp>)
        4    0.000    0.000    0.000    0.000 {built-in method builtins.issubclass}
       17    0.000    0.000    0.000    0.000 {built-in method builtins.iter}
        1    0.000    0.000    0.000    0.000 {built-in method _imp.is_builtin}
        1    0.000    0.000    0.000    0.000 {built-in method _codecs.lookup}
        5    0.000    0.000    0.000    0.000 {method 'append' of 'collections.deque' objects}
        3    0.000    0.000    0.000    0.000 {method 'acquire' of '_thread.RLock' objects}
       13    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:36(_relax_case)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:147(__enter__)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:719(find_spec)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:792(find_spec)
        4    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:859(__exit__)
        1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap_external>:1272(find_spec)
        4    0.000    0.000    0.000    0.000 posixpath.py:41(_get_sep)
        1    0.000    0.000    0.000    0.000 inspect.py:276(isbuiltin)
        1    0.000    0.000    0.000    0.000 _collections.py:140(__new__)
        1    0.000    0.000    0.000    0.000 langhelpers.py:316(get_func_kwargs)
        1    0.000    0.000    0.000    0.000 langhelpers.py:327(get_callable_argspec)
        6    0.000    0.000    0.000    0.000 langhelpers.py:1119(coerce_kw_type)
        7    0.000    0.000    0.000    0.000 elements.py:346(_copy_internals)
        2    0.000    0.000    0.000    0.000 elements.py:1292(__init__)
        2    0.000    0.000    0.000    0.000 selectable.py:3726(<listcomp>)
        1    0.000    0.000    0.000    0.000 base.py:261(__init__)
        1    0.000    0.000    0.000    0.000 attr.py:278(_memoized_attr__exec_once_mutex)
        1    0.000    0.000    0.000    0.000 base.py:596(begin)
        1    0.000    0.000    0.000    0.000 base.py:1682(__init__)
        1    0.000    0.000    0.000    0.000 url.py:56(__init__)
        1    0.000    0.000    0.000    0.000 compiler.py:396(__init__)
        2    0.000    0.000    0.000    0.000 compiler.py:901(escape_literal_column)
        2    0.000    0.000    0.000    0.000 compiler.py:3314(visit_VARCHAR)
        2    0.000    0.000    0.000    0.000 log.py:59(_should_log_info)
        1    0.000    0.000    0.000    0.000 url.py:221(make_url)
        1    0.000    0.000    0.000    0.000 base.py:724(__init__)
        1    0.000    0.000    0.001    0.001 impl.py:237(_do_get)
        8    0.000    0.000    0.000    0.000 default.py:1075(pre_exec)
        8    0.000    0.000    0.000    0.000 default.py:1078(post_exec)
        1    0.000    0.000    0.025    0.025 loading.py:85(<listcomp>)
        1    0.000    0.000    0.000    0.000 <string>:1(filter)
        1    0.000    0.000    0.000    0.000 pysqlite.py:408(get_pool_class)
        1    0.000    0.000    0.000    0.000 econf.py:111(shellre)
        1    0.000    0.000    0.000    0.000 econf.py:139(<listcomp>)
        2    0.000    0.000    0.000    0.000 {method 'items' of 'collections.OrderedDict' objects}
        7    0.000    0.000    0.000    0.000 {method 'difference_update' of 'set' objects}
       14    0.000    0.000    0.000    0.000 {method 'rpartition' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
        6    0.000    0.000    0.000    0.000 {built-in method _imp.acquire_lock}
        1    0.000    0.000    0.000    0.000 {built-in method _imp.is_frozen}
        3    0.000    0.000    0.000    0.000 {built-in method _thread.allocate_lock}
        3    0.000    0.000    0.000    0.000 {method 'release' of '_thread.RLock' objects}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:151(__exit__)
        1    0.000    0.000    0.000    0.000 types.py:164(__get__)
        1    0.000    0.000    0.000    0.000 weakref.py:336(__new__)
        2    0.000    0.000    0.000    0.000 inspect.py:80(ismethod)
        3    0.000    0.000    0.000    0.000 inspect.py:158(isfunction)
        2    0.000    0.000    0.000    0.000 inspect.py:252(iscode)
        1    0.000    0.000    0.000    0.000 six.py:184(find_module)
        1    0.000    0.000    0.000    0.000 {method 'rollback' of 'sqlite3.Connection' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 langhelpers.py:1472(only_once)
        1    0.000    0.000    0.000    0.000 elements.py:4509(_expression_literal_as_text)
        1    0.000    0.000    0.000    0.000 type_api.py:357(_has_bind_expression)
        1    0.000    0.000    0.000    0.000 attr.py:330(__bool__)
        1    0.000    0.000    0.000    0.000 sqltypes.py:2863(_resolve_value_to_type)
        1    0.000    0.000    0.001    0.001 base.py:2272(_wrap_pool_connect)
        1    0.000    0.000    0.000    0.000 interfaces.py:485(_get_default_schema_name)
        2    0.000    0.000    0.000    0.000 compiler.py:717(default_from)
        1    0.000    0.000    0.000    0.000 compiler.py:3371(visit_unicode)
        1    0.000    0.000    0.000    0.000 log.py:221(__set__)
        1    0.000    0.000    0.000    0.000 url.py:157(<listcomp>)
        1    0.000    0.000    0.000    0.000 base.py:231(_creator)
        1    0.000    0.000    0.001    0.001 base.py:305(_create_connection)
        1    0.000    0.000    0.000    0.000 default.py:526(do_begin)
        1    0.000    0.000    0.000    0.000 state.py:309(_pending_mutations)
        1    0.000    0.000    0.000    0.000 session.py:2482(_is_clean)
        1    0.000    0.000    0.000    0.000 identity.py:56(check_modified)
        7    0.000    0.000    0.000    0.000 strategies.py:1307(__init__)
        2    0.000    0.000    0.000    0.000 strategies.py:1397(<listcomp>)
        1    0.000    0.000    0.000    0.000 base.py:1534(on_connect)
        1    0.000    0.000    0.000    0.000 pysqlite.py:415(_get_server_version_info)
        8    0.000    0.000    0.000    0.000 {method 'setdefault' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {method 'rfind' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {method 'strip' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {built-in method time.time}
        2    0.000    0.000    0.000    0.000 {built-in method _thread.get_ident}
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:143(__init__)
        1    0.000    0.000    0.000    0.000 enum.py:628(value)
        1    0.000    0.000    0.000    0.000 _collections.py:145(__init__)
        8    0.000    0.000    0.000    0.000 _collections.py:151(union)
        2    0.000    0.000    0.000    0.000 elements.py:4606(_literal_as_binds)
        1    0.000    0.000    0.000    0.000 sqltypes.py:256(bind_processor)
        1    0.000    0.000    0.000    0.000 attr.py:365(for_modify)
        1    0.000    0.000    0.000    0.000 events.py:328(_accept_with)
        1    0.000    0.000    0.000    0.000 interfaces.py:780(get_dialect_cls)
        1    0.000    0.000    0.000    0.000 interfaces.py:796(engine_created)
        1    0.000    0.000    0.000    0.000 url.py:129(password)
        1    0.000    0.000    0.000    0.000 default.py:347(_check_max_identifier_length)
        1    0.000    0.000    0.000    0.000 __init__.py:52(<lambda>)
        1    0.000    0.000    0.000    0.000 session.py:306(_is_transaction_boundary)
        2    0.000    0.000    0.000    0.000 econf.py:93(atomre)
lmmentel commented 5 years ago

Thanks for reporting Simon!

I really appreciate the feedback and I have to be honest that I haven't looked at optimizing the performance of mendeelev beyond good practices. I would really appreciate if you would describe your use case and potential requirements so I could look into it.

A few thoughts about the example you posted. When retrieving the electronegativity using mendeleev.element('Au').electronegativity(scale='pauling') most of the time is spend fetching and instantiating the Element object, namely executing mendeleev.element('Au') and then it's just an class attribute lookup to get the electronegativity value/

Consider

%timeit mendeleev.element('Au')
15.8 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

vs

%timeit mendeleev.element('Au').electronegativity(scale='pauling')
15.2 ms ± 161 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

where there is no practical difference.

If you would like squeeze some more performance out of this code I would encourage you to limit the db io, and read the data on relevant element once and then retrieve from memory when needed. Your example with reading the relevant data into a dict seems to be doing a great job.

If you would like to have more alternatives mendeleev currently exposes a few different ways of accessing data and some of those are documented here. As you will find you can fetch the elements by their symbols and then access their properties quite quickly:

from mendeleev import Au

%timeit Au.en_pauling
302 ns ± 3.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

If it is more convenient for you to operate on collections of elements and properties, there is a get_neutral_data function in the utils module here that fetches a lot of data from multiple tables and returns a pandas DataFrame. Once you create a data frame you can access the individual values performantly:

from mendeleev.utils import get_neutral_data
data = get_neutral_data()
data = data.set_index('symbol')

%timeit data.loc['Au', 'en_pauling']
4.75 µs ± 23.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

you can also then access arrays of properties by querying whole columns.

Let me know if that helps or you have some other suggestions?