Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#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)

in reply to:  1 ; comment:1 by tic20@…, 8 years ago

Timings running the same script on 3j3q:

Finding 1551264 dihedrals for 313236 residues took 12.68152 seconds
Retrieving all 311880 omega dihedrals took 0.12949 seconds
Getting all dihedral angles for 311880 dihedrals took 0.11216 seconds
Deleting 1800 atoms in 231 residues took 279.71557 seconds

On 2018-01-23 09:52, ChimeraX wrote:

in reply to:  2 ; comment:2 by tic20@…, 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 pett, 8 years ago

Resolution: not a bug
Status: assignedclosed

Yes, as you discovered, DestructionBatcher prevents individual callbacks for each destruction when many are occurring. Makes a difference. :-)

comment:4 by pett, 8 years ago

Component: UnassignedPerformance
Note: See TracTickets for help on using tickets.