From b740be6554f7853e4444b011fd4fc700480dc0d4 Mon Sep 17 00:00:00 2001 From: RumovZ Date: Wed, 11 May 2022 10:59:49 +0200 Subject: [PATCH] Avoid creating CardGenContexts for every note This requires CardGenContext to be generic, so it works both with an owned and borrowed notetype. --- rslib/src/dbcheck.rs | 6 +++- rslib/src/import_export/text/import.rs | 19 +++++++----- rslib/src/notes/mod.rs | 10 +++---- rslib/src/notetype/cardgen.rs | 41 +++++++++++++++----------- rslib/src/notetype/notetypechange.rs | 2 +- 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/rslib/src/dbcheck.rs b/rslib/src/dbcheck.rs index e13c97b5e..e97814b1a 100644 --- a/rslib/src/dbcheck.rs +++ b/rslib/src/dbcheck.rs @@ -262,7 +262,11 @@ impl Collection { // write note, updating tags and generating missing cards let ctx = genctx.get_or_insert_with(|| { - CardGenContext::new(&nt, self.get_last_deck_added_to_for_notetype(nt.id), usn) + CardGenContext::new( + nt.as_ref(), + self.get_last_deck_added_to_for_notetype(nt.id), + usn, + ) }); self.update_note_inner_generating_cards( ctx, &mut note, &original, false, norm, true, diff --git a/rslib/src/import_export/text/import.rs b/rslib/src/import_export/text/import.rs index 47ac1391b..f17adfff8 100644 --- a/rslib/src/import_export/text/import.rs +++ b/rslib/src/import_export/text/import.rs @@ -32,6 +32,7 @@ struct Context<'a> { deck_ids: HashMap>, usn: Usn, normalize_notes: bool, + card_gen_ctxs: HashMap<(NotetypeId, DeckId), CardGenContext>>, //progress: IncrementableProgress, } @@ -52,6 +53,7 @@ impl<'a> Context<'a> { normalize_notes, notetypes, deck_ids, + card_gen_ctxs: HashMap::new(), }) } @@ -89,7 +91,7 @@ impl<'a> Context<'a> { for foreign in notes { if let Some(notetype) = self.notetype_for_note(&foreign)? { if let Some(deck_id) = self.deck_id_for_note(&foreign)? { - let log_note = self.import_foreign_note(foreign, ¬etype, deck_id)?; + let log_note = self.import_foreign_note(foreign, notetype, deck_id)?; log.new.push(log_note); } } @@ -100,12 +102,12 @@ impl<'a> Context<'a> { fn import_foreign_note( &mut self, foreign: ForeignNote, - notetype: &Notetype, + notetype: Arc, deck_id: DeckId, ) -> Result { let today = self.col.timing_today()?.days_elapsed; - let (mut note, mut cards) = foreign.into_native(notetype, deck_id, today); - self.import_note(&mut note, notetype)?; + let (mut note, mut cards) = foreign.into_native(¬etype, deck_id, today); + self.import_note(&mut note, ¬etype)?; self.import_cards(&mut cards, note.id)?; self.generate_missing_cards(notetype, deck_id, ¬e)?; Ok(note.into_log_note()) @@ -128,13 +130,16 @@ impl<'a> Context<'a> { fn generate_missing_cards( &mut self, - notetype: &Notetype, + notetype: Arc, deck_id: DeckId, note: &Note, ) -> Result<()> { - let card_gen_context = CardGenContext::new(notetype, Some(deck_id), self.usn); + let card_gen_context = self + .card_gen_ctxs + .entry((notetype.id, deck_id)) + .or_insert_with(|| CardGenContext::new(notetype, Some(deck_id), self.usn)); self.col - .generate_cards_for_existing_note(&card_gen_context, note) + .generate_cards_for_existing_note(card_gen_context, note) } } diff --git a/rslib/src/notes/mod.rs b/rslib/src/notes/mod.rs index ed8ec29fa..6a375f6ad 100644 --- a/rslib/src/notes/mod.rs +++ b/rslib/src/notes/mod.rs @@ -80,7 +80,7 @@ impl Collection { .get_notetype(note.notetype_id)? .ok_or_else(|| AnkiError::invalid_input("missing note type"))?; let last_deck = col.get_last_deck_added_to_for_notetype(note.notetype_id); - let ctx = CardGenContext::new(&nt, last_deck, col.usn()?); + let ctx = CardGenContext::new(nt.as_ref(), last_deck, col.usn()?); let norm = col.get_config_bool(BoolKey::NormalizeNoteText); col.add_note_inner(&ctx, note, did, norm) }) @@ -334,7 +334,7 @@ impl Collection { pub(crate) fn add_note_inner( &mut self, - ctx: &CardGenContext, + ctx: &CardGenContext<&Notetype>, note: &mut Note, did: DeckId, normalize_text: bool, @@ -397,7 +397,7 @@ impl Collection { .get_notetype(note.notetype_id)? .ok_or_else(|| AnkiError::invalid_input("missing note type"))?; let last_deck = self.get_last_deck_added_to_for_notetype(note.notetype_id); - let ctx = CardGenContext::new(&nt, last_deck, self.usn()?); + let ctx = CardGenContext::new(nt.as_ref(), last_deck, self.usn()?); let norm = self.get_config_bool(BoolKey::NormalizeNoteText); self.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm, true)?; Ok(()) @@ -405,7 +405,7 @@ impl Collection { pub(crate) fn update_note_inner_generating_cards( &mut self, - ctx: &CardGenContext, + ctx: &CardGenContext<&Notetype>, note: &mut Note, original: &Note, mark_note_modified: bool, @@ -508,7 +508,7 @@ impl Collection { if out.generate_cards { let ctx = genctx.get_or_insert_with(|| { CardGenContext::new( - &nt, + nt.as_ref(), self.get_last_deck_added_to_for_notetype(nt.id), usn, ) diff --git a/rslib/src/notetype/cardgen.rs b/rslib/src/notetype/cardgen.rs index cd264dfea..75dba064d 100644 --- a/rslib/src/notetype/cardgen.rs +++ b/rslib/src/notetype/cardgen.rs @@ -1,7 +1,10 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + ops::Deref, +}; use itertools::Itertools; use rand::{rngs::StdRng, Rng, SeedableRng}; @@ -38,9 +41,9 @@ pub(crate) struct SingleCardGenContext { /// Info required to determine which cards should be generated when note added/updated, /// and where they should be placed. -pub(crate) struct CardGenContext<'a> { +pub(crate) struct CardGenContext> { pub usn: Usn, - pub notetype: &'a Notetype, + pub notetype: N, /// The last deck that was added to with this note type pub last_deck: Option, cards: Vec, @@ -53,20 +56,21 @@ pub(crate) struct CardGenCache { deck_configs: HashMap, } -impl CardGenContext<'_> { - pub(crate) fn new(nt: &Notetype, last_deck: Option, usn: Usn) -> CardGenContext<'_> { +impl> CardGenContext { + pub(crate) fn new(nt: N, last_deck: Option, usn: Usn) -> CardGenContext { + let cards = nt + .templates + .iter() + .map(|tmpl| SingleCardGenContext { + template: tmpl.parsed_question(), + target_deck_id: tmpl.target_deck_id(), + }) + .collect(); CardGenContext { usn, last_deck, notetype: nt, - cards: nt - .templates - .iter() - .map(|tmpl| SingleCardGenContext { - template: tmpl.parsed_question(), - target_deck_id: tmpl.target_deck_id(), - }) - .collect(), + cards, } } @@ -209,7 +213,7 @@ pub(crate) fn extract_data_from_existing_cards( impl Collection { pub(crate) fn generate_cards_for_new_note( &mut self, - ctx: &CardGenContext, + ctx: &CardGenContext>, note: &Note, target_deck_id: DeckId, ) -> Result<()> { @@ -224,7 +228,7 @@ impl Collection { pub(crate) fn generate_cards_for_existing_note( &mut self, - ctx: &CardGenContext, + ctx: &CardGenContext>, note: &Note, ) -> Result<()> { let existing = self.storage.existing_cards_for_note(note.id)?; @@ -233,7 +237,7 @@ impl Collection { fn generate_cards_for_note( &mut self, - ctx: &CardGenContext, + ctx: &CardGenContext>, note: &Note, existing: &[AlreadyGeneratedCardInfo], target_deck_id: Option, @@ -246,7 +250,10 @@ impl Collection { self.add_generated_cards(note.id, &cards, target_deck_id, cache) } - pub(crate) fn generate_cards_for_notetype(&mut self, ctx: &CardGenContext) -> Result<()> { + pub(crate) fn generate_cards_for_notetype( + &mut self, + ctx: &CardGenContext>, + ) -> Result<()> { let existing_cards = self.storage.existing_cards_for_notetype(ctx.notetype.id)?; let by_note = group_generated_cards_by_note(existing_cards); let mut cache = CardGenCache::default(); diff --git a/rslib/src/notetype/notetypechange.rs b/rslib/src/notetype/notetypechange.rs index af13bf787..5d845a35a 100644 --- a/rslib/src/notetype/notetypechange.rs +++ b/rslib/src/notetype/notetypechange.rs @@ -255,7 +255,7 @@ impl Collection { .get_notetype(new_notetype_id)? .ok_or(AnkiError::NotFound)?; let last_deck = self.get_last_deck_added_to_for_notetype(notetype.id); - let ctx = CardGenContext::new(¬etype, last_deck, usn); + let ctx = CardGenContext::new(notetype.as_ref(), last_deck, usn); for nid in note_ids { let mut note = self.storage.get_note(*nid)?.ok_or(AnkiError::NotFound)?;