spotify: Reuse artist, album, and track models

This adds a module-level cache of artist, album, and track models, whose
content is almost entirely static. This cache is used when we convert from
pyspotify to Mopidy objects.

Previously, an album with 15 tracks would create 15 track objects, 15 artists
objects on the tracks, 15 album objects on the tracks, and 15 artist objects on
the 15 album objects, in total 60 objects. With this change, we only create 15
track objects, 1 album object, and 1 artist object, in total 17 objects.

Measurements with 90 playlists containing about 6500 tracks in total shows that
this reduces the number of Artist objects from 13600 to 3800, and the number of
Album objects from 6500 to 4500 objects.

An unscientific measurement of memory usage using ps(1) indicated a reduction
in RSS from 71MB to 65MB, measured right after the Spotify playlists was loaded
the first time.
This commit is contained in:
Stein Magnus Jodal 2012-11-23 12:48:41 +01:00
parent ec639d17ae
commit 6403e3e3d1

View File

@ -6,32 +6,45 @@ from mopidy import settings
from mopidy.models import Artist, Album, Track, Playlist
artist_cache = {}
album_cache = {}
track_cache = {}
def to_mopidy_artist(spotify_artist):
if spotify_artist is None:
return
uri = str(Link.from_artist(spotify_artist))
if uri in artist_cache:
return artist_cache[uri]
if not spotify_artist.is_loaded():
return Artist(uri=uri, name='[loading...]')
return Artist(uri=uri, name=spotify_artist.name())
artist_cache[uri] = Artist(uri=uri, name=spotify_artist.name())
return artist_cache[uri]
def to_mopidy_album(spotify_album):
if spotify_album is None:
return
uri = str(Link.from_album(spotify_album))
if uri in album_cache:
return album_cache[uri]
if not spotify_album.is_loaded():
return Album(uri=uri, name='[loading...]')
return Album(
album_cache[uri] = Album(
uri=uri,
name=spotify_album.name(),
artists=[to_mopidy_artist(spotify_album.artist())],
date=spotify_album.year())
return album_cache[uri]
def to_mopidy_track(spotify_track):
if spotify_track is None:
return
uri = str(Link.from_track(spotify_track, 0))
if uri in track_cache:
return track_cache[uri]
if not spotify_track.is_loaded():
return Track(uri=uri, name='[loading...]')
spotify_album = spotify_track.album()
@ -39,7 +52,7 @@ def to_mopidy_track(spotify_track):
date = spotify_album.year()
else:
date = None
return Track(
track_cache[uri] = Track(
uri=uri,
name=spotify_track.name(),
artists=[to_mopidy_artist(a) for a in spotify_track.artists()],
@ -48,6 +61,7 @@ def to_mopidy_track(spotify_track):
date=date,
length=spotify_track.duration(),
bitrate=settings.SPOTIFY_BITRATE)
return track_cache[uri]
def to_mopidy_playlist(spotify_playlist):