Skip to content

Commit

Permalink
change: Rust APIの脱Tokioを行い、モジュール名をtokio:nonblocking
Browse files Browse the repository at this point in the history
  • Loading branch information
qryxip committed Sep 12, 2024
1 parent e07c795 commit 35d2040
Show file tree
Hide file tree
Showing 19 changed files with 257 additions and 141 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ async-fs = "2.1.2"
async_zip = "=0.0.16"
bindgen = "0.69.4"
binstall-tar = "0.4.39"
blocking = "1.6.1"
bytes = "1.1.0"
camino = "1.1.6"
cargo_metadata = "0.18.1"
Expand Down Expand Up @@ -57,6 +58,7 @@ octocrab = { version = "0.19.0", default-features = false }
once_cell = "1.19.0"
ouroboros = "0.18.0"
parse-display = "0.8.2"
pollster = "0.3.0"
pretty_assertions = "1.3.0"
proc-macro2 = "1.0.69"
pyo3 = "0.20.3"
Expand Down
5 changes: 3 additions & 2 deletions crates/voicevox_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ link-onnxruntime = []
anyhow.workspace = true
async-fs.workspace = true
async_zip = { workspace = true, features = ["deflate"] }
blocking.workspace = true
camino.workspace = true
const_format.workspace = true
derive-getters.workspace = true
Expand All @@ -27,7 +28,7 @@ duplicate.workspace = true
easy-ext.workspace = true
educe.workspace = true
enum-map.workspace = true
fs-err = { workspace = true, features = ["tokio"] }
fs-err.workspace = true
futures-io.workspace = true
futures-lite.workspace = true
futures-util = { workspace = true, features = ["io"] }
Expand All @@ -46,14 +47,14 @@ smallvec.workspace = true
strum = { workspace = true, features = ["derive"] }
tempfile.workspace = true
thiserror.workspace = true
tokio = { workspace = true, features = ["rt"] } # FIXME: feature-gateする
tracing.workspace = true
uuid = { workspace = true, features = ["v4", "serde"] }
voicevox-ort = { workspace = true, features = ["download-binaries", "__init-for-voicevox"] }
voicevox_core_macros = { path = "../voicevox_core_macros" }

