#1012 closed enhancement (not a bug)
Methods for fast automatic object deletion
Reported by: | Tristan Croll | Owned by: | pett |
---|---|---|---|
Priority: | moderate | Milestone: | |
Component: | Performance | Version: | |
Keywords: | Cc: | Tom Goddard | |
Blocked By: | Blocking: | ||
Notify when closed: | Platform: | all | |
Project: | ChimeraX |
Description
I have a working C++ dihedral implementation along with a manager that grows and shrinks as needed - either creating the dihedral objects all at once or just on demand, and deleting them when atoms/residues are deleted. Everything's fast, other than deletion. For example, for an 11,850 residue structure, the below test script gives:
Finding 58230 dihedrals for 11850 residues took 0.21404 seconds
Retrieving all 11800 omega dihedrals took 0.00186 seconds
Getting all dihedral angles for 11800 dihedrals took 0.00494 seconds
Deleting 11892 atoms in 748 residues took 6.56996 seconds
If I understand correctly, the reason for the slow deletion speed (~O(N2) in model size) is that my Proper_Dihedral_Mgr
is a DestructionObserver
(looking for deleted Atom
and Residue
instances and deleting Proper_Dihedral
instances and mappings accordingly) - but the Proper_Dihedral
deletions themselves create new DestructionUser
instances. So everything gets a bit circular, and there's a lot of spinning of wheels until it sorts itself out.
It's not particularly urgent (only becomes problematic for large structures, when deleting large numbers of atoms at once), but it would be nice to find a way to improve on this. I'd like to suggest a minor modification to the destruction framework. What if, instead of DestructionCoordinator
storing the destroyed pointers as std::set<void*>
, it stored them as std::unordered_map<std::type_index, std::set<void*> >
with the key being the original type of the destroyed pointers? Then each DestructionObserver
could quickly determine if any of the destroyed pointers are of interest without having to loop through all of them.
from chimerax.core.atomic import AtomicStructure m = session.models.list(type=AtomicStructure)[0] r = m.residues from chimerax.isolde import molobject, molarray dm = molobject.Proper_Dihedral_Mgr(session) from time import time start_time = time() dm.find_dihedrals(m) print ('Finding {} dihedrals for {} residues took {:.5f} seconds'.format(len(dm), len(r), time()-start_time)) start_time = time() omegas = dm.get_dihedrals(r, 'omega') print('Retrieving all {} omega dihedrals took {:.5f} seconds'.format(len(omegas), time()-start_time)) start_time = time() angles = omegas.angles print('Getting all dihedral angles for {} dihedrals took {:.5f} seconds'.format(len(omegas), time()-start_time)) chain_a = m.atoms[m.atoms.chain_ids == 'A'] n_atoms = len(chain_a) n_res = len(chain_a.unique_residues) start_time = time() chain_a.delete() print('Deleting {} atoms in {} residues took {:.5f} seconds'.format(n_atoms, n_res, time()-start_time))
Change History (4)
follow-up: 2 comment:2 by , 8 years ago
Ah! Never mind. I just discovered how DestructionBatcher works. Finding 1551264 dihedrals for 313236 residues took 10.19984 seconds Retrieving all 311880 omega dihedrals took 0.12412 seconds Getting all dihedral angles for 311880 dihedrals took 0.10229 seconds Deleting 1800 atoms in 231 residues took 0.86846 seconds On 2018-01-23 10:21, ChimeraX wrote:
comment:3 by , 8 years ago
Resolution: | → not a bug |
---|---|
Status: | assigned → closed |
Yes, as you discovered, DestructionBatcher prevents individual callbacks for each destruction when many are occurring. Makes a difference. :-)
comment:4 by , 8 years ago
Component: | Unassigned → Performance |
---|