def test_playlists_featuring_performance(s): """Basic performance tests for `playlists_featuring()` Initial tests indicate that: For 100,000 songs with 20 Playlists (each of 1000 songs): -> The cache is ~= 6MB in size, delivers a 250x speed increase once warm For 10,000 songs with 20 Playlists (each of 100 songs): -> The cache is ~= 770 KB in size, 6.4x speed increase once warm For 10,000 songs with 2 Playlists (each of 5000 songs) -> The cache is ~= 770 KB in size, 180x speed increase once warm TODO: Reporting, debugging. """ # Basic sizes NUM_PLAYLISTS = 10 NUM_SONGS = 10000 # Every nth song is playlisted SONGS_TO_PLAYLIST_SIZE_RATIO = 10 PLAYLISTS_PER_PLAYLISTED_SONG = 3 ARTISTS = ["Mr Foo", "Bar", "Miss T Fie", "Dr Death"] pls = [] library = [] def setup(): Playlist._remove_all() for i in xrange(NUM_PLAYLISTS): pls.append(Playlist(PLAYLISTS, "List %d" % (i+1))) for i in xrange(NUM_SONGS): a = ARTISTS[randint(0,2)] t = "Song %d" % i data = {"title": t, "artist":a, "~#tracknumber": i % 20, "~filename": "%s.mp3" % t, "~#filesize":randint(1000000,100000000)} song = Fakesong(data) library.append(song) if not (i % SONGS_TO_PLAYLIST_SIZE_RATIO): song["~included"] = "yes" for j in range(PLAYLISTS_PER_PLAYLISTED_SONG): pls[(i+j) % NUM_PLAYLISTS].append(song) print_d("\nSetting up %d songs and %d playlists... " % ( NUM_SONGS, NUM_PLAYLISTS)) print_d("took %.1f ms" % (timeit(setup, "pass", default_timer, 1)*1000.0)) def get_playlists(): for song in library: #song = library[randint(0,len(library)-1)] playlists = func(song) s.failUnlessEqual(len(playlists), PLAYLISTS_PER_PLAYLISTED_SONG if song("~included") else 0) # Spot sanity check # s.failUnless(song in list(playlists)[0]) REPEATS = 2 func = Playlist._uncached_playlists_featuring print_d("Using %d songs and %d playlists, with 1 in %d songs " "in %d playlist(s) => each playlist has %d songs. " % (NUM_SONGS, NUM_PLAYLISTS, SONGS_TO_PLAYLIST_SIZE_RATIO, PLAYLISTS_PER_PLAYLISTED_SONG, PLAYLISTS_PER_PLAYLISTED_SONG * NUM_SONGS / (SONGS_TO_PLAYLIST_SIZE_RATIO * NUM_PLAYLISTS))) print_d("Timing basic get_playlists_featuring()... ") duration = timeit(get_playlists, "pass", default_timer, REPEATS) print_d("averages %.1f ms" % (duration * 1000.0 / REPEATS)) # Now try caching version func = Playlist._cached_playlists_featuring print_d("Timing cached get_playlists_featuring()...") cold = timeit(get_playlists, "pass", default_timer, 1) # And now it's warmed up... print_d("cold: averages %.1f ms" % (cold* 1000.0)) warm = timeit(get_playlists, "pass", default_timer, REPEATS -1) print_d("warm: averages %.1f ms (speedup = %.1f X)" % (warm * 1000.0 / (REPEATS-1), cold/warm)) print_d("Cache hits = %d, misses = %d (%d%% hits). Size of cache=%.2f KB" % (Playlist._hits, Playlist._misses, Playlist._hits * 100 / (Playlist._misses + Playlist._hits), Playlist._get_cache_size()))