Add benchmark for Python threaded word count
Add benchmark where the sequential Rust version of the word count is executed twice to demonstrate parallelism with Python threads. Also slightly simplify the benchmark functions.
This commit is contained in:
parent
bafe269dde
commit
d2c7645bad
|
@ -7,21 +7,22 @@ use rayon::prelude::*;
|
|||
|
||||
/// Searches for the word, parallelized by rayon
|
||||
#[pyfunction]
|
||||
fn search(py: Python<'_>, contents: &str, needle: &str) -> PyResult<usize> {
|
||||
let count = py.allow_threads(move || {
|
||||
contents
|
||||
.par_lines()
|
||||
.map(|line| count_line(line, needle))
|
||||
.sum()
|
||||
});
|
||||
Ok(count)
|
||||
fn search(contents: &str, needle: &str) -> usize {
|
||||
contents
|
||||
.par_lines()
|
||||
.map(|line| count_line(line, needle))
|
||||
.sum()
|
||||
}
|
||||
|
||||
/// Searches for a word in a classic sequential fashion
|
||||
#[pyfunction]
|
||||
fn search_sequential(contents: &str, needle: &str) -> PyResult<usize> {
|
||||
let result = contents.lines().map(|line| count_line(line, needle)).sum();
|
||||
Ok(result)
|
||||
fn search_sequential(contents: &str, needle: &str) -> usize {
|
||||
contents.lines().map(|line| count_line(line, needle)).sum()
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn search_sequential_allow_threads(py: Python, contents: &str, needle: &str) -> usize {
|
||||
py.allow_threads(|| search_sequential(contents, needle))
|
||||
}
|
||||
|
||||
fn matches(word: &str, needle: &str) -> bool {
|
||||
|
@ -56,6 +57,7 @@ fn count_line(line: &str, needle: &str) -> usize {
|
|||
fn word_count(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||
m.add_wrapped(wrap_pyfunction!(search))?;
|
||||
m.add_wrapped(wrap_pyfunction!(search_sequential))?;
|
||||
m.add_wrapped(wrap_pyfunction!(search_sequential_allow_threads))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import pytest
|
||||
|
||||
import word_count
|
||||
|
||||
current_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -49,3 +50,23 @@ def test_word_count_rust_sequential(benchmark, contents):
|
|||
def test_word_count_python_sequential(benchmark, contents):
|
||||
count = benchmark(word_count.search_py, contents, "is")
|
||||
assert count == 10000
|
||||
|
||||
|
||||
def run_rust_sequential_twice(
|
||||
executor: ThreadPoolExecutor, contents: str, needle: str
|
||||
) -> int:
|
||||
future_1 = executor.submit(
|
||||
word_count.search_sequential_allow_threads, contents, needle
|
||||
)
|
||||
future_2 = executor.submit(
|
||||
word_count.search_sequential_allow_threads, contents, needle
|
||||
)
|
||||
result_1 = future_1.result()
|
||||
result_2 = future_2.result()
|
||||
return result_1 + result_2
|
||||
|
||||
|
||||
def test_word_count_rust_sequential_twice_with_threads(benchmark, contents):
|
||||
executor = ThreadPoolExecutor(max_workers=2)
|
||||
count = benchmark(run_rust_sequential_twice, executor, contents, "is")
|
||||
assert count == 20000
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
from .word_count import search, search_sequential
|
||||
from .word_count import search, search_sequential, search_sequential_allow_threads
|
||||
|
||||
__all__ = ["search_py", "search", "search_sequential"]
|
||||
__all__ = [
|
||||
"search_py",
|
||||
"search",
|
||||
"search_sequential",
|
||||
"search_sequential_allow_threads",
|
||||
]
|
||||
|
||||
|
||||
def search_py(contents, needle):
|
||||
|
|
Loading…
Reference in New Issue