forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#68232 - Mark-Simulacrum:unicode-tables, r=j…
…oshtriplett Optimize size/speed of Unicode datasets The overall implementation has the same general idea as the prior approach, which was based on a compressed trie structure, but modified to use less space (and, coincidentally, be an overall performance improvement). Sizes | Old | New | New/current -- | -- | -- | -- Alphabetic | 4616 | 2982 | 64.60% Case_Ignorable | 3144 | 2112 | 67.18% Cased | 2376 | 934 | 39.31% Cc | 19 | 43 | 226.32% Grapheme_Extend | 3072 | 1734 | 56.45% Lowercase | 2328 | 985 | 42.31% N | 2648 | 1239 | 46.79% Uppercase | 1978 | 934 | 47.22% White_Space | 241 | 140 | 58.09% | | | Total | 20422 | 11103 | 54.37% This table shows the size of the old and new tables in bytes. The most important of these tables is "Grapheme_Extend", as it is present in essentially all Rust programs due to being called from `str`'s Debug impl (`char::escape_debug`). In a representative case given by this [blog post] for the embedded world, the shrinking in this PR shrinks the final binary by 1,604 bytes, from 14,440 to 12,836. The performance of these new tables, based on the (rough) benchmark of linearly scanning the entire valid set of chars, querying for each `is_*`, is roughly ~50% better, though in some cases is either on par or slightly (3-5%) worse. In practice, I believe the size benefits of this PR are the main concern. The new implementation has been tested to be equivalent to the current nightly in terms of returned values on the set of valid chars. A (relatively) high-level explanation of the specific compression scheme used can be found [in the generator]. This is split into three commits -- the first adds the generator which produces the Rust code for the tables, the second adds support code for the lookup, and the third actually swaps the current implementation out for the new one. [blog post]: https://jamesmunns.com/blog/fmt-unreasonably-expensive/ [in the generator]: https://github.com/Mark-Simulacrum/rust/blob/unicode-tables/src/tools/unicode-table-generator/src/raw_emitter.rs
- Loading branch information
Showing
15 changed files
with
2,966 additions
and
3,202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,59 @@ | ||
#![unstable(feature = "unicode_internals", issue = "none")] | ||
#![allow(missing_docs)] | ||
|
||
mod bool_trie; | ||
pub(crate) mod printable; | ||
pub(crate) mod tables; | ||
mod unicode_data; | ||
pub(crate) mod version; | ||
|
||
use version::UnicodeVersion; | ||
|
||
/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of | ||
/// `char` and `str` methods are based on. | ||
#[unstable(feature = "unicode_version", issue = "49726")] | ||
pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { | ||
major: unicode_data::UNICODE_VERSION.0, | ||
minor: unicode_data::UNICODE_VERSION.1, | ||
micro: unicode_data::UNICODE_VERSION.2, | ||
_priv: (), | ||
}; | ||
|
||
// For use in liballoc, not re-exported in libstd. | ||
pub mod derived_property { | ||
pub use crate::unicode::tables::derived_property::{Case_Ignorable, Cased}; | ||
pub use super::{Case_Ignorable, Cased}; | ||
} | ||
pub mod conversions { | ||
pub use crate::unicode::tables::conversions::{to_lower, to_upper}; | ||
|
||
pub use unicode_data::alphabetic::lookup as Alphabetic; | ||
pub use unicode_data::case_ignorable::lookup as Case_Ignorable; | ||
pub use unicode_data::cased::lookup as Cased; | ||
pub use unicode_data::cc::lookup as Cc; | ||
pub use unicode_data::conversions; | ||
pub use unicode_data::grapheme_extend::lookup as Grapheme_Extend; | ||
pub use unicode_data::lowercase::lookup as Lowercase; | ||
pub use unicode_data::n::lookup as N; | ||
pub use unicode_data::uppercase::lookup as Uppercase; | ||
pub use unicode_data::white_space::lookup as White_Space; | ||
|
||
#[inline(always)] | ||
fn range_search<const N: usize, const N1: usize, const N2: usize>( | ||
needle: u32, | ||
chunk_idx_map: &[u8; N], | ||
(last_chunk_idx, last_chunk_mapping): (u16, u8), | ||
bitset_chunk_idx: &[[u8; 16]; N1], | ||
bitset: &[u64; N2], | ||
) -> bool { | ||
let bucket_idx = (needle / 64) as usize; | ||
let chunk_map_idx = bucket_idx / 16; | ||
let chunk_piece = bucket_idx % 16; | ||
let chunk_idx = if chunk_map_idx >= N { | ||
if chunk_map_idx == last_chunk_idx as usize { | ||
last_chunk_mapping | ||
} else { | ||
return false; | ||
} | ||
} else { | ||
chunk_idx_map[chunk_map_idx] | ||
}; | ||
let idx = bitset_chunk_idx[(chunk_idx as usize)][chunk_piece]; | ||
let word = bitset[(idx as usize)]; | ||
(word & (1 << (needle % 64) as u64)) != 0 | ||
} |
Oops, something went wrong.