[dev-dependencies]
heck.workspace = true
pollster = { workspace = true, features = ["macro"] }
pretty_assertions.workspace = true
rstest.workspace = true
rstest_reuse.workspace = true
Expand Down
12 changes: 6 additions & 6 deletions crates/voicevox_core/src/__internal/doctest_fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ pub async fn synthesizer_with_sample_voice_model(
OsString,
>,
open_jtalk_dic_dir: impl AsRef<Utf8Path>,
) -> anyhow::Result<crate::tokio::Synthesizer<crate::tokio::OpenJtalk>> {
let syntesizer = crate::tokio::Synthesizer::new(
) -> anyhow::Result<crate::nonblocking::Synthesizer<crate::nonblocking::OpenJtalk>> {
let syntesizer = crate::nonblocking::Synthesizer::new(
#[cfg(feature = "load-onnxruntime")]
crate::tokio::Onnxruntime::load_once()
crate::nonblocking::Onnxruntime::load_once()
.filename(onnxruntime_dylib_path)
.exec()
.await?,
#[cfg(feature = "link-onnxruntime")]
crate::tokio::Onnxruntime::init_once().await?,
crate::tokio::OpenJtalk::new(open_jtalk_dic_dir).await?,
crate::nonblocking::Onnxruntime::init_once().await?,
crate::nonblocking::OpenJtalk::new(open_jtalk_dic_dir).await?,
&InitializeOptions {
acceleration_mode: AccelerationMode::Cpu,
..Default::default()
},
)?;

let model = &crate::tokio::VoiceModel::from_path(voice_model_path).await?;
let model = &crate::nonblocking::VoiceModel::from_path(voice_model_path).await?;
syntesizer.load_voice_model(model).await?;

Ok(syntesizer)
Expand Down
6 changes: 2 additions & 4 deletions crates/voicevox_core/src/asyncs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
//! に[`SingleTasked`]を用意している。
//!
//! [ブロッキング版API]: crate::blocking
//! [非同期版API]: crate::tokio
//! [blocking]: https://docs.rs/crate/blocking
//! [非同期版API]: crate::nonblocking
use std::{
io::{self, Read as _, Seek as _, SeekFrom},
Expand Down Expand Up @@ -71,8 +70,7 @@ impl Async for SingleTasked {
///
/// [非同期版API]用。
///
/// [blocking]: https://docs.rs/crate/blocking
/// [非同期版API]: crate::tokio
/// [非同期版API]: crate::nonblocking
pub(crate) enum BlockingThreadPool {}

impl Async for BlockingThreadPool {
Expand Down
4 changes: 2 additions & 2 deletions crates/voicevox_core/src/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ fn test_gpu(
/// しても`cuda`や`dml`は`true`を示しうる。
///
/// ```
/// # #[tokio::main]
/// # #[pollster::main]
/// # async fn main() -> anyhow::Result<()> {
/// use voicevox_core::{tokio::Onnxruntime, SupportedDevices};
/// use voicevox_core::{nonblocking::Onnxruntime, SupportedDevices};
///
/// # voicevox_core::blocking::Onnxruntime::load_once()
/// # .filename(if cfg!(windows) {
Expand Down
4 changes: 2 additions & 2 deletions crates/voicevox_core/src/engine/full_context_label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ mod tests {
#[apply(label_cases)]
#[tokio::test]
async fn open_jtalk(text: &str, labels: &[&str], _accent_phrase: &[AccentPhrase]) {
let open_jtalk = crate::tokio::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
let open_jtalk = crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
assert_eq!(&open_jtalk.extract_fullcontext(text).unwrap(), labels);
Expand All @@ -447,7 +447,7 @@ mod tests {
#[apply(label_cases)]
#[tokio::test]
async fn extract_fullcontext(text: &str, _labels: &[&str], accent_phrase: &[AccentPhrase]) {
let open_jtalk = crate::tokio::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
let open_jtalk = crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
assert_eq!(
Expand Down
28 changes: 24 additions & 4 deletions crates/voicevox_core/src/engine/open_jtalk.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
// TODO: `VoiceModel`のように、次のような設計にする。
//
// ```
// pub(crate) mod blocking {
// pub struct OpenJtalk(Inner<SingleTasked>);
// // …
// }
// pub(crate) mod nonblocking {
// pub struct OpenJtalk(Inner<BlockingThreadPool>);
// // …
// }
// ```

use ::open_jtalk::Text2MecabError;

#[derive(thiserror::Error, Debug)]
Expand Down Expand Up @@ -183,12 +196,19 @@ pub(crate) mod blocking {
}
}

pub(crate) mod tokio {
pub(crate) mod nonblocking {
use camino::Utf8Path;

use super::FullcontextExtractor;

/// テキスト解析器としてのOpen JTalk。
///
/// # Performance
///
/// [blocking]クレートにより動いている。詳しくは[`nonblocking`モジュールのドキュメント]を参照。
///
/// [blocking]: https://docs.rs/crate/blocking
/// [`nonblocking`モジュールのドキュメント]: crate::nonblocking
#[derive(Clone)]
pub struct OpenJtalk(super::blocking::OpenJtalk);

Expand All @@ -206,7 +226,7 @@ pub(crate) mod tokio {
/// この関数を呼び出した後にユーザー辞書を変更した場合は、再度この関数を呼ぶ必要がある。
pub async fn use_user_dict(
&self,
user_dict: &crate::tokio::UserDict,
user_dict: &crate::nonblocking::UserDict,
) -> crate::result::Result<()> {
let inner = self.0 .0.clone();
let words = user_dict.to_mecab_format();
Expand Down Expand Up @@ -325,7 +345,7 @@ mod tests {
#[case] text: &str,
#[case] expected: anyhow::Result<Vec<String>>,
) {
let open_jtalk = super::tokio::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
let open_jtalk = super::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
let result = open_jtalk.extract_fullcontext(text);
Expand All @@ -339,7 +359,7 @@ mod tests {
#[case] text: &str,
#[case] expected: anyhow::Result<Vec<String>>,
) {
let open_jtalk = super::tokio::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
let open_jtalk = super::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
for _ in 0..10 {
Expand Down
38 changes: 28 additions & 10 deletions crates/voicevox_core/src/infer/runtimes/onnxruntime.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
// TODO: `VoiceModel`のように、次のような設計にする。
//
// ```
// pub(crate) mod blocking {
// pub struct Onnxruntime(Inner<SingleTasked>);
// // …
// }
// pub(crate) mod nonblocking {
// pub struct Onnxruntime(Inner<BlockingThreadPool>);
// // …
// }
// ```

use std::{fmt::Debug, vec};

use anyhow::{anyhow, bail, ensure};
Expand All @@ -18,9 +31,6 @@ use super::super::{
OutputScalarKind, OutputTensor, ParamInfo, PushInputTensor,
};

// TODO: `trait AsyncRuntime`みたいなものを作って抽象化しながら同期版と非同期版に別個の役割を
// 持たせる
// (なぜそうしたいかの理由の一つとしては<https://github.com/VOICEVOX/voicevox_core/issues/687>)
impl InferenceRuntime for self::blocking::Onnxruntime {
type Session = ort::Session;
type RunContext<'a> = OnnxruntimeRunContext<'a>;
Expand Down Expand Up @@ -254,7 +264,7 @@ pub(crate) mod blocking {
/// # Rust APIにおけるインスタンスの共有
///
/// インスタンスは[voicevox-ort]側に作られる。Rustのクレートとしてこのライブラリを利用する場合、
/// Tokio版APIやvoicevox-ortを利用する他クレートともインスタンスが共有される。
/// 非同期版APIやvoicevox-ortを利用する他クレートともインスタンスが共有される。
///
#[cfg_attr(feature = "load-onnxruntime", doc = "```")]
#[cfg_attr(not(feature = "load-onnxruntime"), doc = "```compile_fail")]
Expand All @@ -268,7 +278,7 @@ pub(crate) mod blocking {
/// # .exec()?;
/// # }
/// let ort1 = voicevox_core::blocking::Onnxruntime::load_once().exec()?;
/// let ort2 = another_lib::tokio::Onnxruntime::get().expect("`ort1`と同一のはず");
/// let ort2 = another_lib::nonblocking::Onnxruntime::get().expect("`ort1`と同一のはず");
/// assert_eq!(ptr_addr(ort1), ptr_addr(ort2));
///
/// fn ptr_addr(obj: &impl Sized) -> usize {
Expand Down Expand Up @@ -430,7 +440,7 @@ pub(crate) mod blocking {
}
}

pub(crate) mod tokio {
pub(crate) mod nonblocking {
use ref_cast::{ref_cast_custom, RefCastCustom};

use crate::SupportedDevices;
Expand All @@ -448,15 +458,17 @@ pub(crate) mod tokio {
#[cfg_attr(not(feature = "load-onnxruntime"), doc = "```compile_fail")]
/// # use voicevox_core as another_lib;
/// #
/// # #[tokio::main]
/// # #[pollster::main]
/// # async fn main() -> anyhow::Result<()> {
/// # if cfg!(windows) {
/// # // Windows\System32\onnxruntime.dllを回避
/// # voicevox_core::blocking::Onnxruntime::load_once()
/// # .filename(test_util::ONNXRUNTIME_DYLIB_PATH)
/// # .exec()?;
/// # }
/// let ort1 = voicevox_core::tokio::Onnxruntime::load_once().exec().await?;
/// let ort1 = voicevox_core::nonblocking::Onnxruntime::load_once()
/// .exec()
/// .await?;
/// let ort2 = another_lib::blocking::Onnxruntime::get().expect("`ort1`と同一のはず");
/// assert_eq!(ptr_addr(ort1), ptr_addr(ort2));
///
Expand All @@ -467,7 +479,13 @@ pub(crate) mod tokio {
/// # }
/// ```
///
/// # Performance
///
/// [blocking]クレートにより動いている。詳しくは[`nonblocking`モジュールのドキュメント]を参照。
///
/// [voicevox-ort]: https://github.com/VOICEVOX/ort
/// [blocking]: https://docs.rs/crate/blocking
/// [`nonblocking`モジュールのドキュメント]: crate::nonblocking
#[derive(Debug, RefCastCustom)]
#[repr(transparent)]
pub struct Onnxruntime(pub(crate) super::blocking::Onnxruntime);
Expand Down Expand Up @@ -584,11 +602,11 @@ mod tests {

assert_eq!(
super::blocking::Onnxruntime::LIB_NAME,
super::tokio::Onnxruntime::LIB_NAME,
super::nonblocking::Onnxruntime::LIB_NAME,
);
assert_eq!(
super::blocking::Onnxruntime::LIB_VERSION,
super::tokio::Onnxruntime::LIB_VERSION,
super::nonblocking::Onnxruntime::LIB_VERSION,
);
}

Expand Down
2 changes: 1 addition & 1 deletion crates/voicevox_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ mod voice_model;

pub mod __internal;
pub mod blocking;
pub mod tokio;
pub mod nonblocking;

#[cfg(test)]
mod test_util;
Expand Down
25 changes: 25 additions & 0 deletions crates/voicevox_core/src/nonblocking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! 非同期版API。
//!
//! # Performance
//!
//! これらは[blocking]クレートにより動いている。特定の非同期ランタイムを必要とせず、[pollster]など
//! でも動かすことができる。
//!
//! スレッドプールおよびエグゼキュータはblockingクレートに依存するすべてのプログラム間で共有される。
//! スレッドプールのサイズは、blockingクレートの説明にある通り`$BLOCKING_MAX_THREADS`で調整すること
//! ができる。
//!
//! [blocking]: https://docs.rs/crate/blocking
//! [pollster]: https://docs.rs/crate/pollster
pub use crate::{
engine::open_jtalk::nonblocking::OpenJtalk,
infer::runtimes::onnxruntime::nonblocking::Onnxruntime, synthesizer::nonblocking::Synthesizer,
user_dict::dict::nonblocking::UserDict, voice_model::nonblocking::VoiceModel,
};

pub mod onnxruntime {
#[cfg(feature = "load-onnxruntime")]
#[cfg_attr(docsrs, doc(cfg(feature = "load-onnxruntime")))]
pub use crate::infer::runtimes::onnxruntime::nonblocking::LoadOnce;
}
4 changes: 2 additions & 2 deletions crates/voicevox_core/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ mod tests {
talk: enum_map!(_ => InferenceSessionOptions::new(0, DeviceSpec::Cpu)),
},
);
let model = &crate::tokio::VoiceModel::sample().await.unwrap();
let model = &crate::nonblocking::VoiceModel::sample().await.unwrap();
let model_contents = &model.read_inference_models().await.unwrap();
let result = status.insert_model(model.header(), model_contents);
assert_debug_fmt_eq!(Ok(()), result);
Expand All @@ -424,7 +424,7 @@ mod tests {
talk: enum_map!(_ => InferenceSessionOptions::new(0, DeviceSpec::Cpu)),
},
);
let vvm = &crate::tokio::VoiceModel::sample().await.unwrap();
let vvm = &crate::nonblocking::VoiceModel::sample().await.unwrap();
let model_header = vvm.header();
let model_contents = &vvm.read_inference_models().await.unwrap();
assert!(
Expand Down
Loading

0 comments on commit 35d2040

Please sign in to comment.