Instrumentation for perf analysis using Flame

* [Cargo.toml] Add `flame_it` feature to enable instrumentation in
`lib.rs` and on `pub fn`s on major modules.

* Add example crate to get bidi info and visual runs for one piece of
bidi text and output flame chart.

* Move UDHR data files out of `/benches/` and into `/data/` to share
between various types of crates in the repo.

Test:
```
cargo run --example flame_udhr --features flame_it
```
produces `flame-udhr-graph.html`..
This commit is contained in:
Behnam Esfahbod
2017-06-14 00:02:56 -06:00
parent 2e0aa9d506
commit 325b6be383
35 changed files with 136 additions and 34 deletions
+14 -6
View File
@@ -1,5 +1,7 @@
language: rust
sudo: false
os: linux
dist: trusty
rust:
- nightly
@@ -17,12 +19,18 @@ notifications:
email:
on_success: never
before_script:
- pip install git+https://github.com/euclio/travis-cargo@kcov --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build --verbose
- cargo test --verbose
- cargo test --verbose --features with_serde
- cargo doc --verbose --no-deps
- travis-cargo bench
- RUST_BACKTRACE=1 cargo test --verbose
- RUST_BACKTRACE=1 cargo test --verbose --features with_serde
- if [ "$TRAVIS_RUST_VERSION" != "nightly" ] ; then exit ; fi
- RUST_BACKTRACE=1 cargo test --verbose --features bench_it
- RUST_BACKTRACE=1 cargo test --verbose --features flame_it
- cargo run --verbose --features flame_it --example flame_udhr
- cargo bench --verbose --features bench_it
+5 -1
View File
@@ -14,6 +14,8 @@ exclude = ["*.txt"]
name = "unicode_bidi"
[dependencies]
flame = { version = "0.1", optional = true }
flamer = { version = "0.1", optional = true }
matches = "0.1"
serde = {version = ">=0.8, <2.0", optional = true}
serde_derive = {version = ">=0.8, <2.0", optional = true}
@@ -23,5 +25,7 @@ serde_test = ">=0.8, <2.0"
[features]
default = []
unstable = [] # Use in benches/
unstable = [] # travis-cargo needs it
bench_it = []
flame_it = ["flame", "flamer"]
with_serde = ["serde", "serde_derive"]
+1 -1
View File
@@ -7,7 +7,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(all(test, feature = "unstable"))]
#![cfg(all(test, feature = "bench_it"))]
#![feature(test)]
extern crate test;
+25 -25
View File
@@ -7,7 +7,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(all(test, feature = "unstable"))]
#![cfg(all(test, feature = "bench_it"))]
#![feature(test)]
extern crate test;
@@ -19,33 +19,33 @@ use unicode_bidi::BidiInfo;
const LTR_TEXTS: &[&str] = &[
include_str!("udhr_data/ltr/udhr_acu_1.txt"),
include_str!("udhr_data/ltr/udhr_auc.txt"),
include_str!("udhr_data/ltr/udhr_eng.txt"),
include_str!("udhr_data/ltr/udhr_knc.txt"),
include_str!("udhr_data/ltr/udhr_krl.txt"),
include_str!("udhr_data/ltr/udhr_lot.txt"),
include_str!("udhr_data/ltr/udhr_mly_latn.txt"),
include_str!("udhr_data/ltr/udhr_piu.txt"),
include_str!("udhr_data/ltr/udhr_qug.txt"),
include_str!("udhr_data/ltr/udhr_snn.txt"),
include_str!("udhr_data/ltr/udhr_tiv.txt"),
include_str!("udhr_data/ltr/udhr_uig_latn.txt"),
include_str!("../data/udhr/ltr/udhr_acu_1.txt"),
include_str!("../data/udhr/ltr/udhr_auc.txt"),
include_str!("../data/udhr/ltr/udhr_eng.txt"),
include_str!("../data/udhr/ltr/udhr_knc.txt"),
include_str!("../data/udhr/ltr/udhr_krl.txt"),
include_str!("../data/udhr/ltr/udhr_lot.txt"),
include_str!("../data/udhr/ltr/udhr_mly_latn.txt"),
include_str!("../data/udhr/ltr/udhr_piu.txt"),
include_str!("../data/udhr/ltr/udhr_qug.txt"),
include_str!("../data/udhr/ltr/udhr_snn.txt"),
include_str!("../data/udhr/ltr/udhr_tiv.txt"),
include_str!("../data/udhr/ltr/udhr_uig_latn.txt"),
];
const BIDI_TEXTS: &[&str] = &[
include_str!("udhr_data/bidi/udhr_aii.txt"),
include_str!("udhr_data/bidi/udhr_arb.txt"),
include_str!("udhr_data/bidi/udhr_mly_arab.txt"),
include_str!("udhr_data/bidi/udhr_pes_1.txt"),
include_str!("udhr_data/bidi/udhr_skr.txt"),
include_str!("udhr_data/bidi/udhr_urd.txt"),
include_str!("udhr_data/bidi/udhr_pes_2.txt"),
include_str!("udhr_data/bidi/udhr_uig_arab.txt"),
include_str!("udhr_data/bidi/udhr_urd_2.txt"),
include_str!("udhr_data/bidi/udhr_heb.txt"),
include_str!("udhr_data/bidi/udhr_pnb.txt"),
include_str!("udhr_data/bidi/udhr_ydd.txt"),
include_str!("../data/udhr/bidi/udhr_aii.txt"),
include_str!("../data/udhr/bidi/udhr_arb.txt"),
include_str!("../data/udhr/bidi/udhr_mly_arab.txt"),
include_str!("../data/udhr/bidi/udhr_pes_1.txt"),
include_str!("../data/udhr/bidi/udhr_skr.txt"),
include_str!("../data/udhr/bidi/udhr_urd.txt"),
include_str!("../data/udhr/bidi/udhr_pes_2.txt"),
include_str!("../data/udhr/bidi/udhr_uig_arab.txt"),
include_str!("../data/udhr/bidi/udhr_urd_2.txt"),
include_str!("../data/udhr/bidi/udhr_heb.txt"),
include_str!("../data/udhr/bidi/udhr_pnb.txt"),
include_str!("../data/udhr/bidi/udhr_ydd.txt"),
];
+50
View File
@@ -0,0 +1,50 @@
// Copyright 2017 The Servo Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Profiling example
#![allow(unused_imports)]
#![cfg_attr(feature="flame_it", feature(plugin, custom_attribute))]
#![cfg_attr(feature="flame_it", plugin(flamer))]
#[cfg(feature = "flame_it")]
extern crate flame;
extern crate unicode_bidi;
use std::fs::File;
use unicode_bidi::BidiInfo;
#[cfg(feature = "flame_it")]
fn main() {
const BIDI_TEXT: &'static str = include_str!("../data/udhr/bidi/udhr_pes_1.txt");
flame::start("main(): BidiInfo::new()");
let bidi_info = BidiInfo::new(BIDI_TEXT, None);
flame::end("main(): BidiInfo::new()");
flame::start("main(): iter bidi_info.paragraphs");
for para in &bidi_info.paragraphs {
let line = para.range.clone();
bidi_info.reorder_line(para, line);
}
flame::end("main(): iter bidi_info.paragraphs");
flame::dump_html(&mut File::create("flame-udhr-graph.html").unwrap()).unwrap();
}
#[cfg(not(feature = "flame_it"))]
// Allow example to compile
fn main() {}
+1
View File
@@ -20,6 +20,7 @@ use BidiClass::*;
///
/// `processing_classes[i]` must contain the `BidiClass` of the char at byte index `i`,
/// for each char in `text`.
#[cfg_attr(feature="flame_it", flame)]
pub fn compute(
text: &str,
para_level: Level,
+3
View File
@@ -20,6 +20,7 @@ use BidiClass::*;
/// 3.3.4 Resolving Weak Types
///
/// http://www.unicode.org/reports/tr9/#Resolving_Weak_Types
#[cfg_attr(feature="flame_it", flame)]
pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [BidiClass]) {
// FIXME (#8): This function applies steps W1-W6 in a single pass. This can produce
// incorrect results in cases where a "later" rule changes the value of `prev_class` seen
@@ -134,6 +135,7 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B
/// 3.3.5 Resolving Neutral Types
///
/// http://www.unicode.org/reports/tr9/#Resolving_Neutral_Types
#[cfg_attr(feature="flame_it", flame)]
pub fn resolve_neutral(
sequence: &IsolatingRunSequence,
levels: &[Level],
@@ -198,6 +200,7 @@ pub fn resolve_neutral(
/// Returns the maximum embedding level in the paragraph.
///
/// http://www.unicode.org/reports/tr9/#Resolving_Implicit_Levels
#[cfg_attr(feature="flame_it", flame)]
pub fn resolve_levels(original_classes: &[BidiClass], levels: &mut [Level]) -> Level {
let mut max_level = Level::ltr();
+35
View File
@@ -57,6 +57,10 @@
#![forbid(unsafe_code)]
#![cfg_attr(feature="flame_it", feature(plugin, custom_attribute))]
#![cfg_attr(feature="flame_it", plugin(flamer))]
#[macro_use]
extern crate matches;
@@ -67,6 +71,10 @@ extern crate serde_derive;
#[cfg(all(feature = "with_serde", test))]
extern crate serde_test;
#[cfg(feature="flame_it")]
extern crate flame;
pub mod deprecated;
pub mod format_chars;
pub mod level;
@@ -127,6 +135,7 @@ impl<'text> InitialInfo<'text> {
/// Also sets the class for each First Strong Isolate initiator (FSI) to LRI or RLI if a strong
/// character is found before the matching PDI. If no strong character is found, the class will
/// remain FSI, and it's up to later stages to treat these as LRI when needed.
#[cfg_attr(feature="flame_it", flame)]
pub fn new(text: &str, default_para_level: Option<Level>) -> InitialInfo {
let mut original_classes = Vec::with_capacity(text.len());
@@ -137,10 +146,22 @@ impl<'text> InitialInfo<'text> {
let mut para_start = 0;
let mut para_level = default_para_level;
#[cfg(feature="flame_it")]
flame::start("InitialInfo::new(): iter text.char_indices()");
for (i, c) in text.char_indices() {
let class = bidi_class(c);
#[cfg(feature="flame_it")]
flame::start("original_classes.extend()");
original_classes.extend(repeat(class).take(c.len_utf8()));
#[cfg(feature="flame_it")]
flame::end("original_classes.extend()");
match class {
B => {
// P1. Split the text into separate paragraphs. The paragraph separator is kept
// with the previous paragraph.
@@ -158,6 +179,7 @@ impl<'text> InitialInfo<'text> {
para_level = default_para_level;
isolate_stack.clear();
}
L | R | AL => {
match isolate_stack.last() {
Some(&start) => {
@@ -170,6 +192,7 @@ impl<'text> InitialInfo<'text> {
}
}
}
None => {
if para_level.is_none() {
// P2. Find the first character of type L, AL, or R, while skipping
@@ -180,12 +203,15 @@ impl<'text> InitialInfo<'text> {
}
}
}
RLI | LRI | FSI => {
isolate_stack.push(i);
}
PDI => {
isolate_stack.pop();
}
_ => {}
}
}
@@ -197,6 +223,9 @@ impl<'text> InitialInfo<'text> {
}
assert_eq!(original_classes.len(), text.len());
#[cfg(feature="flame_it")]
flame::end("InitialInfo::new(): iter text.char_indices()");
InitialInfo {
text: text,
original_classes: original_classes,
@@ -236,6 +265,7 @@ impl<'text> BidiInfo<'text> {
/// text that is entirely LTR. See the `nsBidi` class from Gecko for comparison.
///
/// TODO: Support auto-RTL base direction
#[cfg_attr(feature="flame_it", flame)]
pub fn new(text: &str, default_para_level: Option<Level>) -> BidiInfo {
let InitialInfo {
original_classes,
@@ -283,6 +313,7 @@ impl<'text> BidiInfo<'text> {
/// Re-order a line based on resolved levels and return only the embedding levels, one `Level`
/// per *byte*.
#[cfg_attr(feature="flame_it", flame)]
pub fn reordered_levels(&self, para: &ParagraphInfo, line: Range<usize>) -> Vec<Level> {
let (levels, _) = self.visual_runs(para, line.clone());
levels
@@ -290,6 +321,7 @@ impl<'text> BidiInfo<'text> {
/// Re-order a line based on resolved levels and return only the embedding levels, one `Level`
/// per *character*.
#[cfg_attr(feature="flame_it", flame)]
pub fn reordered_levels_per_char(
&self,
para: &ParagraphInfo,
@@ -301,6 +333,7 @@ impl<'text> BidiInfo<'text> {
/// Re-order a line based on resolved levels and return the line in display order.
#[cfg_attr(feature="flame_it", flame)]
pub fn reorder_line(&self, para: &ParagraphInfo, line: Range<usize>) -> Cow<'text, str> {
let (levels, runs) = self.visual_runs(para, line.clone());
@@ -325,6 +358,7 @@ impl<'text> BidiInfo<'text> {
/// `line` is a range of bytes indices within `levels`.
///
/// http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
#[cfg_attr(feature="flame_it", flame)]
pub fn visual_runs(
&self,
para: &ParagraphInfo,
@@ -449,6 +483,7 @@ impl<'text> BidiInfo<'text> {
///
/// The levels assigned to these characters are not specified by the algorithm. This function
/// assigns each one the level of the previous character, to avoid breaking level runs.
#[cfg_attr(feature="flame_it", flame)]
fn assign_levels_to_removed_chars(para_level: Level, classes: &[BidiClass], levels: &mut [Level]) {
for i in 0..levels.len() {
if prepare::removed_by_x9(classes[i]) {
+1
View File
@@ -41,6 +41,7 @@ pub struct IsolatingRunSequence {
/// whose matching PDI is the first character of the next level run in the sequence.
///
/// Note: This function does *not* return the sequences in order by their first characters.
#[cfg_attr(feature="flame_it", flame)]
pub fn isolating_run_sequences(
para_level: Level,
original_classes: &[BidiClass],
+1 -1
View File
@@ -7,7 +7,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(all(test, not(feature = "unstable")))]
#![cfg(test)]
extern crate unicode_bidi;