@@ -10,6 +10,7 @@ use measureme::{Addr, StringId};
10
10
use rustc_hash:: FxHashMap ;
11
11
use std:: borrow:: Cow ;
12
12
use std:: error:: Error ;
13
+ use memchr:: memchr;
13
14
14
15
// See module-level documentation for more information on the encoding.
15
16
const UTF8_CONTINUATION_MASK : u8 = 0b1100_0000 ;
@@ -30,9 +31,28 @@ pub struct StringRef<'st> {
30
31
31
32
impl < ' st > StringRef < ' st > {
32
33
pub fn to_string ( & self ) -> Cow < ' st , str > {
33
- let mut output = String :: new ( ) ;
34
- self . write_to_string ( & mut output) ;
35
- Cow :: from ( output)
34
+
35
+ // Try to avoid the allocation, which we can do if this is a
36
+ // [value, 0xFF] entry.
37
+ let addr = self . table . index [ & self . id ] ;
38
+ let pos = addr. as_usize ( ) ;
39
+ let slice_to_search = & self . table . string_data [ pos..] ;
40
+
41
+ // Find the first 0xFF byte which which is either the sequence
42
+ // terminator or a byte in the middle of string id. Use `memchr` which
43
+ // is super fast.
44
+ let terminator_pos = memchr ( TERMINATOR , slice_to_search) . unwrap ( ) ;
45
+
46
+ // Decode the bytes until the terminator. If there is a string id in
47
+ // between somewhere this will fail, and we fall back to the allocating
48
+ // path.
49
+ if let Ok ( s) = std:: str:: from_utf8 ( & slice_to_search[ ..terminator_pos] ) {
50
+ Cow :: from ( s)
51
+ } else {
52
+ let mut output = String :: new ( ) ;
53
+ self . write_to_string ( & mut output) ;
54
+ Cow :: from ( output)
55
+ }
36
56
}
37
57
38
58
pub fn write_to_string ( & self , output : & mut String ) {
0 commit comments