mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Use fsrs batched function
This commit is contained in:
parent
e7e27825b6
commit
dda1324872
3 changed files with 62 additions and 30 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -2233,9 +2233,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsrs"
|
name = "fsrs"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/open-spaced-repetition/fsrs-rs.git#1e271981367454468391f1c686af03a0aa7aab3c"
|
||||||
checksum = "04954cc67c3c11ee342a2ee1f5222bf76d73f7772df08d37dc9a6cdd73c467eb"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"burn",
|
"burn",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
|
|
59
Cargo.toml
59
Cargo.toml
|
@ -33,8 +33,8 @@ git = "https://github.com/ankitects/linkcheck.git"
|
||||||
rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
|
rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
|
||||||
|
|
||||||
[workspace.dependencies.fsrs]
|
[workspace.dependencies.fsrs]
|
||||||
version = "5.1.0"
|
# version = "5.1.0"
|
||||||
# git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
|
git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
|
||||||
# path = "../open-spaced-repetition/fsrs-rs"
|
# path = "../open-spaced-repetition/fsrs-rs"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
@ -63,7 +63,10 @@ bitflags = "2.9.1"
|
||||||
blake3 = "1.8.2"
|
blake3 = "1.8.2"
|
||||||
bytes = "1.10.1"
|
bytes = "1.10.1"
|
||||||
camino = "1.1.10"
|
camino = "1.1.10"
|
||||||
chrono = { version = "0.4.41", default-features = false, features = ["std", "clock"] }
|
chrono = { version = "0.4.41", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
"clock",
|
||||||
|
] }
|
||||||
clap = { version = "4.5.40", features = ["derive"] }
|
clap = { version = "4.5.40", features = ["derive"] }
|
||||||
coarsetime = "0.1.36"
|
coarsetime = "0.1.36"
|
||||||
convert_case = "0.8.0"
|
convert_case = "0.8.0"
|
||||||
|
@ -107,12 +110,26 @@ prost-build = "0.13"
|
||||||
prost-reflect = "0.14.7"
|
prost-reflect = "0.14.7"
|
||||||
prost-types = "0.13"
|
prost-types = "0.13"
|
||||||
pulldown-cmark = "0.13.0"
|
pulldown-cmark = "0.13.0"
|
||||||
pyo3 = { version = "0.25.1", features = ["extension-module", "abi3", "abi3-py39"] }
|
pyo3 = { version = "0.25.1", features = [
|
||||||
|
"extension-module",
|
||||||
|
"abi3",
|
||||||
|
"abi3-py39",
|
||||||
|
] }
|
||||||
rand = "0.9.1"
|
rand = "0.9.1"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
reqwest = { version = "0.12.20", default-features = false, features = ["json", "socks", "stream", "multipart"] }
|
reqwest = { version = "0.12.20", default-features = false, features = [
|
||||||
rusqlite = { version = "0.36.0", features = ["trace", "functions", "collation", "bundled"] }
|
"json",
|
||||||
|
"socks",
|
||||||
|
"stream",
|
||||||
|
"multipart",
|
||||||
|
] }
|
||||||
|
rusqlite = { version = "0.36.0", features = [
|
||||||
|
"trace",
|
||||||
|
"functions",
|
||||||
|
"collation",
|
||||||
|
"bundled",
|
||||||
|
] }
|
||||||
rustls-pemfile = "2.2.0"
|
rustls-pemfile = "2.2.0"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
@ -128,10 +145,18 @@ syn = { version = "2.0.103", features = ["parsing", "printing"] }
|
||||||
tar = "0.4.44"
|
tar = "0.4.44"
|
||||||
tempfile = "3.20.0"
|
tempfile = "3.20.0"
|
||||||
termcolor = "1.4.1"
|
termcolor = "1.4.1"
|
||||||
tokio = { version = "1.45", features = ["fs", "rt-multi-thread", "macros", "signal"] }
|
tokio = { version = "1.45", features = [
|
||||||
|
"fs",
|
||||||
|
"rt-multi-thread",
|
||||||
|
"macros",
|
||||||
|
"signal",
|
||||||
|
] }
|
||||||
tokio-util = { version = "0.7.15", features = ["io"] }
|
tokio-util = { version = "0.7.15", features = ["io"] }
|
||||||
tower-http = { version = "0.6.6", features = ["trace"] }
|
tower-http = { version = "0.6.6", features = ["trace"] }
|
||||||
tracing = { version = "0.1.41", features = ["max_level_trace", "release_max_level_debug"] }
|
tracing = { version = "0.1.41", features = [
|
||||||
|
"max_level_trace",
|
||||||
|
"release_max_level_debug",
|
||||||
|
] }
|
||||||
tracing-appender = "0.2.3"
|
tracing-appender = "0.2.3"
|
||||||
tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter"] }
|
tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter"] }
|
||||||
unic-langid = { version = "0.9.6", features = ["macros"] }
|
unic-langid = { version = "0.9.6", features = ["macros"] }
|
||||||
|
@ -141,10 +166,24 @@ walkdir = "2.5.0"
|
||||||
which = "8.0.0"
|
which = "8.0.0"
|
||||||
widestring = "1.1.0"
|
widestring = "1.1.0"
|
||||||
winapi = { version = "0.3", features = ["wincon", "winreg"] }
|
winapi = { version = "0.3", features = ["wincon", "winreg"] }
|
||||||
windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Media_Core", "Foundation_Collections", "Storage_Streams", "Win32_System_Console", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_Foundation", "Win32_UI_Shell", "Wdk_System_SystemServices"] }
|
windows = { version = "0.61.3", features = [
|
||||||
|
"Media_SpeechSynthesis",
|
||||||
|
"Media_Core",
|
||||||
|
"Foundation_Collections",
|
||||||
|
"Storage_Streams",
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_System_Registry",
|
||||||
|
"Win32_System_SystemInformation",
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_UI_Shell",
|
||||||
|
"Wdk_System_SystemServices",
|
||||||
|
] }
|
||||||
wiremock = "0.6.3"
|
wiremock = "0.6.3"
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
zip = { version = "4.1.0", default-features = false, features = ["deflate", "time"] }
|
zip = { version = "4.1.0", default-features = false, features = [
|
||||||
|
"deflate",
|
||||||
|
"time",
|
||||||
|
] }
|
||||||
zstd = { version = "0.13.3", features = ["zstdmt"] }
|
zstd = { version = "0.13.3", features = ["zstdmt"] }
|
||||||
|
|
||||||
# Apply mild optimizations to our dependencies in dev mode, which among other things
|
# Apply mild optimizations to our dependencies in dev mode, which among other things
|
||||||
|
|
|
@ -10,8 +10,6 @@ use fsrs::FSRS;
|
||||||
use fsrs::FSRS5_DEFAULT_DECAY;
|
use fsrs::FSRS5_DEFAULT_DECAY;
|
||||||
use fsrs::FSRS6_DEFAULT_DECAY;
|
use fsrs::FSRS6_DEFAULT_DECAY;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rayon::iter::IntoParallelRefMutIterator as _;
|
|
||||||
use rayon::iter::ParallelIterator as _;
|
|
||||||
|
|
||||||
use super::params::ignore_revlogs_before_ms_from_config;
|
use super::params::ignore_revlogs_before_ms_from_config;
|
||||||
use super::rescheduler::Rescheduler;
|
use super::rescheduler::Rescheduler;
|
||||||
|
@ -113,7 +111,9 @@ impl Collection {
|
||||||
};
|
};
|
||||||
let preset_desired_retention = req.preset_desired_retention;
|
let preset_desired_retention = req.preset_desired_retention;
|
||||||
|
|
||||||
let mut to_update_memory_state = Vec::new();
|
let mut to_update = Vec::new();
|
||||||
|
let mut fsrs_items = Vec::new();
|
||||||
|
let mut starting_states = Vec::new();
|
||||||
for (idx, (card_id, item)) in items.into_iter().enumerate() {
|
for (idx, (card_id, item)) in items.into_iter().enumerate() {
|
||||||
progress.update(true, |state| state.current_cards = idx as u32 + 1)?;
|
progress.update(true, |state| state.current_cards = idx as u32 + 1)?;
|
||||||
let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?;
|
let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?;
|
||||||
|
@ -130,7 +130,9 @@ impl Collection {
|
||||||
card.desired_retention = Some(desired_retention);
|
card.desired_retention = Some(desired_retention);
|
||||||
card.decay = decay;
|
card.decay = decay;
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
to_update_memory_state.push((card, original, item));
|
to_update.push((card, original));
|
||||||
|
fsrs_items.push(item.item);
|
||||||
|
starting_states.push(item.starting_state);
|
||||||
} else {
|
} else {
|
||||||
// clear memory states if item is None
|
// clear memory states if item is None
|
||||||
card.memory_state = None;
|
card.memory_state = None;
|
||||||
|
@ -138,14 +140,11 @@ impl Collection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to_update_memory_state.par_iter_mut().try_for_each_with(
|
let memory_states = fsrs.memory_state_batch(fsrs_items, starting_states)?;
|
||||||
fsrs.clone(),
|
|
||||||
|fsrs, (card, _, item)| {
|
for ((mut card, original), memory_state) in to_update.into_iter().zip(memory_states) {
|
||||||
card.set_memory_state(fsrs, Some(item.clone()), historical_retention.unwrap())
|
card.memory_state = Some(memory_state.into());
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
for (mut card, original, _) in to_update_memory_state {
|
|
||||||
'reschedule_card: {
|
'reschedule_card: {
|
||||||
// if rescheduling
|
// if rescheduling
|
||||||
let Some(reviews) = &last_revlog_info else {
|
let Some(reviews) = &last_revlog_info else {
|
||||||
|
@ -159,11 +158,6 @@ impl Collection {
|
||||||
let Some(last_review) = &last_info.last_reviewed_at else {
|
let Some(last_review) = &last_info.last_reviewed_at else {
|
||||||
break 'reschedule_card;
|
break 'reschedule_card;
|
||||||
};
|
};
|
||||||
|
|
||||||
// and the card's not new
|
|
||||||
let Some(state) = &card.memory_state else {
|
|
||||||
break 'reschedule_card;
|
|
||||||
};
|
|
||||||
// or in (re)learning
|
// or in (re)learning
|
||||||
if card.ctype != CardType::Review {
|
if card.ctype != CardType::Review {
|
||||||
break 'reschedule_card;
|
break 'reschedule_card;
|
||||||
|
@ -177,7 +171,7 @@ impl Collection {
|
||||||
let days_elapsed = timing.next_day_at.elapsed_days_since(*last_review) as i32;
|
let days_elapsed = timing.next_day_at.elapsed_days_since(*last_review) as i32;
|
||||||
let original_interval = card.interval;
|
let original_interval = card.interval;
|
||||||
let interval = fsrs.next_interval(
|
let interval = fsrs.next_interval(
|
||||||
Some(state.stability),
|
Some(memory_state.stability),
|
||||||
card.desired_retention
|
card.desired_retention
|
||||||
.expect("We set desired retention above"),
|
.expect("We set desired retention above"),
|
||||||
0,
|
0,
|
||||||
|
|
Loading…
Reference in a new issue