Skip to content

Commit

Permalink
Make sorting faster
Browse files Browse the repository at this point in the history
  • Loading branch information
probablykasper committed Oct 5, 2024
1 parent ad9dd9f commit 5151c35
Showing 1 changed file with 39 additions and 33 deletions.
72 changes: 39 additions & 33 deletions src-native/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,84 +86,90 @@ fn get_field_bool(track: &Track, sort_key: &str) -> Option<bool> {
}
}

struct SortItem<'a> {
item_id: ItemId,
track: &'a Track,
}

pub fn sort(options: TracksPageOptions, library: &Library) -> Result<Vec<ItemId>> {
let now = Instant::now();

let id_map = TRACK_ID_MAP.read().unwrap();
let tracks = library.get_tracks();

let mut item_ids = get_tracklist_item_ids(library, &options.playlist_id)?;
let item_count = item_ids.len();
let mut items: Vec<_> = get_tracklist_item_ids(library, &options.playlist_id)?
.into_iter()
.map(|id| SortItem {
item_id: id,
track: tracks
.get(&id_map[id as usize])
.expect("Track ID non-existant"),
})
.collect();
let item_count = items.len();

if options.sort_key == "index" {
// Note: Indexes descend from "first to last", unlike
// other numbers which ascend from "high to low"
if !options.sort_desc {
item_ids.reverse();
items.reverse();
}
println!("Sort: {}ms", now.elapsed().as_millis());
println!("Sort: {:.3}ms", now.elapsed().as_secs_f32() * 1000.0);
let item_ids = items.into_iter().map(|item| item.item_id).collect();
return Ok(item_ids);
}

let tracks = library.get_tracks();
let field = get_track_field_type(&options.sort_key)?;
let group_album_tracks = options.group_album_tracks
&& match options.sort_key.as_str() {
"dateAdded" | "albumName" | "comments" | "genre" | "year" | "artist" => true,
_ => false,
};
item_ids.sort_by(|&id_a, &id_b| {
let track_id_a = &id_map[id_a as usize];
let track_id_b = &id_map[id_b as usize];
let track_a = tracks.get(track_id_a).expect("Track ID non-existant (1)");
let track_b = tracks.get(track_id_b).expect("Track ID non-existant (2)");
compare_track_field(track_a, track_b, &options.sort_key, &field)
items.sort_by(|a, b| {
return compare_track_field(a.track, b.track, &options.sort_key, &field);
});

if options.sort_desc {
item_ids.reverse();
items.reverse();
}

if group_album_tracks {
let mut grouped_track_ids: Vec<ItemId> = Vec::with_capacity(item_ids.len());
let mut item_ids_iter = item_ids.into_iter().peekable();
let mut post_grouped_items: Vec<_> = Vec::with_capacity(items.len());
let mut items_iter = items.into_iter().peekable();

// Process the first track in the next album
while let Some(first_item_id) = item_ids_iter.next() {
while let Some(first_item) = items_iter.next() {
let first_track = first_item.track;
// We need to get the first track to compare with the later tracks
let first_track_id = &id_map[first_item_id as usize];
let first_track = tracks.get(first_track_id).unwrap();
let mut current_album_buffer: Vec<ItemId> = vec![first_item_id];
let mut current_album_buffer: Vec<SortItem> = vec![first_item];

// Collect the rest of the tracks from the same album
while let Some(item_id) = item_ids_iter.peek() {
let track_id = &id_map[*item_id as usize];
let track = tracks.get(track_id).unwrap();
if !track.is_same_album(first_track) {
while let Some(item) = items_iter.peek() {
if !item.track.is_same_album(first_track) {
break;
}
current_album_buffer.push(*item_id);
item_ids_iter.next();
let item = items_iter.next().unwrap();
current_album_buffer.push(item);
}

// Sort album tracks by discNum, then trackNum
current_album_buffer.sort_by(|&id_a, &id_b| {
let track_a = tracks.get(&id_map[id_a as usize]).unwrap();
let track_b = tracks.get(&id_map[id_b as usize]).unwrap();
let mut order = compare_track_field(track_a, track_b, "discNum", &TrackField::U32);
current_album_buffer.sort_by(|a, b| {
let mut order = compare_track_field(a.track, b.track, "discNum", &TrackField::U32);
if order == Ordering::Equal {
order = compare_track_field(track_a, track_b, "trackNum", &TrackField::U32);
order = compare_track_field(a.track, b.track, "trackNum", &TrackField::U32);
}
order
});

grouped_track_ids.append(&mut current_album_buffer);
post_grouped_items.append(&mut current_album_buffer);
}

assert_eq!(item_count, grouped_track_ids.len());
item_ids = grouped_track_ids;
assert_eq!(item_count, post_grouped_items.len());
items = post_grouped_items;
}

println!("Sort group: {}ms", now.elapsed().as_millis());
println!("Sort: {}ms", now.elapsed().as_millis());
let item_ids = items.into_iter().map(|item| item.item_id).collect();
return Ok(item_ids);
}

Expand Down

0 comments on commit 5151c35

Please sign in to comment.