Skip to content

single_char_pattern lint suggests performance regression for strip_prefix/suffix #8111

@twanvl

Description

@twanvl

Summary

The lint single_char_pattern suggest replacing a string with a char constant, but this actually results in significantly worse performance for wide Unicode characters in strip_prefix.

In some sense this is a rust standard library issue, but clippy shouldn't suggest this as an improvement and say "Performing these methods using a char is faster than using a str." when the opposite is true.

This seems to be the case for strip_prefix and strip_suffix. For other methods like split, char is always faster than str.

Simplest fix: remove strip_prefix and strip_suffix from the list of functions to check in this lint.

Lint Name

single_char_pattern

Reproducer

Here is a benchmark:

use criterion::{black_box, criterion_group, criterion_main, Criterion};
pub fn criterion_benchmark(c: &mut Criterion) {
  c.bench_function("strip_prefix str  ascii",   |b| b.iter(|| black_box("hello world").strip_prefix("h")));
  c.bench_function("strip_prefix char ascii",   |b| b.iter(|| black_box("hello world").strip_prefix('h')));
  c.bench_function("strip_prefix str  unicode", |b| b.iter(|| black_box("おはよう、世界").strip_prefix("お")));
  c.bench_function("strip_prefix char unicode", |b| b.iter(|| black_box("おはよう、世界").strip_prefix('お')));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

For which clippy reports:

warning: single-character string constant used as pattern
 --> src\main.rs:4:101
  |
4 |   c.bench_function("strip_prefix str  ascii",   |b| b.iter(|| black_box("hello world").strip_prefix("h")));
  |                                                                                                     ^^^ help: try using a `char` instead: `'h'`
  |
  = note: `#[warn(clippy::single_char_pattern)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern

warning: single-character string constant used as pattern
 --> src\main.rs:6:97
  |
6 |   c.bench_function("strip_prefix str  unicode", |b| b.iter(|| black_box("おはよう、世界").strip_prefix("お")));
  |                                                                                                        ^^^^ help: try using a `char` instead: `'お'`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern

The documentation says "Performing these methods using a char is faster than using a str."

Benchmark output:

strip_prefix str  ascii time:   [4.3805 ns 4.4939 ns 4.6732 ns]
strip_prefix char ascii time:   [4.2060 ns 4.2173 ns 4.2305 ns]
strip_prefix str  unicode
                        time:   [4.7124 ns 4.7187 ns 4.7270 ns]
strip_prefix char unicode
                        time:   [11.643 ns 11.677 ns 11.715 ns]

The performance with a single character Unicode pattern is better with a string pattern than with a char pattern. So clippy shouldn't suggest this change.

Version

rustc 1.59.0-nightly (efec54529 2021-12-04)
binary: rustc
commit-hash: efec545293b9263be9edfb283a7aa66350b3acbf
commit-date: 2021-12-04
host: x86_64-pc-windows-msvc
release: 1.59.0-nightly
LLVM version: 13.0.0

Additional Labels

No response

Metadata

Metadata

Assignees

Labels

C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions