1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use ;
use QualName;
/// An attribute's value, interned so identical values are stored once.
///
/// This was a plain `String`, which meant one separate heap allocation per
/// attribute per element with no sharing between them. A census over the
/// application's own transcript markup
/// (`blitz-tests/tests/attribute_value_duplication.rs`) found **777 attribute
/// values of which 54 were distinct**: 14.4x duplication, and 91.3% of the
/// value bytes were a copy of a string already in the tree. One `class` string
/// appeared 24 times. That is what a Tailwind UI looks like in memory, and it
/// is the shape Blink shares through `ElementDataCache` for the same reason
/// (`element_data.h:172`, "very common for many elements to have duplicate
/// sets of attributes (ex. the same classes)").
///
/// `Atom` is the right tool and was already in the dependency graph, because
/// `QualName` above is built from it. It is 8 bytes against `String`'s 24,
/// stores up to 7 bytes inline with no heap allocation at all, and interns
/// anything longer in a refcounted global table with per-bucket locks rather
/// than one global one.
///
/// The trade is a hash and a possible lock acquisition per *write*, against a
/// heap allocation and a memcpy per write today, and equality becoming a
/// pointer comparison rather than a memcmp. Reads are unaffected: this derefs
/// to `str`, so every `&attr.value`, `.as_str()`, `.parse()` and `==` call
/// site continues to compile and mean the same thing.
///
/// `Atom` is generic over a set of strings interned at compile time. We have
/// none to pre-intern: attribute *names* are already atoms via `QualName`, and
/// values are arbitrary author strings, so every one of ours takes the dynamic
/// path. `EmptyStaticAtomSet` is the crate's own declaration of that case.
///
/// Named `AttrAtom` rather than the more obvious `AttrValue`, because stylo
/// already exports an `AttrValue` enum that `document.rs` uses in the same
/// breath as this type. Two different things under one name in one file is how
/// a later reader loses an afternoon.
pub type AttrAtom = Atom;
/// A tag attribute, e.g. `class="test"` in `<div class="test" ...>`.