mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 11:21:05 +01:00
Use separate value stores for identifiers and string literals (#4106)
This undoes a previous change to unify them, and I think at my advice. =[ Sorry about that, I think I was just wrong. Specifically, I think I had suggested that it would be more efficient to have a single shared hashtable of strings. The more I look at profiles of the toolchain, the less likely that seems. Specifically for identifiers and string literals it seems especially problematic. Using a single, joint hashtable is likely a good idea when all of the different querying code paths are equally likely, the strings follow the same distribution of sizes, and either there is no clustering of access to different sets of strings or none of the sets are meaningfully small enough to fit into a lower level of resident cache. I think essentially none of these predicates actually hold for identifiers vs. string literals: - Identifiers are *much* more hot - They have wildly different size distributions. - The access patterns are very clustered Sorry for the misleading advice on that one. While splitting them, I've worked to simplify the code a bit by building a way to have the `StringRef` holding canonical value stores not require specializations, and so we get a pretty large code cleanup in the process here.
This commit is contained in:
@@ -77,34 +77,55 @@ TEST(ValueStore, Float) {
|
||||
Eq(llvm::APFloatBase::cmpEqual));
|
||||
}
|
||||
|
||||
TEST(ValueStore, String) {
|
||||
TEST(ValueStore, Identifiers) {
|
||||
std::string a = "a";
|
||||
std::string b = "b";
|
||||
SharedValueStores value_stores;
|
||||
|
||||
auto a_id = value_stores.identifiers().Add(a);
|
||||
auto b_id = value_stores.identifiers().Add(b);
|
||||
|
||||
ASSERT_TRUE(a_id.is_valid());
|
||||
ASSERT_TRUE(b_id.is_valid());
|
||||
EXPECT_THAT(a_id, Not(Eq(b_id)));
|
||||
|
||||
EXPECT_THAT(value_stores.identifiers().Get(a_id), Eq(a));
|
||||
EXPECT_THAT(value_stores.identifiers().Get(b_id), Eq(b));
|
||||
|
||||
EXPECT_THAT(value_stores.identifiers().Lookup(a), Eq(a_id));
|
||||
EXPECT_THAT(value_stores.identifiers().Lookup("c"),
|
||||
Eq(IdentifierId::Invalid));
|
||||
}
|
||||
|
||||
TEST(ValueStore, StringLiterals) {
|
||||
std::string a = "a";
|
||||
std::string b = "b";
|
||||
SharedValueStores value_stores;
|
||||
|
||||
auto a_id = value_stores.string_literal_values().Add(a);
|
||||
auto b_id = value_stores.string_literal_values().Add(b);
|
||||
|
||||
ASSERT_TRUE(a_id.is_valid());
|
||||
ASSERT_TRUE(b_id.is_valid());
|
||||
EXPECT_THAT(a_id, Not(Eq(b_id)));
|
||||
|
||||
EXPECT_THAT(a_id.index, Not(Eq(b_id.index)));
|
||||
EXPECT_THAT(value_stores.identifiers().Get(a_id), Eq(a));
|
||||
EXPECT_THAT(value_stores.string_literal_values().Get(a_id), Eq(a));
|
||||
EXPECT_THAT(value_stores.string_literal_values().Get(b_id), Eq(b));
|
||||
|
||||
// Adding the same string again, even with a different Id type, should return
|
||||
// the same id.
|
||||
EXPECT_THAT(value_stores.string_literal_values().Add(a).index,
|
||||
Eq(a_id.index));
|
||||
EXPECT_THAT(value_stores.identifiers().Add(b).index, Eq(b_id.index));
|
||||
EXPECT_THAT(value_stores.string_literal_values().Lookup(a), Eq(a_id));
|
||||
EXPECT_THAT(value_stores.string_literal_values().Lookup("c"),
|
||||
Eq(StringLiteralValueId::Invalid));
|
||||
}
|
||||
|
||||
auto MatchSharedValues(testing::Matcher<Yaml::MappingValue> ints,
|
||||
testing::Matcher<Yaml::MappingValue> reals,
|
||||
testing::Matcher<Yaml::MappingValue> identifiers,
|
||||
testing::Matcher<Yaml::MappingValue> strings) -> auto {
|
||||
return Yaml::IsYaml(Yaml::Sequence(ElementsAre(Yaml::Mapping(ElementsAre(Pair(
|
||||
"shared_values",
|
||||
Yaml::Mapping(ElementsAre(Pair("ints", Yaml::Mapping(ints)),
|
||||
Pair("reals", Yaml::Mapping(reals)),
|
||||
Pair("identifiers", Yaml::Mapping(identifiers)),
|
||||
Pair("strings", Yaml::Mapping(strings))))))))));
|
||||
}
|
||||
|
||||
@@ -113,7 +134,7 @@ TEST(ValueStore, PrintEmpty) {
|
||||
TestRawOstream out;
|
||||
value_stores.Print(out);
|
||||
EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()),
|
||||
MatchSharedValues(IsEmpty(), IsEmpty(), IsEmpty()));
|
||||
MatchSharedValues(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
|
||||
}
|
||||
|
||||
TEST(ValueStore, PrintVals) {
|
||||
@@ -122,15 +143,17 @@ TEST(ValueStore, PrintVals) {
|
||||
value_stores.ints().Add(apint);
|
||||
value_stores.reals().Add(
|
||||
Real{.mantissa = apint, .exponent = apint, .is_decimal = true});
|
||||
value_stores.identifiers().Add("a");
|
||||
value_stores.string_literal_values().Add("foo'\"baz");
|
||||
TestRawOstream out;
|
||||
value_stores.Print(out);
|
||||
|
||||
EXPECT_THAT(
|
||||
Yaml::Value::FromText(out.TakeStr()),
|
||||
MatchSharedValues(ElementsAre(Pair("int0", Yaml::Scalar("8"))),
|
||||
ElementsAre(Pair("real0", Yaml::Scalar("8*10^8"))),
|
||||
ElementsAre(Pair("str0", Yaml::Scalar("foo'\"baz")))));
|
||||
EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()),
|
||||
MatchSharedValues(
|
||||
ElementsAre(Pair("int0", Yaml::Scalar("8"))),
|
||||
ElementsAre(Pair("real0", Yaml::Scalar("8*10^8"))),
|
||||
ElementsAre(Pair("identifier0", Yaml::Scalar("a"))),
|
||||
ElementsAre(Pair("string0", Yaml::Scalar("foo'\"baz")))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user