Friday, August 9, 2013

Week 8: Isolating similarity calculations

This week, I placed the similarity calculations in a separate class so that they could more easily be called from outside the SelectorLibraryTableModel. Initially, this change seemed to cause a unusually large performance hit, but I eventually realized that due to merging with master, the tracks were being dirtied in TrackDAO::getTrackFromDb and thus each one was being re-saved upon access. Resolving this caused average time for calculating similarity against 1458 tracks to jump back from 2800 ms to about 1100 ms.

Further improvement should still be possible, and in my search for places to optimize I tried using callgrind, but it was not particularly revealing (the biggest bottleneck seemed to be the database queries). I will try with the Google profiling tools to see if I can uncover anything else.

Right now, to add a new similarity function requires changes in the following places:

  • dlgprefselector.ui: add a new slider
  • dlgprefselector.cpp: hook up the slider signals/slots, and add a function to show the description
  • library/selector/selector_preferences.h: add a preference key for said slider
  • library/selector/selectorsimilarity.cpp: implement the actual comparison in the foreach loop of calculateSimilarities
I'll continue looking for ways to speed up the similarity calculation so that it is more responsive, and see if it might be worthwhile to further abstract out comparison functions from SelectorSimilarity to facilitate the addition of new ones.

I also plan to add a function to SelectorSimilarity to allow to fetch the top (or top N) matching tracks according to current preferences; this could then be fed into the Auto-DJ queue or a MIDI mapping with ease. This requires essentially the same filters as are used in SelectorLibraryTableModel, so now is a good time to think about cleaning up the generation of queries for key/BPM filter matching so that the same functions can be used in both classes.

No comments:

Post a Comment