Performance of __refresh_changed_tracks in playlist.py could be improved

Bug #492089 reported by Ralf Schmelter
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Exaile
Fix Released
Low
Ralf Schmelter
exaile (Ubuntu)
Fix Released
Undecided
Unassigned

Bug Description

The performance of the __refresh_changed_tracks in Playlist is not optimal when the playlist is large and the number of changed tracks is large too, since it is O(len(playlist) * len(tracks)). This could be improved by first storing the tracks in a dictionary addressed by the io location and doing just one check for each playlist item, if its location is in the dictionary.

The attached patch does exactly this (as the old code it removes each found track, which would be not suitable if the playlist can contain duplicate tracks).

The version used is trunk.

Revision history for this message
Ralf Schmelter (ralf-schmelter) wrote :
affects: ubuntu → exaile (Ubuntu)
Revision history for this message
reacocard (reacocard) wrote :

Does this patch handle the case where there are multiple instances of a single song in the playlist?

Changed in exaile:
status: New → Incomplete
Revision history for this message
Ralf Schmelter (ralf-schmelter) wrote :

No, but this patch would handle multiple instances of the same song.

Revision history for this message
reacocard (reacocard) wrote :

Hm, isn't rebuilding the dict like that expensive? I'd like to see some numbers on whether this actually improves performance at all - I didn't notice a change after I applied it, but then I have a pretty powerful processor.

Changed in exaile (Ubuntu):
status: New → Triaged
Revision history for this message
Ralf Schmelter (ralf-schmelter) wrote :

I've used the following scenario:
I have opened a playlist containing N tracks already. Then I've added a DAAP client with 500 and 5000 tracks (containing tracks not already in the playlist). These 500 or 5000 tracks end up in the call to __refresh_changed_tracks.

Here are some numbers (Core2 Quad, 2.4 GHz):

500 tracks:
N=2
old: 0.0015 sec
new: 0.0016 sec

N=10
old: 0.005 sec
new: 0.0017 sec

N=50
old: 0.027
new: 0.0021 sec

N=150
old: 0.081 sec
new: 0.0031 sec

N=500
old: 0.27 sec
new: 0.0067 sec

5000 tracks:
N=2:
old: 0.019 sec
new: 0.021 sec

N=10
old: 0.063 sec
new: 0.021 sec

N = 50
old: 0.341 sec
new: 0.021sec

N = 150
old: 1.25 sec
new: 0.023 sec

N = 500
old: 4,03 sec
new: 0.028 sec

Conclusions:
- the new code is as least as fast as the old one if the playlist contains at least 2 items
- creating the dictionary is linear in the number of tracks as expected
- if the playlist contains at least 50 item, the new code is more than an order of magnitude faster
- the speedup is only noticable if the number of tracks in the call is at least ~1000, but for lower numbers the new code is at least as fast as the old one

Revision history for this message
reacocard (reacocard) wrote :

Good enough for me. Patch committed trunk/2681.

Changed in exaile:
assignee: nobody → Ralf Schmelter (ralf-schmelter)
importance: Undecided → Low
milestone: none → 0.3.1
status: Incomplete → Fix Committed
reacocard (reacocard)
Changed in exaile:
status: Fix Committed → Fix Released
Changed in exaile (Ubuntu):
status: Triaged → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.