From a284ebc8414490c90a37146b613b32df63383ee6 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 24 May 2023 11:40:38 +0100 Subject: [PATCH 01/53] Multitree root commit with blocking log write --- .gitignore | 1 + admin/src/lib.rs | 28 ++ admin/src/multitree_bench/data.rs | 731 ++++++++++++++++++++++++++++++ admin/src/multitree_bench/mod.rs | 358 +++++++++++++++ src/btree/mod.rs | 13 +- src/column.rs | 84 ++++ src/db.rs | 72 ++- src/lib.rs | 2 + src/multitree.rs | 17 + src/options.rs | 15 +- 10 files changed, 1311 insertions(+), 10 deletions(-) create mode 100644 admin/src/multitree_bench/data.rs create mode 100644 admin/src/multitree_bench/mod.rs create mode 100644 src/multitree.rs diff --git a/.gitignore b/.gitignore index ab57bcf4..658079fd 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ Cargo.lock *.log test_db/ test_db_stress/ +test_db_multitree_stress/ # vim *.swp diff --git a/admin/src/lib.rs b/admin/src/lib.rs index 6236bd38..9914c246 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; mod bench; +mod multitree_bench; /// Command line admin client entry point. /// Uses default column definition. @@ -127,6 +128,30 @@ pub fn run() -> Result<(), String> { let db = parity_db::Db::open_or_create(&db_options).unwrap(); bench::run_internal(args, db); }, + SubCommand::MultiTreeStress(bench) => { + let args = bench.get_args(); + // avoid deleting folders by mistake. + options.path.push("test_db_multitree_stress"); + if options.path.exists() && !args.append { + std::fs::remove_dir_all(options.path.as_path()) + .map_err(|e| format!("Error clearing stress db: {e:?}"))?; + } + + let mut db_options = options.clone(); + + for mut c in &mut db_options.columns { + c.multitree = true; + } + + if args.compress { + for mut c in &mut db_options.columns { + c.compression = parity_db::CompressionType::Lz4; + } + } + + let db = parity_db::Db::open_or_create(&db_options).unwrap(); + multitree_bench::run_internal(args, db); + }, } Ok(()) } @@ -187,6 +212,8 @@ pub enum SubCommand { Check(Check), /// Stress tests. Stress(bench::Stress), + /// Multitree stress test. + MultiTreeStress(multitree_bench::MultiTreeStress), } impl SubCommand { @@ -207,6 +234,7 @@ impl Cli { SubCommand::Flush(flush) => &flush.shared, SubCommand::Check(check) => &check.shared, SubCommand::Stress(bench) => &bench.shared, + SubCommand::MultiTreeStress(bench) => &bench.shared, } } } diff --git a/admin/src/multitree_bench/data.rs b/admin/src/multitree_bench/data.rs new file mode 100644 index 00000000..e3a015f9 --- /dev/null +++ b/admin/src/multitree_bench/data.rs @@ -0,0 +1,731 @@ +// Copyright 2021-2022 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or MIT. + +pub const DEPTH_CHILD_COUNT_HISTOGRAMS: &[(u32, [u32; 17])] = &[ + (0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), + (1, [0, 0, 9, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (2, [9, 0, 11, 13, 4, 2, 3, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1]), + (3, [78, 0, 43, 15, 5, 2, 5, 0, 1, 0, 1, 0, 3, 2, 2, 7, 16]), + (4, [215, 0, 86, 56, 32, 40, 14, 22, 17, 26, 16, 13, 7, 12, 9, 11, 84]), + (5, [1355, 0, 578, 255, 168, 122, 55, 35, 23, 16, 9, 8, 9, 8, 16, 6, 778]), + (6, [3936, 0, 734, 287, 243, 234, 228, 354, 529, 752, 956, 965, 784, 537, 303, 293, 6120]), + (7, [36666, 0, 20515, 8277, 4180, 3330, 4509, 7107, 10629, 14209, 15995, 15107, 11277, 6318, 2522, 561, 1236]), + (8, [610349, 0, 272521, 75786, 16430, 3401, 1955, 2547, 2898, 2788, 2450, 1912, 1400, 641, 257, 96, 359]), + (9, [921168, 0, 65235, 9919, 1750, 334, 107, 203, 470, 656, 839, 963, 801, 470, 172, 57, 25]), + (10, [188318, 0, 17655, 4333, 924, 203, 20, 2, 0, 0, 5, 11, 17, 7, 0, 0, 0]), + (11, [50231, 0, 1485, 35, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (12, [2917, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (13, [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), +]; + +pub const _KEY_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ + (5, 1), (20, 1), (32, 183), (36, 14), (44, 6247), (48, 1727), (52, 4381), (53, 1), (55, 32), + (56, 80), (64, 549), (65, 1), (66, 67), (68, 30), (69, 667), (72, 249742), (73, 16), (76, 304), + (77, 12321), (80, 1238143), (81, 503), (84, 19113), (92, 281057), (120, 70), +]; + +pub const VALUE_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ + (1, 66581), (2, 95), (3, 1), (4, 283269), (5, 1308), (6, 169), (7, 3), (8, 73), (9, 10), + (10, 2), (11, 205), (12, 5), (13, 4), (14, 4), (15, 7), (16, 559), (17, 418), (18, 3), (19, 4), + (20, 609), (21, 57), (22, 1), (23, 1), (24, 6), (25, 5), (26, 69428), (27, 1), (28, 6), + (29, 8), (30, 9), (31, 12), (32, 85052), (33, 3212), (34, 116), (35, 220), (36, 454), + (37, 10344), (38, 9378), (39, 31), (40, 23), (41, 27), (42, 17), (43, 18), (44, 20), (45, 19), + (46, 74), (47, 7), (48, 175), (49, 3835), (50, 1851), (51, 890), (52, 29), (53, 85), + (54, 2992), (55, 15), (56, 98), (57, 688), (58, 34), (59, 22), (60, 21), (61, 12), (62, 14), + (63, 9), (64, 21), (65, 187), (66, 176), (67, 16), (68, 12), (69, 38), (70, 2318), (71, 20), + (72, 19), (73, 94), (74, 25), (75, 12), (76, 1778), (77, 50), (78, 22), (79, 21), + (80, 1098004), (81, 44), (82, 295), (83, 132), (84, 17), (85, 96), (86, 27), (87, 12), + (88, 150), (89, 360), (90, 517), (91, 85), (92, 22), (93, 7), (94, 22), (95, 79), (96, 86), + (97, 88), (98, 388), (99, 14), (100, 44), (101, 36), (102, 2957), (103, 11), (104, 22), + (105, 24), (106, 14), (107, 8), (108, 24), (109, 81), (110, 13), (111, 11), (112, 18), + (113, 23), (114, 45194), (115, 503), (116, 18), (117, 11), (118, 13), (119, 10), (120, 167), + (121, 38), (122, 43), (123, 67), (124, 17), (125, 10), (126, 23), (127, 17), (128, 191), + (129, 241), (130, 139), (131, 6), (132, 24), (133, 15), (134, 1944), (135, 14), (136, 16), + (137, 13), (138, 5), (139, 5), (140, 11), (141, 13), (142, 66), (143, 4), (144, 12), (145, 58), + (146, 16), (147, 2), (148, 20), (149, 2), (150, 1), (151, 2), (152, 128), (153, 29), (154, 2), + (155, 1), (156, 5), (157, 1), (158, 4), (159, 3), (160, 7), (161, 41), (162, 9), (163, 2), + (164, 41), (165, 29), (166, 1891), (167, 60), (168, 70), (169, 52), (170, 63), (171, 2), + (172, 6), (173, 28), (174, 8), (176, 3), (177, 5), (178, 7), (179, 1), (180, 2), (181, 52), + (182, 2), (184, 2), (185, 2), (186, 30), (188, 28), (189, 2), (190, 4), (192, 1918), (193, 27), + (194, 2), (195, 2), (196, 2), (197, 9), (198, 1454), (199, 23), (200, 1), (201, 4), (202, 26), + (203, 1), (205, 8), (206, 66), (207, 44), (208, 139), (209, 42), (210, 44), (211, 6), + (212, 22), (213, 6), (214, 5), (216, 6), (217, 29), (218, 2), (219, 1), (220, 3), (221, 2), + (222, 2), (223, 2), (225, 14), (226, 1), (228, 4), (229, 1), (230, 1178), (232, 1), (233, 3), + (234, 3), (237, 2), (238, 3), (239, 4), (241, 1), (242, 6), (243, 1), (244, 8), (245, 28), + (246, 38), (247, 41), (248, 17), (249, 32), (250, 81), (251, 18), (252, 24), (253, 36), + (254, 1), (255, 3), (257, 13), (258, 5), (259, 1), (260, 1), (261, 2), (262, 1306), (264, 16), + (265, 3), (266, 10), (268, 7), (269, 8), (270, 21), (272, 10), (273, 11), (274, 30), (276, 7), + (277, 3), (278, 10), (279, 7), (280, 10), (281, 7), (282, 4), (283, 9), (284, 56), (285, 39), + (286, 35), (287, 22), (288, 32), (289, 55), (290, 41), (291, 2), (292, 2), (293, 5), + (294, 992), (295, 8), (296, 10), (297, 1), (298, 6), (300, 1), (301, 2), (303, 7), (305, 5), + (306, 2), (307, 5), (308, 1), (309, 1), (311, 3), (313, 3), (315, 3), (317, 1), (318, 12), + (319, 1), (321, 22), (322, 3), (323, 33), (324, 39), (325, 29), (326, 1337), (327, 29), + (328, 20), (329, 32), (330, 17), (331, 12), (332, 1), (333, 4), (334, 4), (335, 9), (336, 2), + (337, 5), (338, 1), (339, 7), (340, 13), (341, 1), (342, 3), (343, 6), (344, 8), (345, 2), + (347, 8), (349, 2), (350, 3), (351, 5), (352, 1), (353, 13), (354, 2), (355, 12), (357, 3), + (358, 1063), (359, 9), (360, 6), (361, 9), (362, 22), (363, 62), (364, 17), (365, 26), + (366, 21), (367, 25), (368, 25), (369, 30), (370, 7), (371, 21), (373, 18), (374, 4), + (375, 90), (377, 27), (378, 8), (379, 125), (380, 2), (381, 34), (382, 51), (383, 18996), + (384, 52), (385, 33308), (386, 7601), (387, 949), (388, 3922), (389, 72), (390, 1089), + (391, 287), (392, 175), (393, 571), (394, 352), (395, 35), (396, 92), (397, 29), (398, 5), + (399, 9), (400, 14), (401, 44), (402, 50), (403, 54), (404, 26), (405, 19), (406, 12), + (407, 15), (408, 9), (409, 25), (410, 7), (412, 5), (413, 2), (415, 1), (417, 12), (418, 1), + (419, 2), (422, 1086), (424, 1), (425, 4), (426, 1), (427, 2), (428, 2), (429, 2), (431, 2), + (433, 3), (436, 7), (440, 8), (441, 48), (442, 38), (443, 25), (444, 11), (445, 9), (446, 14), + (447, 16), (448, 5), (449, 18), (450, 15), (452, 2), (454, 1085), (455, 5), (456, 1), (460, 1), + (461, 1), (465, 1), (469, 2), (471, 1), (472, 6), (477, 1), (478, 2), (479, 5), (480, 18), + (481, 90), (482, 31), (483, 9), (484, 7), (485, 12), (486, 1796), (487, 7), (488, 7), (489, 8), + (490, 5), (491, 3), (492, 1), (493, 2), (494, 2), (495, 1), (497, 1), (501, 1), (513, 7), + (516, 10), (518, 14326), (519, 21), (520, 35), (521, 20), (522, 3), (523, 10), (524, 17), + (525, 8), (526, 11), (527, 6), (528, 4), (529, 3), (530, 2), (533, 1), (534, 2), (538, 3), + (543, 1), (545, 7), (549, 1), (557, 1), (558, 13), (559, 17), (560, 13), (561, 7), (562, 18), + (563, 14), (564, 9), (565, 9), (566, 7), (567, 8), (568, 2), (569, 5), (570, 2), (572, 2), + (573, 2), (577, 1), (582, 4), (596, 11), (597, 4), (598, 7), (599, 4), (600, 8), (601, 20), + (602, 20), (603, 6), (604, 12), (605, 14), (606, 4), (607, 1), (608, 3), (609, 2), (610, 5), + (612, 1), (613, 1), (614, 1), (617, 1), (624, 1), (626, 1), (630, 1), (635, 15), (636, 6), + (637, 8), (638, 11), (639, 2), (640, 15), (641, 25), (642, 15), (643, 17), (644, 10), (645, 2), + (646, 2), (647, 16), (648, 5), (649, 2), (650, 2), (653, 1), (670, 4), (673, 6), (674, 15), + (676, 9), (677, 6), (678, 2), (679, 15), (680, 17), (681, 18), (682, 15), (683, 7), (685, 1), + (686, 1), (687, 1), (688, 1), (689, 1), (690, 1), (691, 2), (693, 1), (709, 1), (713, 13), + (714, 7), (715, 7), (716, 2), (717, 3), (718, 6), (719, 17), (720, 14), (721, 8), (722, 3), + (723, 4), (724, 4), (725, 1), (726, 3), (727, 1), (728, 1), (729, 1), (730, 2), (731, 1), + (736, 3), (737, 1), (752, 19), (753, 5), (754, 9), (755, 6), (756, 2), (757, 3), (758, 16), + (759, 9), (760, 12), (761, 11), (763, 1), (764, 3), (765, 5), (766, 1), (768, 1), (769, 2), + (770, 4), (772, 1), (780, 3), (785, 1), (789, 6), (791, 15), (792, 6), (793, 16), (794, 1), + (795, 2), (796, 5), (797, 12), (798, 15), (799, 18), (800, 6), (801, 1), (802, 8), (803, 1), + (808, 3), (809, 1), (810, 2), (814, 1), (824, 1), (830, 13), (831, 7), (832, 8), (833, 8), + (834, 7), (835, 3), (836, 13), (837, 8), (838, 9), (839, 4), (841, 3), (842, 2), (843, 4), + (844, 1), (846, 2), (847, 5), (849, 2), (853, 1), (854, 1), (855, 1), (868, 2), (869, 13), + (870, 6), (871, 10), (872, 2), (873, 2), (874, 2), (875, 10), (876, 15), (877, 14), (878, 5), + (879, 4), (880, 2), (881, 3), (882, 5), (883, 2), (884, 2), (886, 1), (888, 1), (889, 2), + (890, 2), (891, 2), (908, 3), (909, 5), (910, 10), (911, 5), (912, 6), (914, 3), (915, 3), + (916, 8), (917, 2), (918, 6), (919, 1), (920, 7), (921, 5), (922, 2), (923, 3), (926, 2), + (927, 2), (929, 2), (930, 5), (931, 2), (932, 5), (933, 2), (934, 3), (947, 3), (948, 6), + (949, 7), (950, 2), (951, 5), (952, 1), (953, 3), (954, 7), (955, 10), (956, 6), (957, 3), + (958, 6), (959, 10), (960, 3), (961, 4), (962, 1), (966, 1), (967, 1), (968, 3), (969, 10), + (970, 9), (971, 3), (972, 3), (977, 1), (978, 3), (986, 2), (987, 5), (988, 16), (989, 3), + (990, 3), (991, 1), (992, 7), (993, 7), (994, 11), (995, 4), (996, 10), (997, 6), (998, 4), + (999, 2), (1000, 1), (1001, 1), (1002, 2), (1005, 1), (1008, 7), (1009, 7), (1010, 9), + (1011, 6), (1012, 1), (1013, 1), (1014, 2), (1022, 3), (1025, 1), (1026, 10), (1027, 10), + (1028, 6), (1029, 2), (1030, 6), (1031, 6), (1032, 13), (1033, 10), (1034, 3), (1035, 6), + (1036, 7), (1037, 4), (1038, 1), (1040, 1), (1041, 1), (1044, 7), (1046, 5), (1047, 11), + (1048, 4), (1050, 1), (1052, 2), (1065, 10), (1066, 9), (1067, 4), (1068, 3), (1069, 4), + (1070, 1), (1071, 4), (1072, 11), (1073, 4), (1074, 4), (1075, 1), (1076, 2), (1077, 1), + (1078, 2), (1079, 5), (1085, 1), (1086, 7), (1087, 4), (1088, 3), (1089, 2), (1104, 4), + (1105, 9), (1106, 5), (1107, 2), (1108, 4), (1109, 4), (1110, 14), (1111, 12), (1112, 8), + (1113, 2), (1114, 3), (1115, 1), (1116, 1), (1117, 4), (1118, 3), (1124, 1), (1125, 4), + (1126, 10), (1127, 3), (1141, 6), (1143, 6), (1144, 12), (1145, 5), (1146, 3), (1147, 4), + (1148, 4), (1149, 6), (1150, 7), (1151, 7), (1152, 1), (1153, 2), (1154, 1), (1155, 2), + (1156, 2), (1164, 2), (1165, 8), (1166, 6), (1167, 3), (1168, 2), (1171, 1), (1176, 1), + (1181, 1), (1182, 3), (1183, 11), (1184, 3), (1185, 4), (1186, 4), (1187, 3), (1188, 7), + (1189, 6), (1190, 5), (1191, 1), (1193, 1), (1196, 1), (1198, 3), (1202, 1), (1203, 4), + (1204, 3), (1205, 9), (1206, 7), (1207, 3), (1208, 1), (1210, 1), (1220, 4), (1221, 3), + (1222, 5), (1223, 4), (1224, 1), (1225, 2), (1226, 5), (1227, 14), (1228, 6), (1229, 4), + (1230, 4), (1231, 3), (1232, 3), (1234, 1), (1242, 5), (1243, 1), (1244, 5), (1245, 6), + (1246, 2), (1247, 3), (1248, 1), (1249, 1), (1259, 4), (1260, 1), (1261, 1), (1262, 6), + (1263, 5), (1264, 4), (1265, 3), (1266, 3), (1267, 9), (1268, 2), (1269, 7), (1270, 2), + (1281, 2), (1283, 3), (1284, 3), (1286, 3), (1287, 1), (1288, 1), (1296, 6), (1298, 1), + (1299, 1), (1300, 7), (1301, 3), (1302, 3), (1303, 1), (1304, 8), (1305, 10), (1306, 11), + (1307, 4), (1308, 3), (1311, 1), (1320, 4), (1321, 1), (1322, 1), (1323, 2), (1324, 1), + (1325, 1), (1327, 1), (1330, 2), (1338, 2), (1339, 2), (1341, 4), (1342, 2), (1343, 3), + (1344, 17), (1345, 16), (1346, 7), (1347, 2), (1348, 1), (1350, 1), (1352, 3), (1359, 3), + (1360, 1), (1362, 2), (1365, 1), (1366, 1), (1374, 2), (1375, 1), (1376, 1), (1377, 1), + (1378, 2), (1380, 1), (1381, 2), (1382, 3), (1383, 9), (1384, 7), (1385, 13), (1386, 5), + (1388, 1), (1389, 1), (1394, 1), (1396, 2), (1400, 2), (1415, 2), (1416, 1), (1417, 1), + (1418, 4), (1419, 6), (1420, 5), (1421, 2), (1422, 3), (1423, 8), (1424, 10), (1425, 5), + (1426, 1), (1428, 1), (1443, 1), (1445, 2), (1454, 1), (1455, 3), (1456, 1), (1457, 2), + (1458, 4), (1459, 4), (1460, 10), (1461, 8), (1462, 11), (1463, 5), (1464, 5), (1465, 1), + (1480, 1), (1483, 1), (1485, 1), (1494, 2), (1495, 1), (1496, 7), (1497, 7), (1498, 5), + (1499, 4), (1500, 5), (1501, 12), (1502, 10), (1503, 3), (1504, 2), (1505, 2), (1507, 3), + (1520, 1), (1529, 3), (1532, 2), (1533, 23), (1535, 14), (1536, 8), (1537, 2), (1538, 3), + (1539, 10), (1540, 11), (1541, 13), (1542, 4), (1543, 2), (1546, 1), (1548, 1), (1551, 2), + (1571, 2), (1572, 6), (1573, 4), (1574, 4), (1575, 2), (1576, 7), (1577, 5), (1578, 8), + (1579, 12), (1580, 4), (1581, 5), (1582, 1), (1586, 1), (1595, 1), (1609, 2), (1610, 2), + (1611, 3), (1612, 3), (1613, 5), (1614, 6), (1615, 1), (1616, 8), (1617, 11), (1618, 12), + (1619, 11), (1620, 5), (1621, 1), (1622, 1), (1649, 2), (1650, 2), (1651, 8), (1652, 2), + (1653, 5), (1654, 5), (1655, 2), (1656, 13), (1657, 20), (1658, 10), (1659, 8), (1660, 4), + (1661, 2), (1663, 1), (1688, 2), (1689, 2), (1690, 1), (1691, 5), (1692, 3), (1693, 5), + (1694, 8), (1695, 13), (1696, 12), (1697, 5), (1698, 1), (1699, 2), (1700, 1), (1701, 1), + (1702, 1), (1703, 1), (1705, 1), (1727, 3), (1728, 3), (1729, 2), (1730, 3), (1731, 4), + (1732, 5), (1733, 3), (1734, 7), (1735, 15), (1736, 15), (1737, 7), (1738, 6), (1739, 1), + (1741, 1), (1742, 1), (1763, 6), (1766, 8), (1767, 2), (1768, 1), (1769, 4), (1770, 5), + (1771, 1), (1772, 5), (1773, 13), (1774, 10), (1775, 9), (1776, 9), (1777, 4), (1778, 2), + (1779, 2), (1804, 1), (1805, 2), (1807, 2), (1808, 2), (1809, 3), (1810, 3), (1811, 6), + (1812, 12), (1813, 13), (1814, 9), (1815, 3), (1816, 2), (1817, 4), (1821, 2), (1844, 2), + (1845, 1), (1846, 2), (1847, 8), (1848, 6), (1849, 5), (1850, 7), (1851, 4), (1852, 3), + (1853, 9), (1854, 5), (1855, 6), (1856, 3), (1858, 1), (1860, 1), (1882, 1), (1883, 2), + (1884, 1), (1885, 4), (1886, 1), (1887, 2), (1888, 3), (1889, 2), (1890, 8), (1891, 6), + (1892, 14), (1893, 3), (1894, 1), (1895, 1), (1896, 1), (1898, 1), (1922, 6), (1923, 1), + (1924, 3), (1925, 5), (1926, 4), (1927, 6), (1928, 7), (1929, 7), (1930, 13), (1931, 11), + (1932, 8), (1933, 3), (1934, 1), (1936, 2), (1937, 2), (1938, 1), (1939, 2), (1961, 3), + (1963, 3), (1964, 2), (1965, 5), (1966, 7), (1967, 4), (1968, 5), (1969, 9), (1970, 11), + (1971, 7), (1972, 5), (1973, 3), (1974, 2), (1977, 1), (1997, 2), (2000, 2), (2001, 1), + (2002, 4), (2003, 4), (2004, 7), (2005, 3), (2006, 9), (2007, 13), (2008, 22), (2009, 8), + (2010, 10), (2011, 5), (2012, 2), (2014, 1), (2016, 1), (2021, 1), (2039, 3), (2041, 5), + (2042, 5), (2043, 8), (2044, 6), (2045, 2), (2046, 12), (2047, 10), (2048, 9), (2049, 4), + (2050, 4), (2051, 2), (2054, 3), (2062, 1), (2070, 5), (2077, 1), (2078, 4), (2079, 4), + (2080, 2), (2081, 4), (2082, 5), (2083, 7), (2084, 4), (2085, 13), (2086, 4), (2087, 7), + (2088, 6), (2089, 8), (2090, 1), (2091, 1), (2092, 4), (2113, 6), (2117, 6), (2118, 2), + (2120, 3), (2121, 5), (2122, 9), (2123, 8), (2124, 8), (2125, 9), (2126, 6), (2127, 7), + (2128, 7), (2130, 2), (2133, 1), (2156, 4), (2157, 1), (2158, 3), (2159, 1), (2160, 6), + (2161, 3), (2162, 7), (2163, 10), (2164, 9), (2165, 9), (2166, 8), (2167, 5), (2170, 3), + (2171, 1), (2193, 1), (2194, 1), (2195, 2), (2196, 2), (2197, 2), (2198, 4), (2199, 5), + (2200, 9), (2201, 5), (2202, 13), (2203, 17), (2204, 13), (2205, 11), (2206, 1), (2207, 2), + (2209, 1), (2210, 2), (2234, 7), (2235, 1), (2236, 2), (2238, 6), (2239, 9), (2240, 7), + (2241, 13), (2242, 12), (2243, 9), (2244, 6), (2245, 4), (2246, 2), (2247, 3), (2273, 2), + (2274, 4), (2275, 2), (2277, 4), (2278, 9), (2279, 7), (2280, 8), (2281, 7), (2282, 4), + (2283, 3), (2284, 2), (2285, 2), (2286, 1), (2290, 1), (2311, 2), (2312, 3), (2313, 1), + (2314, 4), (2315, 3), (2316, 3), (2317, 10), (2318, 11), (2319, 12), (2320, 11), (2321, 17), + (2322, 9), (2323, 3), (2325, 3), (2326, 4), (2341, 1), (2351, 12), (2352, 3), (2353, 4), + (2354, 5), (2355, 7), (2356, 7), (2357, 5), (2358, 8), (2359, 7), (2360, 10), (2361, 7), + (2362, 4), (2363, 2), (2364, 2), (2365, 5), (2367, 1), (2369, 1), (2390, 1), (2391, 1), + (2392, 5), (2394, 4), (2395, 6), (2396, 7), (2397, 8), (2398, 7), (2399, 5), (2400, 10), + (2401, 3), (2402, 1), (2403, 1), (2408, 5), (2412, 1), (2428, 1), (2429, 12), (2430, 2), + (2431, 4), (2433, 2), (2434, 9), (2435, 8), (2436, 10), (2437, 11), (2438, 13), (2439, 11), + (2440, 3), (2441, 1), (2442, 1), (2443, 2), (2445, 1), (2464, 2), (2468, 1), (2469, 2), + (2470, 6), (2471, 3), (2472, 3), (2473, 5), (2474, 7), (2475, 6), (2476, 13), (2477, 16), + (2478, 10), (2479, 10), (2480, 1), (2482, 1), (2483, 1), (2484, 2), (2509, 1), (2510, 2), + (2511, 8), (2512, 6), (2513, 7), (2514, 12), (2515, 10), (2516, 10), (2517, 9), (2518, 9), + (2519, 4), (2520, 2), (2521, 3), (2522, 3), (2546, 2), (2547, 1), (2548, 1), (2549, 2), + (2550, 7), (2551, 2), (2552, 5), (2553, 6), (2554, 13), (2555, 14), (2556, 8), (2557, 5), + (2558, 2), (2559, 1), (2561, 1), (2589, 5), (2590, 6), (2591, 3), (2592, 8), (2593, 10), + (2594, 14), (2595, 3), (2596, 7), (2597, 8), (2598, 2), (2599, 2), (2600, 2), (2604, 1), + (2625, 1), (2628, 2), (2629, 5), (2630, 2), (2631, 4), (2632, 9), (2633, 8), (2634, 14), + (2635, 3), (2636, 6), (2637, 2), (2638, 1), (2639, 2), (2641, 1), (2642, 1), (2643, 1), + (2664, 4), (2665, 6), (2666, 7), (2667, 3), (2668, 3), (2669, 5), (2670, 9), (2671, 11), + (2672, 12), (2673, 15), (2674, 3), (2675, 6), (2676, 1), (2677, 2), (2678, 2), (2679, 1), + (2682, 1), (2683, 2), (2703, 3), (2704, 3), (2705, 2), (2706, 4), (2707, 4), (2708, 4), + (2709, 4), (2710, 8), (2711, 8), (2712, 11), (2713, 6), (2714, 7), (2715, 2), (2716, 2), + (2717, 1), (2718, 2), (2731, 2), (2742, 1), (2743, 2), (2745, 2), (2746, 8), (2747, 3), + (2748, 5), (2749, 8), (2750, 8), (2751, 6), (2752, 4), (2753, 5), (2755, 1), (2756, 1), + (2757, 4), (2758, 1), (2760, 5), (2775, 1), (2778, 1), (2781, 2), (2782, 2), (2783, 1), + (2784, 3), (2785, 3), (2786, 2), (2787, 11), (2788, 7), (2789, 8), (2790, 9), (2791, 4), + (2792, 4), (2793, 3), (2795, 3), (2796, 4), (2797, 1), (2798, 1), (2799, 1), (2820, 2), + (2822, 1), (2823, 2), (2825, 4), (2826, 4), (2827, 6), (2828, 4), (2829, 8), (2830, 5), + (2831, 3), (2832, 2), (2835, 3), (2836, 3), (2837, 1), (2859, 3), (2861, 5), (2862, 3), + (2863, 7), (2864, 3), (2865, 6), (2866, 5), (2867, 11), (2868, 9), (2869, 5), (2870, 6), + (2871, 1), (2873, 2), (2877, 1), (2898, 6), (2900, 1), (2901, 2), (2902, 7), (2903, 4), + (2904, 2), (2905, 7), (2906, 7), (2907, 9), (2908, 4), (2909, 3), (2910, 2), (2911, 2), + (2912, 2), (2913, 1), (2916, 1), (2937, 2), (2938, 1), (2940, 4), (2941, 4), (2942, 4), + (2943, 4), (2944, 16), (2945, 11), (2946, 3), (2947, 11), (2948, 3), (2949, 2), (2950, 2), + (2951, 1), (2954, 1), (2962, 6), (2976, 1), (2977, 1), (2978, 2), (2979, 2), (2980, 3), + (2981, 3), (2982, 2), (2983, 2), (2984, 5), (2985, 11), (2986, 6), (2987, 2), (2988, 1), + (2989, 2), (2992, 1), (3015, 2), (3016, 4), (3017, 4), (3018, 2), (3019, 3), (3020, 3), + (3021, 6), (3022, 11), (3023, 10), (3024, 2), (3025, 5), (3026, 1), (3027, 3), (3029, 2), + (3035, 1), (3054, 4), (3057, 2), (3058, 3), (3059, 5), (3060, 3), (3061, 8), (3062, 5), + (3063, 4), (3064, 6), (3065, 2), (3066, 1), (3086, 1), (3092, 2), (3093, 4), (3094, 1), + (3095, 4), (3096, 1), (3097, 2), (3098, 3), (3099, 3), (3100, 5), (3101, 6), (3102, 7), + (3103, 2), (3104, 3), (3105, 4), (3110, 1), (3124, 6), (3132, 4), (3134, 3), (3135, 1), + (3136, 5), (3137, 3), (3138, 5), (3139, 8), (3140, 7), (3141, 6), (3142, 9), (3143, 1), + (3144, 2), (3145, 1), (3147, 1), (3148, 2), (3171, 2), (3172, 1), (3173, 2), (3174, 3), + (3175, 4), (3176, 4), (3177, 4), (3178, 5), (3179, 2), (3180, 8), (3181, 4), (3182, 2), + (3183, 3), (3184, 1), (3189, 1), (3194, 4), (3210, 2), (3212, 2), (3213, 3), (3214, 7), + (3215, 7), (3216, 4), (3217, 4), (3218, 8), (3219, 5), (3220, 4), (3221, 1), (3223, 1), + (3249, 2), (3250, 2), (3251, 1), (3252, 2), (3253, 4), (3254, 5), (3255, 4), (3256, 6), + (3257, 4), (3258, 8), (3259, 4), (3260, 3), (3261, 2), (3262, 1), (3288, 3), (3290, 3), + (3291, 2), (3292, 4), (3293, 2), (3294, 4), (3295, 5), (3296, 11), (3297, 10), (3298, 2), + (3299, 4), (3300, 1), (3301, 2), (3303, 1), (3306, 1), (3327, 1), (3329, 2), (3330, 6), + (3331, 5), (3332, 2), (3333, 1), (3334, 5), (3335, 6), (3336, 5), (3337, 5), (3338, 2), + (3340, 1), (3342, 1), (3366, 13), (3368, 4), (3369, 2), (3370, 5), (3371, 5), (3372, 4), + (3373, 3), (3374, 7), (3375, 5), (3376, 2), (3377, 1), (3378, 1), (3380, 1), (3382, 1), + (3389, 6), (3394, 1), (3405, 6), (3406, 1), (3407, 2), (3408, 3), (3409, 5), (3410, 2), + (3411, 3), (3412, 4), (3413, 5), (3414, 6), (3415, 5), (3417, 2), (3418, 1), (3421, 1), + (3423, 1), (3424, 1), (3444, 3), (3445, 1), (3447, 3), (3448, 1), (3449, 2), (3450, 4), + (3451, 5), (3452, 6), (3453, 8), (3454, 6), (3455, 2), (3456, 4), (3477, 1), (3483, 1), + (3484, 4), (3485, 5), (3486, 2), (3487, 3), (3488, 3), (3489, 6), (3490, 8), (3491, 6), + (3492, 8), (3493, 5), (3494, 2), (3499, 1), (3512, 4), (3522, 1), (3523, 2), (3524, 3), + (3525, 3), (3526, 6), (3527, 5), (3528, 3), (3529, 10), (3530, 10), (3531, 7), (3532, 4), + (3533, 3), (3534, 1), (3535, 2), (3561, 1), (3562, 2), (3563, 3), (3564, 3), (3565, 2), + (3566, 6), (3567, 2), (3568, 2), (3569, 14), (3570, 7), (3571, 2), (3572, 2), (3573, 1), + (3574, 2), (3575, 1), (3576, 1), (3600, 4), (3601, 3), (3602, 5), (3603, 3), (3604, 4), + (3605, 4), (3606, 7), (3607, 8), (3608, 5), (3609, 3), (3610, 3), (3639, 3), (3640, 1), + (3641, 1), (3642, 5), (3643, 2), (3644, 6), (3645, 4), (3646, 4), (3647, 3), (3648, 2), + (3649, 1), (3650, 2), (3651, 1), (3678, 1), (3680, 4), (3681, 2), (3682, 7), (3683, 2), + (3684, 6), (3685, 4), (3686, 4), (3687, 4), (3688, 3), (3690, 2), (3691, 2), (3692, 1), + (3694, 1), (3717, 1), (3718, 1), (3719, 3), (3720, 5), (3721, 5), (3722, 8), (3723, 3), + (3724, 2), (3725, 2), (3726, 2), (3727, 4), (3728, 1), (3731, 1), (3732, 2), (3733, 1), + (3756, 4), (3758, 13), (3759, 2), (3760, 7), (3761, 3), (3762, 4), (3763, 2), (3764, 6), + (3765, 1), (3766, 2), (3769, 1), (3795, 1), (3797, 3), (3798, 4), (3799, 9), (3800, 3), + (3801, 6), (3802, 5), (3803, 2), (3804, 5), (3805, 2), (3807, 1), (3808, 1), (3834, 1), + (3835, 1), (3836, 4), (3837, 1), (3838, 4), (3839, 5), (3840, 4), (3841, 7), (3842, 8), + (3843, 5), (3844, 1), (3845, 3), (3846, 2), (3847, 1), (3874, 4), (3875, 3), (3876, 7), + (3877, 7), (3878, 3), (3879, 3), (3880, 2), (3881, 5), (3882, 3), (3883, 4), (3884, 1), + (3885, 1), (3886, 1), (3913, 1), (3914, 3), (3915, 4), (3916, 4), (3917, 6), (3920, 2), + (3921, 5), (3922, 4), (3923, 1), (3925, 1), (3928, 1), (3929, 1), (3951, 1), (3952, 1), + (3953, 3), (3954, 2), (3955, 1), (3956, 8), (3957, 4), (3958, 5), (3959, 3), (3960, 5), + (3961, 3), (3962, 1), (3963, 2), (3964, 1), (3991, 3), (3992, 4), (3993, 2), (3994, 5), + (3995, 3), (3996, 6), (3997, 8), (3998, 4), (3999, 4), (4000, 1), (4001, 3), (4002, 1), + (4003, 1), (4031, 2), (4032, 4), (4033, 7), (4034, 4), (4035, 3), (4036, 3), (4037, 1), + (4038, 3), (4039, 5), (4040, 4), (4041, 1), (4069, 1), (4070, 3), (4071, 4), (4072, 1), + (4073, 2), (4074, 4), (4075, 1), (4076, 2), (4077, 5), (4078, 4), (4079, 2), (4083, 1), + (4107, 1), (4108, 2), (4109, 2), (4110, 3), (4111, 4), (4112, 4), (4113, 6), (4114, 1), + (4115, 5), (4116, 1), (4117, 3), (4119, 1), (4120, 1), (4147, 2), (4148, 4), (4150, 3), + (4151, 3), (4152, 2), (4153, 5), (4154, 4), (4155, 4), (4156, 3), (4157, 3), (4158, 2), + (4161, 1), (4185, 2), (4187, 2), (4188, 7), (4189, 5), (4190, 2), (4191, 1), (4192, 5), + (4193, 2), (4194, 3), (4195, 2), (4196, 2), (4197, 2), (4198, 2), (4224, 2), (4225, 2), + (4226, 1), (4227, 2), (4228, 4), (4229, 4), (4230, 3), (4231, 3), (4232, 3), (4233, 3), + (4234, 3), (4236, 1), (4259, 2), (4263, 4), (4264, 1), (4265, 2), (4266, 4), (4267, 3), + (4268, 1), (4269, 5), (4270, 5), (4271, 4), (4272, 3), (4273, 3), (4274, 2), (4277, 1), + (4280, 5), (4300, 2), (4302, 3), (4303, 2), (4304, 4), (4305, 6), (4306, 2), (4307, 3), + (4308, 2), (4309, 4), (4310, 7), (4311, 2), (4312, 4), (4313, 4), (4314, 1), (4342, 1), + (4343, 3), (4344, 7), (4345, 7), (4346, 2), (4347, 2), (4348, 6), (4349, 3), (4350, 3), + (4351, 3), (4352, 2), (4353, 2), (4354, 1), (4356, 2), (4380, 4), (4383, 8), (4385, 3), + (4386, 8), (4387, 3), (4388, 5), (4389, 1), (4390, 1), (4391, 2), (4392, 2), (4393, 2), + (4419, 4), (4420, 2), (4421, 3), (4422, 5), (4423, 7), (4424, 3), (4425, 5), (4426, 5), + (4427, 3), (4428, 4), (4429, 1), (4430, 3), (4431, 1), (4432, 7), (4434, 1), (4458, 5), + (4460, 3), (4461, 2), (4462, 6), (4463, 3), (4464, 3), (4465, 3), (4466, 10), (4467, 3), + (4468, 2), (4469, 2), (4470, 1), (4473, 1), (4498, 2), (4500, 3), (4501, 8), (4502, 3), + (4503, 1), (4504, 6), (4505, 3), (4506, 3), (4507, 1), (4508, 2), (4509, 2), (4510, 2), + (4511, 2), (4536, 1), (4538, 3), (4539, 5), (4540, 3), (4541, 6), (4542, 2), (4543, 4), + (4544, 3), (4545, 3), (4546, 1), (4547, 1), (4550, 1), (4575, 3), (4576, 1), (4577, 5), + (4578, 3), (4579, 8), (4580, 3), (4581, 4), (4582, 4), (4583, 4), (4584, 5), (4587, 3), + (4588, 2), (4614, 1), (4616, 1), (4617, 4), (4618, 4), (4619, 1), (4620, 3), (4621, 3), + (4622, 2), (4623, 4), (4624, 3), (4627, 2), (4628, 2), (4653, 2), (4655, 3), (4656, 3), + (4657, 4), (4658, 3), (4659, 4), (4660, 3), (4661, 2), (4662, 7), (4663, 7), (4664, 1), + (4665, 2), (4666, 1), (4693, 1), (4694, 2), (4695, 2), (4696, 5), (4699, 1), (4700, 4), + (4701, 3), (4702, 2), (4703, 1), (4704, 1), (4731, 3), (4733, 2), (4734, 6), (4735, 1), + (4736, 2), (4737, 3), (4738, 3), (4739, 3), (4740, 4), (4741, 2), (4742, 3), (4743, 2), + (4744, 2), (4770, 1), (4771, 3), (4772, 2), (4773, 4), (4774, 5), (4775, 3), (4776, 5), + (4777, 8), (4778, 1), (4779, 2), (4780, 3), (4781, 1), (4782, 1), (4785, 2), (4809, 2), + (4811, 2), (4812, 6), (4813, 4), (4814, 1), (4815, 2), (4816, 2), (4817, 1), (4818, 5), + (4819, 2), (4820, 1), (4821, 2), (4834, 1), (4848, 1), (4850, 3), (4851, 2), (4852, 4), + (4853, 1), (4854, 1), (4855, 3), (4856, 8), (4857, 2), (4858, 2), (4859, 2), (4860, 2), + (4862, 2), (4887, 2), (4888, 1), (4890, 3), (4891, 4), (4893, 3), (4894, 2), (4895, 4), + (4896, 6), (4897, 3), (4899, 1), (4900, 1), (4926, 2), (4927, 1), (4928, 4), (4929, 2), + (4930, 2), (4931, 2), (4932, 4), (4933, 7), (4934, 1), (4935, 3), (4937, 1), (4938, 2), + (4939, 1), (4942, 1), (4964, 1), (4965, 1), (4966, 1), (4968, 1), (4969, 5), (4970, 5), + (4971, 3), (4972, 1), (4973, 7), (4974, 1), (4975, 2), (4977, 1), (4978, 1), (4979, 2), + (5004, 3), (5005, 2), (5006, 1), (5007, 1), (5008, 2), (5009, 3), (5010, 1), (5011, 4), + (5012, 4), (5013, 1), (5014, 2), (5015, 5), (5016, 1), (5018, 2), (5019, 1), (5043, 2), + (5046, 6), (5047, 1), (5048, 1), (5049, 1), (5050, 1), (5051, 1), (5052, 5), (5053, 4), + (5054, 2), (5055, 1), (5056, 1), (5082, 1), (5083, 1), (5084, 4), (5085, 4), (5086, 5), + (5087, 2), (5089, 1), (5090, 3), (5091, 6), (5092, 1), (5093, 1), (5094, 4), (5096, 1), + (5098, 2), (5121, 2), (5123, 3), (5124, 4), (5125, 1), (5126, 3), (5127, 1), (5128, 5), + (5130, 2), (5131, 1), (5132, 1), (5133, 2), (5134, 2), (5135, 1), (5136, 2), (5137, 1), + (5160, 1), (5162, 4), (5163, 1), (5164, 3), (5166, 1), (5167, 2), (5168, 8), (5169, 4), + (5170, 1), (5173, 1), (5198, 1), (5201, 2), (5202, 4), (5204, 1), (5205, 1), (5206, 1), + (5207, 3), (5208, 1), (5209, 5), (5210, 3), (5211, 1), (5213, 2), (5215, 1), (5238, 1), + (5239, 6), (5241, 1), (5242, 2), (5243, 2), (5244, 2), (5245, 2), (5246, 4), (5247, 5), + (5248, 3), (5250, 2), (5252, 2), (5280, 3), (5281, 1), (5283, 4), (5284, 2), (5285, 2), + (5286, 1), (5288, 3), (5289, 1), (5290, 1), (5291, 1), (5317, 1), (5318, 2), (5319, 2), + (5321, 3), (5322, 2), (5323, 6), (5324, 1), (5325, 1), (5326, 2), (5327, 3), (5328, 2), + (5329, 2), (5330, 1), (5331, 1), (5356, 1), (5357, 3), (5358, 4), (5360, 1), (5361, 1), + (5362, 2), (5363, 1), (5364, 1), (5366, 2), (5367, 1), (5369, 1), (5395, 2), (5396, 2), + (5397, 2), (5398, 2), (5400, 2), (5401, 2), (5402, 4), (5403, 3), (5404, 1), (5405, 3), + (5406, 1), (5408, 1), (5434, 1), (5435, 2), (5436, 2), (5437, 1), (5438, 4), (5439, 3), + (5440, 3), (5441, 5), (5442, 1), (5443, 1), (5445, 3), (5474, 4), (5475, 1), (5476, 3), + (5477, 1), (5478, 2), (5479, 2), (5480, 4), (5481, 5), (5482, 2), (5485, 2), (5486, 1), + (5512, 1), (5513, 2), (5514, 4), (5515, 4), (5517, 2), (5518, 2), (5519, 2), (5520, 4), + (5521, 2), (5523, 1), (5524, 3), (5525, 9), (5526, 1), (5542, 3), (5551, 1), (5552, 1), + (5553, 1), (5554, 4), (5555, 4), (5556, 1), (5557, 5), (5558, 3), (5559, 1), (5560, 2), + (5563, 1), (5564, 1), (5565, 2), (5566, 1), (5590, 1), (5591, 3), (5592, 5), (5593, 4), + (5594, 1), (5595, 1), (5596, 1), (5597, 3), (5598, 3), (5599, 3), (5601, 2), (5602, 2), + (5603, 1), (5604, 2), (5620, 6), (5628, 1), (5629, 1), (5630, 1), (5631, 1), (5632, 1), + (5633, 3), (5634, 2), (5635, 2), (5636, 2), (5637, 2), (5638, 4), (5639, 3), (5640, 1), + (5641, 1), (5642, 1), (5643, 2), (5668, 1), (5669, 1), (5670, 2), (5671, 3), (5672, 2), + (5673, 2), (5675, 1), (5676, 2), (5677, 2), (5678, 1), (5680, 2), (5706, 1), (5707, 1), + (5709, 2), (5710, 2), (5712, 4), (5713, 1), (5714, 3), (5715, 4), (5718, 1), (5719, 3), + (5721, 1), (5745, 5), (5746, 2), (5747, 2), (5748, 2), (5749, 2), (5750, 3), (5751, 3), + (5753, 2), (5754, 1), (5755, 2), (5756, 3), (5757, 1), (5759, 1), (5785, 2), (5786, 2), + (5787, 4), (5788, 2), (5789, 6), (5790, 5), (5791, 3), (5792, 3), (5793, 2), (5794, 1), + (5795, 1), (5797, 2), (5798, 2), (5799, 1), (5801, 1), (5825, 3), (5826, 1), (5827, 3), + (5828, 3), (5829, 5), (5831, 3), (5832, 5), (5833, 2), (5834, 1), (5835, 2), (5839, 2), + (5862, 1), (5863, 1), (5865, 3), (5868, 1), (5869, 3), (5870, 2), (5871, 4), (5872, 2), + (5874, 2), (5875, 3), (5876, 3), (5901, 1), (5903, 2), (5904, 1), (5905, 1), (5906, 1), + (5907, 3), (5908, 3), (5909, 1), (5910, 2), (5911, 2), (5912, 2), (5914, 1), (5915, 3), + (5917, 1), (5941, 1), (5942, 2), (5943, 2), (5944, 2), (5945, 2), (5946, 2), (5947, 4), + (5948, 1), (5949, 1), (5950, 2), (5951, 2), (5952, 2), (5953, 2), (5955, 2), (5957, 2), + (5980, 1), (5981, 2), (5982, 4), (5984, 3), (5985, 2), (5986, 2), (5987, 3), (5989, 4), + (5991, 2), (5993, 2), (5994, 2), (5995, 2), (5996, 1), (6019, 1), (6021, 2), (6022, 1), + (6023, 1), (6024, 5), (6025, 2), (6026, 1), (6027, 3), (6028, 6), (6030, 1), (6031, 1), + (6032, 1), (6034, 1), (6059, 4), (6060, 2), (6061, 3), (6062, 1), (6063, 1), (6065, 4), + (6066, 2), (6067, 2), (6068, 1), (6069, 2), (6070, 3), (6071, 2), (6073, 1), (6074, 2), + (6098, 1), (6099, 1), (6100, 1), (6101, 1), (6102, 3), (6103, 1), (6104, 2), (6105, 6), + (6106, 3), (6107, 1), (6108, 2), (6111, 2), (6112, 1), (6114, 1), (6130, 1), (6135, 1), + (6137, 1), (6138, 2), (6139, 1), (6141, 4), (6142, 1), (6143, 2), (6144, 1), (6146, 1), + (6148, 2), (6150, 2), (6151, 1), (6177, 3), (6178, 2), (6179, 2), (6180, 2), (6181, 2), + (6182, 1), (6185, 1), (6186, 2), (6187, 1), (6188, 2), (6189, 2), (6190, 2), (6215, 2), + (6216, 3), (6217, 3), (6218, 1), (6219, 3), (6220, 3), (6221, 6), (6222, 2), (6223, 3), + (6224, 3), (6225, 1), (6226, 2), (6227, 1), (6228, 1), (6254, 1), (6255, 1), (6256, 1), + (6257, 1), (6258, 1), (6259, 3), (6260, 3), (6261, 2), (6262, 2), (6264, 2), (6266, 1), + (6292, 1), (6293, 1), (6294, 1), (6295, 1), (6296, 3), (6298, 3), (6299, 5), (6300, 2), + (6301, 2), (6302, 2), (6303, 3), (6304, 1), (6305, 2), (6306, 2), (6307, 1), (6308, 2), + (6324, 1), (6330, 1), (6331, 2), (6332, 2), (6333, 4), (6334, 2), (6335, 1), (6337, 3), + (6338, 1), (6339, 1), (6341, 2), (6342, 2), (6343, 1), (6344, 2), (6345, 1), (6347, 1), + (6372, 1), (6374, 4), (6375, 2), (6376, 2), (6378, 3), (6379, 5), (6382, 1), (6383, 3), + (6384, 1), (6386, 1), (6402, 8), (6408, 1), (6410, 2), (6413, 1), (6414, 2), (6415, 1), + (6416, 2), (6417, 3), (6418, 3), (6419, 3), (6420, 1), (6421, 1), (6423, 2), (6426, 1), + (6430, 1), (6447, 1), (6448, 2), (6451, 2), (6452, 3), (6453, 2), (6454, 1), (6455, 4), + (6456, 3), (6457, 3), (6459, 3), (6461, 2), (6462, 2), (6463, 1), (6486, 2), (6490, 1), + (6492, 3), (6493, 1), (6494, 5), (6495, 3), (6496, 2), (6497, 2), (6498, 4), (6499, 2), + (6500, 1), (6501, 3), (6502, 1), (6503, 3), (6504, 1), (6505, 1), (6527, 1), (6528, 2), + (6530, 2), (6531, 4), (6533, 2), (6535, 1), (6536, 2), (6537, 1), (6538, 2), (6541, 1), + (6564, 1), (6565, 1), (6566, 1), (6567, 1), (6569, 3), (6570, 4), (6571, 2), (6572, 2), + (6573, 4), (6574, 5), (6575, 1), (6576, 1), (6577, 2), (6578, 2), (6579, 2), (6580, 1), + (6581, 1), (6582, 1), (6603, 2), (6604, 2), (6605, 1), (6606, 1), (6607, 1), (6608, 1), + (6609, 3), (6610, 3), (6611, 1), (6612, 2), (6613, 1), (6614, 2), (6615, 1), (6617, 4), + (6618, 4), (6619, 1), (6620, 4), (6644, 1), (6645, 1), (6646, 1), (6647, 1), (6648, 5), + (6649, 2), (6650, 1), (6651, 1), (6652, 3), (6653, 2), (6654, 3), (6655, 1), (6656, 2), + (6657, 2), (6658, 2), (6686, 1), (6687, 4), (6688, 5), (6689, 4), (6690, 1), (6692, 1), + (6693, 1), (6694, 3), (6695, 3), (6696, 1), (6697, 1), (6722, 2), (6723, 1), (6724, 1), + (6725, 3), (6726, 1), (6727, 2), (6728, 2), (6729, 6), (6731, 1), (6734, 1), (6735, 3), + (6736, 3), (6737, 1), (6761, 2), (6762, 1), (6763, 3), (6764, 2), (6765, 1), (6766, 5), + (6767, 1), (6769, 3), (6770, 2), (6771, 3), (6772, 3), (6773, 3), (6774, 4), (6775, 1), + (6777, 1), (6798, 1), (6800, 2), (6801, 1), (6802, 3), (6803, 2), (6804, 3), (6805, 2), + (6806, 7), (6807, 1), (6808, 2), (6809, 2), (6810, 4), (6811, 2), (6812, 3), (6813, 2), + (6814, 1), (6815, 1), (6816, 2), (6837, 1), (6839, 1), (6841, 5), (6842, 3), (6843, 4), + (6844, 5), (6845, 1), (6847, 3), (6848, 1), (6849, 2), (6850, 3), (6851, 1), (6852, 2), + (6853, 2), (6855, 1), (6863, 6), (6878, 1), (6879, 2), (6881, 2), (6882, 3), (6883, 2), + (6884, 4), (6885, 4), (6886, 2), (6887, 3), (6888, 3), (6889, 3), (6890, 1), (6891, 2), + (6892, 2), (6896, 1), (6915, 1), (6916, 2), (6917, 2), (6918, 1), (6919, 1), (6921, 1), + (6922, 2), (6923, 8), (6924, 3), (6926, 7), (6927, 2), (6928, 2), (6929, 1), (6932, 1), + (6952, 6), (6956, 1), (6957, 4), (6959, 5), (6960, 2), (6961, 6), (6962, 6), (6963, 1), + (6964, 2), (6965, 5), (6967, 4), (6969, 1), (6970, 3), (6971, 1), (6972, 1), (6993, 1), + (6995, 2), (6996, 1), (6997, 2), (6998, 1), (6999, 1), (7000, 5), (7001, 2), (7002, 4), + (7003, 3), (7004, 1), (7005, 1), (7007, 2), (7008, 2), (7009, 1), (7010, 1), (7014, 1), + (7033, 1), (7035, 2), (7037, 1), (7038, 3), (7039, 2), (7040, 8), (7041, 1), (7042, 2), + (7043, 2), (7044, 1), (7045, 1), (7046, 2), (7047, 1), (7048, 2), (7070, 1), (7073, 1), + (7075, 1), (7076, 1), (7077, 1), (7078, 3), (7079, 5), (7080, 4), (7081, 4), (7083, 1), + (7084, 2), (7085, 4), (7086, 2), (7088, 2), (7089, 3), (7098, 6), (7111, 1), (7113, 1), + (7114, 3), (7115, 7), (7117, 3), (7118, 6), (7119, 1), (7120, 2), (7121, 2), (7122, 3), + (7123, 1), (7125, 2), (7126, 2), (7130, 1), (7153, 5), (7155, 2), (7156, 4), (7157, 3), + (7158, 2), (7159, 1), (7160, 2), (7161, 1), (7162, 2), (7163, 4), (7164, 3), (7167, 3), + (7184, 2), (7190, 1), (7192, 1), (7194, 1), (7196, 4), (7198, 1), (7199, 2), (7200, 4), + (7201, 4), (7202, 2), (7203, 1), (7204, 2), (7230, 2), (7231, 1), (7232, 3), (7233, 3), + (7234, 1), (7235, 2), (7236, 3), (7238, 2), (7239, 4), (7240, 1), (7241, 3), (7242, 3), + (7243, 2), (7244, 1), (7245, 1), (7248, 1), (7266, 1), (7268, 1), (7270, 2), (7271, 4), + (7272, 1), (7273, 2), (7274, 6), (7275, 2), (7278, 3), (7279, 4), (7280, 2), (7281, 1), + (7282, 2), (7283, 1), (7289, 1), (7306, 1), (7307, 1), (7308, 2), (7309, 1), (7310, 2), + (7311, 2), (7312, 3), (7313, 3), (7314, 1), (7315, 4), (7316, 3), (7317, 2), (7318, 4), + (7319, 1), (7320, 2), (7321, 1), (7324, 1), (7345, 1), (7347, 2), (7348, 6), (7349, 2), + (7350, 6), (7351, 8), (7352, 2), (7353, 4), (7358, 2), (7359, 2), (7360, 2), (7361, 2), + (7372, 6), (7385, 1), (7386, 3), (7387, 1), (7388, 1), (7389, 3), (7390, 3), (7391, 1), + (7392, 4), (7394, 3), (7395, 3), (7396, 4), (7397, 2), (7398, 4), (7399, 2), (7401, 1), + (7403, 1), (7425, 1), (7426, 2), (7427, 5), (7428, 4), (7429, 5), (7430, 4), (7431, 1), + (7432, 1), (7434, 1), (7435, 2), (7436, 7), (7437, 1), (7438, 1), (7439, 1), (7446, 1), + (7464, 1), (7466, 2), (7467, 3), (7468, 2), (7469, 5), (7470, 3), (7471, 2), (7472, 1), + (7474, 1), (7475, 4), (7476, 4), (7489, 1), (7490, 6), (7503, 1), (7504, 2), (7505, 3), + (7506, 2), (7507, 2), (7508, 2), (7509, 1), (7510, 2), (7511, 3), (7512, 3), (7513, 5), + (7514, 1), (7515, 4), (7517, 1), (7518, 1), (7520, 1), (7522, 1), (7539, 1), (7541, 2), + (7544, 6), (7545, 3), (7546, 2), (7547, 5), (7548, 3), (7549, 2), (7550, 1), (7552, 1), + (7553, 5), (7554, 2), (7555, 2), (7556, 1), (7558, 1), (7559, 1), (7583, 2), (7584, 3), + (7585, 5), (7586, 3), (7587, 2), (7588, 5), (7589, 1), (7591, 2), (7592, 3), (7593, 4), + (7594, 1), (7595, 2), (7596, 2), (7620, 1), (7621, 3), (7623, 5), (7624, 3), (7625, 3), + (7626, 3), (7627, 4), (7628, 5), (7629, 1), (7630, 1), (7631, 1), (7632, 3), (7633, 2), + (7634, 1), (7635, 1), (7639, 1), (7648, 6), (7655, 6), (7659, 2), (7660, 2), (7662, 2), + (7663, 1), (7664, 3), (7665, 6), (7667, 1), (7670, 3), (7671, 3), (7672, 1), (7673, 2), + (7674, 1), (7675, 1), (7676, 1), (7685, 1), (7699, 2), (7700, 2), (7701, 5), (7702, 3), + (7703, 5), (7704, 3), (7705, 1), (7706, 2), (7707, 5), (7708, 4), (7709, 2), (7710, 1), + (7713, 1), (7714, 1), (7738, 2), (7739, 2), (7740, 3), (7741, 4), (7742, 3), (7743, 2), + (7744, 4), (7745, 3), (7746, 1), (7748, 2), (7750, 3), (7751, 1), (7752, 2), (7753, 1), + (7776, 2), (7777, 3), (7778, 2), (7779, 2), (7780, 3), (7781, 3), (7782, 5), (7783, 4), + (7784, 2), (7786, 4), (7787, 2), (7788, 2), (7789, 4), (7794, 1), (7812, 1), (7816, 1), + (7817, 3), (7818, 2), (7819, 3), (7820, 3), (7821, 8), (7822, 3), (7823, 3), (7824, 3), + (7825, 2), (7827, 1), (7828, 3), (7830, 2), (7831, 1), (7836, 6), (7851, 1), (7853, 1), + (7855, 1), (7857, 1), (7858, 1), (7859, 2), (7860, 3), (7861, 1), (7863, 1), (7864, 6), + (7865, 4), (7866, 4), (7867, 4), (7868, 1), (7869, 1), (7871, 1), (7894, 2), (7895, 5), + (7896, 6), (7897, 5), (7898, 1), (7899, 1), (7900, 1), (7901, 3), (7902, 1), (7903, 1), + (7904, 9), (7905, 2), (7906, 1), (7907, 2), (7909, 1), (7910, 1), (7932, 3), (7933, 9), + (7934, 1), (7935, 4), (7936, 3), (7937, 7), (7938, 2), (7939, 4), (7940, 3), (7941, 1), + (7942, 2), (7943, 4), (7944, 2), (7945, 5), (7946, 2), (7948, 1), (7949, 1), (7960, 6), + (7967, 2), (7970, 2), (7972, 2), (7973, 1), (7974, 2), (7975, 1), (7976, 3), (7977, 2), + (7978, 2), (7979, 1), (7980, 5), (7981, 1), (7982, 2), (7983, 3), (7984, 3), (7985, 1), + (7986, 4), (7987, 1), (7988, 1), (8011, 4), (8012, 5), (8013, 1), (8014, 3), (8015, 3), + (8016, 1), (8017, 5), (8018, 1), (8019, 3), (8021, 1), (8022, 6), (8023, 4), (8024, 1), + (8025, 1), (8027, 1), (8028, 2), (8029, 2), (8050, 2), (8051, 3), (8052, 1), (8053, 6), + (8054, 3), (8055, 1), (8056, 2), (8057, 4), (8058, 2), (8059, 4), (8060, 3), (8061, 3), + (8062, 2), (8063, 1), (8064, 2), (8065, 1), (8066, 1), (8067, 1), (8079, 1), (8088, 2), + (8090, 2), (8091, 5), (8092, 3), (8093, 4), (8094, 1), (8095, 3), (8096, 2), (8097, 3), + (8098, 2), (8099, 2), (8100, 2), (8101, 2), (8103, 6), (8104, 1), (8106, 1), (8108, 1), + (8128, 2), (8129, 3), (8130, 13), (8131, 4), (8132, 2), (8133, 2), (8134, 3), (8136, 2), + (8137, 2), (8139, 7), (8140, 7), (8141, 3), (8142, 1), (8143, 2), (8145, 1), (8167, 1), + (8168, 1), (8169, 5), (8171, 6), (8172, 2), (8173, 1), (8174, 2), (8175, 1), (8176, 1), + (8177, 7), (8180, 2), (8182, 1), (8206, 1), (8207, 6), (8208, 4), (8209, 5), (8210, 3), + (8211, 7), (8212, 4), (8213, 3), (8214, 4), (8215, 2), (8216, 4), (8217, 2), (8218, 4), + (8219, 3), (8220, 2), (8221, 1), (8222, 1), (8240, 6), (8244, 2), (8245, 1), (8246, 2), + (8247, 5), (8248, 6), (8249, 1), (8250, 1), (8251, 2), (8252, 5), (8253, 1), (8254, 7), + (8255, 4), (8256, 2), (8257, 3), (8258, 4), (8259, 2), (8260, 3), (8261, 1), (8282, 1), + (8284, 2), (8285, 3), (8286, 4), (8287, 5), (8288, 1), (8289, 3), (8290, 4), (8291, 3), + (8292, 2), (8294, 1), (8295, 1), (8296, 3), (8297, 3), (8298, 2), (8299, 2), (8302, 1), + (8314, 1), (8320, 1), (8321, 1), (8322, 1), (8323, 1), (8324, 2), (8325, 2), (8326, 2), + (8327, 2), (8328, 4), (8329, 2), (8330, 1), (8331, 1), (8332, 4), (8333, 3), (8334, 3), + (8335, 3), (8336, 1), (8337, 1), (8339, 2), (8340, 1), (8342, 6), (8360, 1), (8362, 1), + (8363, 5), (8364, 6), (8365, 3), (8366, 2), (8367, 6), (8368, 2), (8369, 2), (8370, 3), + (8372, 5), (8373, 2), (8374, 7), (8375, 3), (8377, 2), (8398, 1), (8400, 2), (8402, 2), + (8403, 4), (8404, 1), (8405, 2), (8406, 2), (8407, 2), (8408, 4), (8409, 3), (8410, 4), + (8411, 3), (8412, 2), (8413, 2), (8414, 5), (8415, 2), (8416, 1), (8439, 2), (8440, 1), + (8441, 3), (8442, 4), (8443, 2), (8444, 5), (8445, 2), (8446, 1), (8447, 3), (8448, 1), + (8449, 4), (8450, 3), (8451, 6), (8452, 2), (8453, 3), (8455, 3), (8456, 2), (8465, 1), + (8480, 4), (8481, 5), (8482, 7), (8483, 4), (8484, 2), (8485, 3), (8487, 1), (8488, 3), + (8489, 3), (8490, 6), (8491, 4), (8492, 5), (8495, 1), (8518, 2), (8519, 1), (8520, 3), + (8521, 1), (8522, 4), (8523, 2), (8524, 1), (8525, 1), (8526, 2), (8527, 5), (8528, 1), + (8529, 2), (8530, 5), (8531, 4), (8532, 3), (8533, 3), (8534, 1), (8536, 1), (8557, 4), + (8558, 4), (8559, 3), (8561, 3), (8562, 1), (8563, 1), (8564, 1), (8566, 1), (8567, 1), + (8568, 4), (8569, 2), (8570, 6), (8571, 4), (8572, 4), (8573, 3), (8574, 1), (8575, 1), + (8576, 6), (8583, 1), (8587, 4), (8596, 1), (8597, 3), (8598, 1), (8599, 3), (8600, 2), + (8601, 2), (8602, 2), (8603, 2), (8604, 1), (8605, 2), (8606, 2), (8607, 2), (8608, 1), + (8609, 2), (8610, 2), (8611, 2), (8612, 2), (8633, 1), (8634, 8), (8635, 3), (8636, 1), + (8637, 3), (8638, 3), (8639, 1), (8640, 2), (8641, 1), (8642, 2), (8643, 2), (8645, 4), + (8646, 2), (8647, 8), (8648, 5), (8649, 1), (8650, 3), (8653, 5), (8673, 1), (8675, 1), + (8676, 1), (8677, 5), (8678, 4), (8679, 4), (8680, 2), (8681, 3), (8682, 3), (8683, 3), + (8684, 2), (8685, 2), (8686, 2), (8687, 1), (8688, 3), (8689, 2), (8701, 6), (8705, 6), + (8710, 1), (8712, 1), (8713, 1), (8714, 1), (8716, 1), (8717, 6), (8718, 2), (8719, 2), + (8721, 1), (8723, 6), (8724, 1), (8725, 1), (8726, 2), (8727, 1), (8728, 1), (8731, 1), + (8753, 1), (8754, 3), (8755, 2), (8756, 1), (8757, 1), (8759, 6), (8760, 1), (8762, 2), + (8763, 3), (8764, 3), (8765, 2), (8768, 2), (8770, 2), (8791, 2), (8793, 1), (8794, 2), + (8795, 1), (8796, 1), (8797, 1), (8799, 1), (8800, 3), (8801, 3), (8802, 2), (8803, 4), + (8804, 6), (8805, 3), (8809, 1), (8816, 1), (8827, 1), (8829, 1), (8830, 1), (8832, 2), + (8833, 5), (8834, 3), (8835, 2), (8836, 1), (8837, 3), (8838, 2), (8839, 1), (8840, 3), + (8841, 3), (8842, 2), (8843, 2), (8845, 1), (8869, 2), (8870, 6), (8871, 1), (8872, 6), + (8875, 5), (8876, 4), (8877, 1), (8878, 5), (8879, 2), (8880, 3), (8882, 1), (8884, 3), + (8885, 1), (8886, 1), (8887, 6), (8888, 1), (8909, 1), (8910, 1), (8911, 2), (8912, 2), + (8914, 3), (8917, 5), (8918, 1), (8919, 6), (8920, 3), (8921, 4), (8922, 6), (8923, 1), + (8928, 1), (8946, 1), (8948, 1), (8949, 2), (8950, 9), (8951, 2), (8952, 2), (8953, 2), + (8954, 2), (8956, 2), (8957, 1), (8958, 3), (8959, 5), (8960, 1), (8961, 4), (8962, 2), + (8985, 1), (8987, 1), (8990, 2), (8991, 3), (8992, 2), (8993, 2), (8994, 1), (8995, 1), + (8997, 6), (8998, 3), (8999, 1), (9001, 1), (9002, 1), (9003, 1), (9004, 5), (9007, 5), + (9026, 1), (9027, 2), (9028, 3), (9029, 2), (9030, 2), (9031, 1), (9034, 1), (9035, 3), + (9036, 2), (9037, 4), (9038, 5), (9039, 2), (9064, 2), (9065, 1), (9066, 2), (9067, 4), + (9069, 3), (9070, 2), (9071, 3), (9072, 2), (9074, 2), (9075, 3), (9076, 1), (9078, 3), + (9079, 2), (9080, 1), (9087, 1), (9104, 1), (9106, 1), (9107, 2), (9108, 1), (9109, 1), + (9110, 1), (9111, 2), (9112, 1), (9113, 2), (9114, 3), (9115, 1), (9116, 2), (9117, 3), + (9120, 1), (9139, 1), (9145, 3), (9146, 1), (9147, 5), (9148, 1), (9149, 3), (9150, 3), + (9151, 3), (9152, 2), (9153, 9), (9154, 1), (9155, 2), (9156, 1), (9157, 1), (9181, 1), + (9183, 4), (9184, 7), (9185, 1), (9186, 1), (9187, 1), (9189, 2), (9190, 1), (9191, 1), + (9192, 4), (9193, 3), (9194, 1), (9195, 2), (9196, 1), (9197, 2), (9198, 1), (9204, 6), + (9219, 1), (9221, 3), (9222, 2), (9223, 3), (9224, 1), (9227, 2), (9228, 1), (9229, 2), + (9230, 3), (9232, 1), (9233, 2), (9235, 1), (9259, 1), (9260, 1), (9261, 1), (9262, 2), + (9264, 2), (9265, 1), (9268, 1), (9269, 2), (9270, 2), (9271, 1), (9272, 6), (9273, 2), + (9274, 1), (9298, 1), (9299, 2), (9301, 2), (9302, 3), (9303, 2), (9305, 1), (9306, 1), + (9307, 3), (9308, 1), (9309, 1), (9310, 3), (9311, 2), (9312, 3), (9313, 2), (9334, 3), + (9339, 1), (9340, 2), (9342, 1), (9343, 1), (9346, 2), (9347, 4), (9348, 3), (9350, 2), + (9351, 4), (9352, 2), (9353, 1), (9376, 1), (9377, 2), (9378, 2), (9379, 3), (9380, 1), + (9381, 2), (9382, 3), (9384, 3), (9386, 3), (9387, 2), (9388, 3), (9389, 8), (9390, 1), + (9391, 1), (9415, 2), (9419, 1), (9420, 3), (9421, 2), (9422, 2), (9425, 3), (9426, 6), + (9427, 3), (9428, 1), (9429, 3), (9430, 1), (9431, 1), (9455, 2), (9456, 1), (9457, 2), + (9458, 1), (9459, 1), (9460, 1), (9461, 1), (9462, 2), (9463, 3), (9464, 2), (9465, 3), + (9466, 2), (9467, 2), (9468, 4), (9474, 1), (9491, 1), (9494, 3), (9496, 1), (9497, 2), + (9498, 1), (9501, 2), (9503, 2), (9504, 3), (9505, 3), (9506, 10), (9507, 3), (9508, 4), + (9509, 2), (9510, 1), (9533, 2), (9534, 6), (9535, 1), (9536, 1), (9537, 1), (9538, 1), + (9539, 1), (9541, 1), (9542, 1), (9543, 1), (9544, 2), (9545, 3), (9546, 3), (9547, 2), + (9562, 6), (9570, 1), (9571, 1), (9572, 2), (9573, 1), (9574, 1), (9576, 4), (9577, 1), + (9581, 3), (9582, 8), (9584, 2), (9585, 1), (9586, 3), (9609, 1), (9611, 1), (9612, 5), + (9613, 1), (9614, 1), (9616, 2), (9618, 2), (9619, 1), (9621, 3), (9622, 1), (9623, 2), + (9624, 3), (9625, 4), (9626, 1), (9628, 1), (9650, 2), (9653, 2), (9656, 1), (9657, 2), + (9658, 1), (9659, 2), (9660, 1), (9661, 4), (9662, 2), (9666, 2), (9668, 1), (9689, 1), + (9690, 1), (9693, 1), (9694, 2), (9695, 1), (9696, 1), (9698, 2), (9699, 3), (9700, 1), + (9701, 4), (9703, 1), (9705, 1), (9727, 1), (9729, 1), (9731, 1), (9732, 1), (9733, 1), + (9734, 3), (9735, 1), (9736, 1), (9737, 1), (9738, 1), (9739, 1), (9740, 3), (9742, 1), + (9743, 2), (9744, 1), (9767, 1), (9769, 2), (9770, 1), (9771, 3), (9772, 3), (9773, 2), + (9776, 3), (9777, 5), (9778, 1), (9779, 3), (9780, 1), (9783, 1), (9808, 1), (9809, 1), + (9811, 2), (9814, 1), (9815, 4), (9816, 3), (9817, 2), (9818, 2), (9819, 1), (9820, 2), + (9821, 2), (9824, 1), (9840, 3), (9847, 3), (9849, 8), (9852, 1), (9853, 1), (9854, 4), + (9855, 5), (9856, 1), (9857, 3), (9858, 2), (9859, 1), (9884, 5), (9886, 2), (9888, 1), + (9889, 1), (9891, 2), (9892, 1), (9893, 1), (9895, 2), (9896, 3), (9897, 4), (9903, 1), + (9923, 2), (9924, 2), (9925, 3), (9927, 1), (9928, 2), (9929, 1), (9932, 2), (9933, 1), + (9935, 4), (9936, 2), (9937, 3), (9939, 1), (9940, 1), (9964, 4), (9966, 1), (9967, 1), + (9970, 1), (9971, 1), (9972, 1), (9973, 2), (9974, 5), (9975, 1), (9976, 2), (9977, 3), + (9996, 1), (9999, 1), (10002, 1), (10003, 2), (10004, 2), (10005, 2), (10011, 4), (10012, 2), + (10013, 2), (10015, 1), (10016, 1), (10040, 1), (10042, 1), (10043, 4), (10044, 3), (10048, 1), + (10049, 1), (10050, 1), (10051, 1), (10052, 2), (10053, 2), (10054, 2), (10081, 2), (10082, 1), + (10084, 1), (10085, 1), (10086, 1), (10087, 2), (10089, 2), (10090, 2), (10092, 2), (10093, 2), + (10094, 1), (10096, 6), (10117, 5), (10118, 3), (10119, 2), (10121, 1), (10122, 2), (10123, 5), + (10124, 3), (10125, 1), (10126, 3), (10127, 1), (10129, 4), (10130, 2), (10131, 1), (10132, 2), + (10134, 1), (10139, 6), (10155, 1), (10157, 2), (10158, 2), (10161, 2), (10163, 1), (10165, 2), + (10168, 1), (10169, 1), (10170, 2), (10171, 2), (10172, 1), (10197, 1), (10198, 1), (10202, 1), + (10205, 1), (10206, 1), (10207, 1), (10208, 2), (10210, 2), (10211, 1), (10232, 1), (10234, 1), + (10236, 1), (10237, 1), (10238, 1), (10239, 2), (10240, 1), (10242, 1), (10243, 2), (10244, 2), + (10245, 2), (10246, 4), (10247, 3), (10248, 1), (10251, 1), (10259, 1), (10278, 1), (10279, 1), + (10280, 2), (10282, 1), (10283, 1), (10285, 3), (10286, 1), (10287, 3), (10289, 1), (10312, 1), + (10313, 1), (10314, 1), (10315, 1), (10317, 3), (10319, 1), (10322, 2), (10323, 1), (10324, 1), + (10325, 2), (10326, 1), (10327, 1), (10329, 2), (10350, 1), (10353, 1), (10355, 3), (10356, 1), + (10358, 1), (10360, 1), (10362, 1), (10363, 1), (10364, 2), (10365, 1), (10366, 4), (10391, 1), + (10393, 1), (10394, 2), (10395, 3), (10400, 4), (10404, 3), (10405, 1), (10407, 1), (10416, 6), + (10430, 2), (10431, 1), (10432, 1), (10434, 3), (10435, 1), (10437, 1), (10438, 2), (10439, 2), + (10440, 2), (10441, 1), (10442, 1), (10445, 2), (10446, 2), (10469, 2), (10470, 1), (10471, 1), + (10472, 1), (10473, 2), (10474, 1), (10476, 1), (10477, 1), (10481, 1), (10482, 1), (10483, 3), + (10485, 1), (10487, 1), (10488, 1), (10510, 1), (10511, 2), (10512, 1), (10514, 1), (10515, 1), + (10518, 2), (10519, 1), (10520, 1), (10522, 2), (10548, 2), (10549, 2), (10550, 3), (10553, 1), + (10554, 1), (10555, 2), (10556, 1), (10557, 3), (10559, 1), (10563, 1), (10586, 1), (10587, 2), + (10589, 3), (10590, 2), (10591, 1), (10592, 1), (10593, 2), (10594, 2), (10597, 1), (10598, 2), + (10599, 2), (10602, 1), (10603, 1), (10604, 2), (10625, 2), (10626, 2), (10627, 3), (10629, 6), + (10630, 2), (10631, 1), (10636, 1), (10638, 1), (10639, 1), (10640, 1), (10662, 6), (10664, 2), + (10667, 1), (10672, 1), (10673, 2), (10674, 1), (10675, 1), (10679, 1), (10698, 77), + (10703, 2), (10704, 1), (10705, 1), (10707, 5), (10708, 1), (10711, 1), (10712, 1), (10714, 1), + (10716, 3), (10717, 1), (10718, 1), (10720, 1), (10742, 2), (10744, 1), (10746, 1), (10747, 1), + (10752, 1), (10753, 1), (10754, 3), (10755, 1), (10757, 1), (10788, 1), (10789, 1), (10790, 1), + (10791, 6), (10793, 2), (10794, 2), (10795, 2), (10798, 1), (10818, 1), (10821, 1), (10826, 1), + (10830, 1), (10832, 1), (10834, 1), (10835, 1), (10837, 1), (10857, 1), (10861, 2), (10862, 1), + (10864, 1), (10865, 1), (10868, 4), (10869, 1), (10870, 2), (10871, 4), (10872, 1), (10875, 1), + (10898, 3), (10899, 1), (10903, 1), (10904, 1), (10905, 1), (10907, 4), (10908, 1), (10909, 2), + (10911, 2), (10912, 1), (10913, 1), (10916, 1), (10931, 5), (10933, 1), (10937, 1), (10938, 1), + (10939, 1), (10943, 1), (10945, 1), (10946, 3), (10947, 1), (10948, 1), (10949, 3), (10952, 1), + (10977, 1), (10978, 1), (10979, 1), (10980, 1), (10981, 1), (10982, 1), (10984, 1), (10985, 2), + (10986, 1), (10987, 1), (10988, 1), (10991, 2), (10992, 1), (11014, 1), (11016, 1), (11018, 2), + (11019, 1), (11020, 4), (11022, 1), (11023, 1), (11025, 1), (11026, 1), (11028, 4), (11029, 2), + (11052, 1), (11056, 1), (11057, 1), (11062, 3), (11063, 2), (11064, 2), (11065, 1), (11067, 1), + (11069, 1), (11070, 1), (11084, 1), (11093, 1), (11103, 1), (11104, 2), (11105, 3), (11106, 2), + (11107, 1), (11132, 1), (11133, 1), (11134, 1), (11135, 3), (11136, 1), (11139, 1), (11141, 1), + (11144, 2), (11146, 1), (11147, 1), (11148, 1), (11171, 1), (11173, 1), (11174, 1), (11176, 1), + (11180, 1), (11183, 1), (11186, 1), (11210, 1), (11212, 1), (11219, 1), (11220, 2), (11222, 3), + (11223, 2), (11224, 1), (11225, 1), (11226, 1), (11231, 1), (11249, 1), (11250, 1), (11253, 1), + (11254, 5), (11257, 1), (11258, 3), (11259, 3), (11261, 1), (11264, 2), (11287, 1), (11289, 1), + (11290, 2), (11291, 1), (11293, 1), (11296, 1), (11300, 1), (11301, 1), (11302, 1), (11326, 1), + (11328, 5), (11329, 1), (11335, 1), (11336, 2), (11337, 1), (11338, 1), (11339, 1), (11340, 1), + (11366, 3), (11368, 1), (11369, 2), (11370, 1), (11374, 2), (11375, 1), (11378, 2), (11379, 1), + (11404, 2), (11407, 1), (11409, 2), (11410, 2), (11411, 1), (11414, 1), (11415, 3), (11417, 1), + (11422, 1), (11443, 1), (11446, 1), (11450, 1), (11454, 1), (11455, 2), (11481, 6), (11485, 1), + (11487, 1), (11488, 1), (11492, 1), (11493, 1), (11494, 1), (11495, 1), (11498, 3), (11499, 1), + (11521, 1), (11522, 1), (11524, 2), (11525, 2), (11526, 1), (11528, 1), (11532, 1), (11564, 1), + (11565, 2), (11572, 1), (11576, 1), (11577, 1), (11599, 1), (11601, 1), (11602, 2), (11603, 1), + (11607, 1), (11609, 1), (11614, 1), (11616, 1), (11631, 1), (11640, 2), (11641, 1), (11642, 1), + (11643, 4), (11651, 3), (11653, 2), (11654, 1), (11655, 1), (11679, 2), (11682, 5), (11686, 1), + (11687, 1), (11689, 1), (11690, 3), (11691, 1), (11693, 1), (11717, 2), (11719, 3), (11720, 4), + (11721, 6), (11726, 1), (11727, 1), (11728, 1), (11750, 6), (11755, 3), (11756, 2), (11757, 2), + (11759, 1), (11762, 1), (11763, 1), (11764, 1), (11765, 3), (11766, 1), (11768, 1), (11769, 1), + (11770, 2), (11796, 2), (11797, 2), (11798, 1), (11801, 1), (11804, 1), (11806, 1), (11807, 3), + (11808, 1), (11810, 1), (11811, 1), (11813, 1), (11837, 2), (11841, 2), (11843, 2), (11844, 1), + (11845, 1), (11846, 1), (11871, 1), (11876, 2), (11877, 1), (11878, 1), (11880, 1), (11881, 2), + (11882, 4), (11883, 5), (11884, 3), (11885, 1), (11888, 1), (11912, 2), (11913, 1), (11923, 1), + (11926, 1), (11927, 1), (11928, 1), (11951, 1), (11953, 2), (11955, 1), (11956, 2), (11959, 2), + (11961, 1), (11962, 1), (11964, 1), (11966, 2), (11990, 1), (11992, 3), (12003, 2), (12028, 1), + (12031, 1), (12033, 1), (12035, 1), (12037, 1), (12038, 1), (12039, 2), (12040, 1), (12041, 1), + (12043, 2), (12072, 4), (12077, 2), (12078, 3), (12079, 2), (12080, 1), (12108, 2), (12109, 2), + (12112, 1), (12114, 1), (12115, 2), (12116, 1), (12117, 2), (12118, 1), (12123, 2), (12145, 1), + (12146, 1), (12147, 3), (12148, 1), (12151, 1), (12156, 1), (12158, 2), (12183, 1), (12190, 1), + (12192, 1), (12194, 2), (12195, 1), (12196, 2), (12197, 3), (12198, 3), (12201, 1), (12224, 1), + (12225, 1), (12226, 1), (12230, 1), (12231, 1), (12234, 1), (12236, 1), (12237, 3), (12263, 1), + (12265, 1), (12266, 1), (12267, 1), (12269, 1), (12272, 1), (12273, 2), (12274, 2), (12276, 2), + (12277, 1), (12279, 1), (12280, 1), (12300, 1), (12303, 1), (12305, 1), (12307, 2), (12309, 1), + (12310, 2), (12311, 1), (12315, 2), (12321, 1), (12341, 1), (12344, 2), (12350, 2), (12351, 1), + (12352, 1), (12353, 1), (12383, 1), (12389, 2), (12390, 1), (12391, 1), (12392, 4), (12395, 1), + (12421, 3), (12423, 1), (12428, 1), (12429, 1), (12430, 1), (12457, 1), (12461, 1), (12463, 1), + (12468, 1), (12471, 1), (12473, 1), (12498, 5), (12499, 2), (12502, 1), (12503, 1), (12505, 1), + (12506, 1), (12508, 2), (12509, 1), (12510, 1), (12511, 1), (12513, 1), (12535, 1), (12536, 1), + (12537, 1), (12538, 1), (12539, 1), (12540, 1), (12542, 1), (12545, 1), (12547, 2), (12548, 1), + (12550, 1), (12577, 1), (12581, 1), (12583, 1), (12585, 1), (12586, 3), (12618, 1), (12624, 1), + (12626, 1), (12655, 1), (12657, 3), (12658, 1), (12663, 1), (12664, 3), (12665, 2), (12667, 1), + (12682, 1), (12693, 1), (12697, 1), (12699, 1), (12701, 1), (12702, 1), (12705, 2), (12706, 1), + (12730, 1), (12732, 2), (12733, 2), (12737, 1), (12739, 1), (12740, 1), (12742, 3), (12771, 1), + (12773, 1), (12780, 1), (12781, 3), (12782, 1), (12809, 1), (12811, 1), (12812, 1), (12819, 1), + (12821, 1), (12822, 1), (12824, 1), (12826, 1), (12848, 1), (12851, 2), (12853, 1), (12860, 3), + (12861, 1), (12862, 1), (12863, 1), (12889, 1), (12890, 1), (12896, 1), (12899, 1), (12928, 1), + (12929, 2), (12930, 1), (12936, 1), (12937, 3), (12938, 1), (12941, 1), (12964, 1), (12969, 1), + (12971, 1), (12973, 1), (12976, 1), (12977, 2), (13005, 1), (13006, 1), (13008, 1), (13010, 1), + (13013, 2), (13015, 2), (13018, 1), (13046, 1), (13047, 1), (13053, 2), (13055, 2), (13081, 1), + (13083, 1), (13085, 4), (13086, 1), (13091, 2), (13092, 2), (13094, 2), (13095, 1), (13096, 1), + (13097, 1), (13123, 2), (13127, 1), (13130, 1), (13131, 1), (13132, 1), (13134, 1), (13136, 1), + (13159, 1), (13161, 2), (13162, 1), (13167, 2), (13168, 1), (13172, 1), (13174, 1), (13175, 1), + (13176, 1), (13206, 1), (13207, 1), (13209, 2), (13212, 1), (13213, 2), (13239, 2), (13242, 1), + (13247, 1), (13249, 2), (13252, 1), (13279, 1), (13280, 2), (13282, 5), (13284, 1), (13286, 1), + (13288, 1), (13289, 1), (13290, 1), (13291, 1), (13317, 1), (13318, 1), (13319, 1), (13320, 1), + (13325, 1), (13326, 1), (13328, 2), (13330, 2), (13354, 2), (13356, 6), (13360, 2), (13362, 1), + (13363, 2), (13364, 3), (13367, 2), (13368, 3), (13370, 1), (13393, 1), (13397, 2), (13406, 1), + (13408, 1), (13435, 1), (13436, 1), (13438, 1), (13440, 2), (13442, 1), (13443, 1), (13444, 1), + (13445, 1), (13449, 1), (13473, 2), (13474, 1), (13475, 1), (13479, 2), (13481, 2), (13482, 1), + (13484, 1), (13485, 1), (13491, 1), (13511, 1), (13520, 1), (13521, 2), (13522, 1), (13527, 1), + (13550, 1), (13551, 1), (13552, 3), (13555, 1), (13557, 1), (13559, 2), (13562, 2), (13564, 1), + (13590, 1), (13592, 1), (13596, 1), (13600, 2), (13602, 1), (13603, 1), (13630, 1), (13633, 1), + (13634, 1), (13637, 1), (13640, 1), (13643, 1), (13668, 1), (13669, 2), (13670, 2), (13674, 1), + (13676, 1), (13677, 1), (13678, 4), (13679, 1), (13680, 1), (13713, 1), (13714, 1), (13716, 6), + (13717, 2), (13745, 1), (13752, 2), (13753, 1), (13754, 1), (13755, 1), (13757, 1), (13758, 1), + (13791, 1), (13795, 1), (13796, 2), (13823, 2), (13831, 1), (13834, 1), (13836, 1), (13837, 1), + (13862, 1), (13863, 1), (13864, 1), (13867, 1), (13875, 1), (13876, 1), (13877, 1), (13878, 1), + (13906, 1), (13910, 2), (13911, 1), (13912, 2), (13914, 2), (13942, 1), (13947, 2), (13948, 2), + (13950, 3), (13951, 1), (13952, 1), (13953, 1), (13954, 1), (13980, 1), (13985, 1), (13987, 1), + (13988, 1), (13989, 1), (14016, 1), (14018, 7), (14020, 2), (14021, 1), (14022, 1), (14023, 1), + (14024, 1), (14026, 1), (14027, 1), (14030, 1), (14061, 1), (14063, 6), (14064, 1), (14068, 1), + (14074, 1), (14098, 1), (14099, 2), (14102, 5), (14104, 2), (14108, 1), (14136, 1), (14140, 1), + (14143, 1), (14145, 1), (14146, 1), (14148, 1), (14174, 2), (14176, 1), (14177, 1), (14186, 1), + (14188, 1), (14189, 1), (14190, 1), (14213, 1), (14216, 1), (14225, 1), (14226, 1), (14253, 1), + (14257, 1), (14258, 1), (14261, 2), (14264, 1), (14265, 1), (14266, 1), (14292, 1), (14293, 1), + (14294, 1), (14303, 1), (14328, 1), (14336, 1), (14337, 1), (14340, 1), (14341, 1), (14342, 1), + (14370, 1), (14371, 1), (14373, 5), (14375, 1), (14378, 1), (14382, 2), (14409, 1), (14410, 1), + (14412, 1), (14417, 1), (14420, 4), (14421, 1), (14424, 1), (14448, 5), (14449, 2), (14455, 1), + (14459, 1), (14460, 1), (14491, 1), (14492, 1), (14494, 1), (14495, 1), (14500, 1), (14522, 1), + (14530, 2), (14532, 3), (14534, 1), (14537, 2), (14563, 1), (14565, 1), (14567, 1), (14575, 1), + (14576, 1), (14578, 2), (14606, 2), (14607, 2), (14608, 1), (14610, 1), (14611, 1), (14614, 1), + (14618, 2), (14645, 2), (14648, 1), (14651, 1), (14652, 1), (14653, 1), (14655, 1), (14685, 1), + (14687, 1), (14688, 1), (14689, 1), (14691, 4), (14692, 1), (14694, 1), (14695, 1), (14720, 1), + (14722, 1), (14723, 1), (14724, 1), (14725, 1), (14727, 1), (14728, 1), (14730, 2), (14731, 1), + (14732, 2), (14735, 2), (14757, 1), (14763, 1), (14765, 1), (14767, 1), (14769, 2), (14797, 1), + (14798, 1), (14801, 1), (14806, 2), (14810, 2), (14811, 1), (14813, 2), (14842, 1), (14847, 2), + (14849, 2), (14875, 1), (14881, 1), (14884, 1), (14885, 2), (14886, 2), (14889, 2), (14917, 1), + (14919, 1), (14921, 2), (14923, 1), (14924, 1), (14926, 1), (14927, 1), (14928, 1), (14956, 2), + (14957, 1), (14958, 1), (14961, 1), (14963, 3), (14968, 1), (15003, 2), (15007, 1), (15034, 1), + (15041, 2), (15043, 1), (15044, 1), (15045, 1), (15076, 1), (15080, 1), (15081, 1), (15082, 1), + (15083, 1), (15085, 1), (15112, 1), (15114, 1), (15117, 1), (15118, 1), (15120, 2), (15123, 1), + (15124, 1), (15155, 1), (15156, 1), (15165, 1), (15186, 1), (15196, 1), (15197, 1), (15199, 1), + (15200, 1), (15231, 1), (15232, 2), (15233, 1), (15235, 3), (15237, 2), (15238, 1), (15266, 1), + (15270, 1), (15275, 2), (15276, 1), (15280, 1), (15309, 1), (15314, 1), (15345, 1), (15352, 1), + (15353, 2), (15355, 2), (15356, 1), (15384, 1), (15385, 1), (15386, 1), (15388, 1), (15396, 1), + (15421, 1), (15422, 1), (15425, 1), (15434, 1), (15435, 1), (15436, 1), (15461, 1), (15462, 1), + (15463, 1), (15469, 1), (15474, 1), (15475, 1), (15500, 1), (15504, 1), (15505, 1), (15507, 1), + (15508, 1), (15509, 1), (15512, 1), (15513, 1), (15539, 1), (15542, 1), (15544, 1), (15548, 2), + (15550, 1), (15551, 1), (15580, 1), (15586, 1), (15587, 1), (15589, 1), (15590, 1), (15618, 1), + (15620, 1), (15624, 1), (15626, 1), (15659, 2), (15662, 1), (15665, 1), (15667, 1), (15668, 1), + (15695, 1), (15697, 1), (15698, 1), (15701, 1), (15702, 1), (15704, 1), (15709, 2), (15740, 1), + (15741, 1), (15742, 1), (15743, 1), (15746, 1), (15778, 1), (15779, 1), (15782, 1), (15784, 1), + (15786, 1), (15825, 1), (15849, 1), (15853, 1), (15857, 1), (15860, 1), (15864, 1), (15891, 1), + (15893, 2), (15895, 1), (15896, 1), (15898, 1), (15900, 1), (15932, 1), (15937, 1), (15938, 1), + (15967, 1), (15973, 1), (15977, 1), (15980, 1), (16007, 1), (16010, 1), (16012, 1), (16014, 1), + (16016, 1), (16018, 1), (16019, 1), (16053, 1), (16058, 1), (16086, 1), (16091, 1), (16093, 1), + (16098, 1), (16137, 1), (16162, 1), (16163, 1), (16167, 1), (16168, 2), (16171, 1), (16172, 2), + (16202, 1), (16206, 1), (16210, 2), (16212, 1), (16213, 1), (16215, 1), (16245, 1), (16249, 1), + (16280, 1), (16283, 1), (16284, 1), (16288, 1), (16319, 1), (16322, 2), (16326, 1), (16327, 3), + (16329, 1), (16331, 1), (16370, 1), (16403, 1), (16404, 1), (16406, 1), (16409, 1), (16410, 1), + (16411, 1), (16434, 1), (16440, 1), (16441, 1), (16443, 2), (16444, 1), (16445, 1), (16460, 1), + (16475, 1), (16479, 1), (16482, 1), (16483, 2), (16488, 1), (16521, 2), (16523, 2), (16524, 1), + (16525, 2), (16551, 1), (16552, 1), (16553, 2), (16558, 1), (16563, 1), (16565, 1), (16567, 1), + (16593, 1), (16595, 1), (16596, 1), (16600, 1), (16639, 2), (16644, 1), (16673, 2), (16674, 1), + (16678, 1), (16712, 1), (16714, 1), (16717, 1), (16718, 1), (16750, 1), (16751, 1), (16753, 1), + (16756, 1), (16792, 1), (16796, 1), (16798, 2), (16827, 1), (16875, 1), (16906, 1), (16909, 1), + (16910, 1), (16911, 2), (16941, 1), (16943, 1), (16948, 1), (16949, 1), (16954, 1), (16957, 1), + (16985, 1), (16993, 1), (17022, 2), (17024, 1), (17028, 1), (17032, 1), (17066, 2), (17103, 1), + (17104, 2), (17106, 1), (17109, 1), (17139, 1), (17143, 1), (17179, 1), (17183, 2), (17187, 1), + (17189, 1), (17217, 1), (17223, 2), (17255, 1), (17262, 1), (17265, 1), (17278, 1), (17298, 1), + (17302, 2), (17334, 1), (17338, 1), (17371, 2), (17378, 1), (17381, 1), (17415, 1), (17416, 1), + (17457, 1), (17458, 1), (17490, 1), (17499, 1), (17536, 1), (17539, 1), (17568, 1), (17571, 1), + (17572, 1), (17616, 1), (17617, 1), (17619, 1), (17682, 5), (17687, 1), (17729, 1), (17731, 1), + (17763, 1), (17769, 1), (17803, 1), (17806, 1), (17812, 1), (17841, 1), (17887, 1), (17889, 1), + (17920, 1), (17922, 1), (17925, 1), (17961, 1), (17965, 1), (17967, 1), (18004, 1), (18030, 1), + (18040, 2), (18042, 1), (18043, 1), (18044, 1), (18045, 1), (18078, 1), (18157, 1), (18167, 1), + (18236, 1), (18239, 1), (18270, 1), (18314, 1), (18355, 1), (18394, 1), (18396, 1), (18436, 1), + (18465, 1), (18469, 1), (18505, 1), (18542, 2), (18547, 1), (18550, 1), (18584, 1), (18587, 1), + (18588, 1), (18667, 1), (18668, 1), (18702, 1), (18741, 1), (18742, 1), (18783, 1), (18784, 1), + (18818, 1), (18855, 1), (18900, 1), (18904, 1), (18939, 1), (18943, 1), (18977, 1), (19013, 1), + (19019, 1), (19021, 1), (19048, 1), (19053, 1), (19056, 1), (19133, 2), (19172, 1), (19176, 2), + (19201, 5), (19211, 1), (19248, 1), (19249, 1), (19280, 1), (19288, 1), (19295, 1), (19325, 1), + (19327, 1), (19328, 2), (19330, 2), (19337, 6), (19365, 1), (19406, 1), (19407, 1), (19450, 1), + (19487, 1), (19526, 1), (19561, 2), (19564, 1), (19600, 1), (19605, 1), (19640, 1), (19680, 1), + (19720, 1), (19758, 1), (19800, 1), (19952, 2), (19954, 1), (19955, 1), (19956, 1), (19988, 1), + (19989, 26), (19990, 21), (19991, 30), (19992, 21), (19993, 13), (19994, 12), (19995, 9), + (19996, 6), (20000, 1), (20010, 1), (20030, 1), (20031, 1), (20066, 1), (20069, 1), (20070, 1), + (20073, 1), (20109, 1), (20111, 1), (20132, 1), (20150, 1), (20186, 1), (20266, 1), (20267, 1), + (20268, 1), (20302, 1), (20303, 1), (20423, 1), (20424, 1), (20540, 1), (20577, 1), (20616, 1), + (20654, 1), (20655, 2), (20693, 1), (20696, 1), (20732, 2), (20773, 2), (20883, 1), (20888, 1), + (20892, 1), (20925, 1), (20928, 1), (21045, 1), (21047, 1), (21083, 2), (21126, 1), (21165, 1), + (21201, 1), (21202, 1), (21276, 1), (21315, 1), (21357, 1), (21399, 2), (21439, 1), (21476, 1), + (21510, 1), (21513, 1), (21550, 1), (21551, 1), (21593, 1), (21633, 1), (21665, 1), (21666, 1), + (21669, 1), (21751, 1), (21826, 1), (21921, 1), (21939, 1), (21943, 1), (21977, 1), (21980, 2), + (21981, 1), (22017, 1), (22018, 1), (22133, 1), (22134, 1), (22135, 2), (22172, 1), (22211, 1), + (22212, 1), (22213, 1), (22251, 1), (22254, 1), (22256, 1), (22290, 1), (22371, 1), (22406, 1), + (22408, 1), (22410, 1), (22451, 1), (22485, 1), (22486, 2), (22525, 1), (22526, 1), (22562, 1), + (22563, 3), (22564, 1), (22607, 1), (22644, 1), (22680, 1), (22758, 1), (22759, 1), (22798, 2), + (22837, 2), (22838, 1), (22875, 1), (22877, 1), (22914, 1), (22916, 1), (22918, 1), (22993, 1), + (23031, 1), (23033, 2), (23070, 1), (23109, 1), (23111, 1), (23148, 1), (23151, 1), (23188, 1), + (23189, 1), (23226, 1), (23227, 1), (23304, 1), (23305, 1), (23381, 5), (23384, 2), (23388, 1), + (23424, 1), (23462, 1), (23498, 1), (23542, 1), (23579, 1), (23580, 1), (23654, 1), (23657, 1), + (23820, 1), (24019, 7), (24047, 1), (24204, 1), (24390, 1), (27166, 6), (31645, 5), (37476, 6), + (50442, 1), (66530, 1), (236741, 1), (266960, 1), (410116, 1), (452279, 1), (521150, 1), + (531415, 1), (531469, 1), (533889, 1), (534391, 1), (537072, 1), (537491, 1), (546820, 1), + (554056, 1), (562513, 1), (570304, 1), (571882, 1), (580008, 1), (582755, 1), (586561, 1), + (589436, 1), (593061, 2), (618859, 1), (619082, 1), (625907, 1), (633533, 1), (644603, 1), + (646180, 1), (655481, 1), (693987, 1), (701633, 1), (728784, 1), (745886, 1), (752140, 1), + (771376, 1), (848764, 1), (902834, 1), (952321, 1), (964030, 1), (974008, 1), (977740, 1), + (992978, 1), (1019553, 1), (1057259, 1), (1094674, 1), (1105518, 1), (1116659, 1), + (1121314, 1), (1135487, 1), (1151345, 1), (1173415, 1), (1189567, 1), (1238079, 1), + (1282021, 1), (1290980, 1), (1293007, 1), (1318405, 1), (1328926, 1), (1338999, 1), + (1373382, 1), (1402596, 1), (1422519, 1), (1446480, 1), (1460046, 1), (1475924, 1), + (1478227, 1), (1482046, 1), (1597051, 1), +]; \ No newline at end of file diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs new file mode 100644 index 00000000..f85b1b59 --- /dev/null +++ b/admin/src/multitree_bench/mod.rs @@ -0,0 +1,358 @@ +// Copyright 2021-2022 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or MIT. + +use super::*; + +mod data; + +pub use parity_db::{CompressionType, Db, Key, Value}; +use parity_db::{NewNode, NodeRef, Operation}; + +use rand::{RngCore, SeedableRng}; +use std::{ + collections::BTreeMap, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, + }, + thread, +}; + +static COMMITS: AtomicUsize = AtomicUsize::new(0); +static NEXT_COMMIT: AtomicUsize = AtomicUsize::new(0); + +/// Stress tests (warning erase db first). +#[derive(Debug, clap::Parser)] +pub struct MultiTreeStress { + #[clap(flatten)] + pub shared: Shared, + + /// Number of reading threads [default: 0]. + #[clap(long)] + pub readers: Option, + + /// Number of iterating threads [default: 0]. + #[clap(long)] + pub iter: Option, + + /// Number of writing threads [default: 1]. + #[clap(long)] + pub writers: Option, + + /// Total number of inserted commits. + #[clap(long)] + pub commits: Option, + + /// Random seed used for key generation. + #[clap(long)] + pub seed: Option, + + /// Open an existing database. + #[clap(long)] + pub append: bool, + + /// Do not apply pruning. + #[clap(long)] + pub archive: bool, + + /// Enable compression. + #[clap(long)] + pub compress: bool, + + /// Time (in milliseconds) between commits. + #[clap(long)] + pub commit_time: Option, +} + +#[derive(Clone)] +pub struct Args { + pub readers: usize, + pub iter: usize, + pub writers: usize, + pub commits: usize, + pub seed: Option, + pub append: bool, + pub archive: bool, + pub compress: bool, + pub commit_time: u64, +} + +impl MultiTreeStress { + pub(super) fn get_args(&self) -> Args { + Args { + readers: self.readers.unwrap_or(0), + iter: self.iter.unwrap_or(0), + writers: self.writers.unwrap_or(1), + commits: self.commits.unwrap_or(100_000), + seed: self.seed, + append: self.append, + archive: self.archive, + compress: self.compress, + commit_time: self.commit_time.unwrap_or(0), + } + } +} + +fn sample_histogram(rnd: u64, histogram: &BTreeMap, total: u32) -> u32 { + let sr = (rnd % total as u64) as u32; + let mut range = histogram.range((std::ops::Bound::Included(sr), std::ops::Bound::Unbounded)); + let size = *range.next().unwrap().1; + size +} + +struct ChainGenerator { + depth_child_count_distribution: Vec>, + depth_child_count_total: Vec, + value_length_distribution: BTreeMap, + value_length_total: u32, +} + +impl ChainGenerator { + fn new( + depth_child_count_histogram: &[(u32, [u32; 17])], + value_length_histogram: &[(u32, u32)], + ) -> ChainGenerator { + let mut depth_child_count_distribution = Vec::default(); + let mut depth_child_count_total = Vec::default(); + for (depth, histogram) in depth_child_count_histogram { + assert_eq!(*depth, depth_child_count_distribution.len() as u32); + + let mut distribution = BTreeMap::default(); + let mut total = 0; + for i in 0..histogram.len() { + let size = i as u32; + let count = histogram[i]; + total += count; + if count > 0 { + distribution.insert(total, size); + } + } + + depth_child_count_distribution.push(distribution); + depth_child_count_total.push(total); + } + + let mut value_length_distribution = BTreeMap::default(); + let mut value_length_total = 0; + for (size, count) in value_length_histogram { + value_length_total += count; + if *count > 0 { + value_length_distribution.insert(value_length_total, *size); + } + } + + ChainGenerator { + depth_child_count_distribution, + depth_child_count_total, + value_length_distribution, + value_length_total, + } + } + + fn key(&self, seed: u64) -> Key { + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); + let mut key = Key::default(); + rng.fill_bytes(&mut key); + key + } + + /// Returns tuple of node data and child seeds + fn generate_node(&self, seed: u64, depth: u32) -> (Vec, Vec) { + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); + + let num_children = if depth < self.depth_child_count_distribution.len() as u32 { + sample_histogram( + rng.next_u64(), + &self.depth_child_count_distribution[depth as usize], + self.depth_child_count_total[depth as usize], + ) + } else { + 0 + }; + let mut children_seeds = Vec::default(); + for _i in 0..num_children { + children_seeds.push(rng.next_u64()); + } + + let mut size = 4; + if num_children == 0 { + size = sample_histogram( + rng.next_u64(), + &self.value_length_distribution, + self.value_length_total, + ) as usize; + } + let mut v = Vec::new(); + v.resize(size, 0); + let fill = size; + rng.fill_bytes(&mut v[..fill]); + + (v, children_seeds) + } +} + +fn informant(shutdown: Arc) { + while !shutdown.load(Ordering::Relaxed) { + thread::sleep(std::time::Duration::from_secs(1)); + } +} + +fn build_commit_tree( + node_data: (Vec, Vec), + depth: u32, + chain_generator: &ChainGenerator, +) -> NodeRef { + let mut children = Vec::default(); + for seed in node_data.1 { + let child_data = chain_generator.generate_node(seed, depth + 1); + let child_node = build_commit_tree(child_data, depth + 1, chain_generator); + children.push(child_node); + } + let new_node = NewNode { data: node_data.0, children }; + NodeRef::New(new_node) +} + +fn num_new_child_nodes(node: &NodeRef) -> u32 { + match node { + NodeRef::New(node) => { + let mut num = 0; + for child in &node.children { + num += num_new_child_nodes(child) + 1; + } + num + }, + NodeRef::Existing(_) => 0, + } +} + +fn writer( + db: Arc, + args: Arc, + chain_generator: Arc, + shutdown: Arc, + start_commit: usize, +) { + let offset = args.seed.unwrap_or(0); + let mut commit = Vec::new(); + + loop { + let n = NEXT_COMMIT.fetch_add(1, Ordering::SeqCst); + if n >= start_commit + args.commits || shutdown.load(Ordering::Relaxed) { + break + } + + let root_seed = n as u64 + offset; + let node_data = chain_generator.generate_node(root_seed, 0); + let root_node_ref = build_commit_tree(node_data, 0, &chain_generator); + let num_new_nodes = num_new_child_nodes(&root_node_ref) + 1; + println!("Tree commit num new nodes: {}", num_new_nodes); + if let NodeRef::New(node) = root_node_ref { + let key = chain_generator.key(root_seed); + commit.push((0, Operation::InsertTree(key.to_vec(), node))); + + db.commit_changes(commit.drain(..)).unwrap(); + COMMITS.fetch_add(1, Ordering::Relaxed); + commit.clear(); + } + } +} + +fn reader( + _db: Arc, + _args: Arc, + _chain_generator: Arc, + _index: u64, + shutdown: Arc, +) { + // Query random keys while writing + /* let seed = args.seed.unwrap_or(0); + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + index); */ + while !shutdown.load(Ordering::Relaxed) {} +} + +fn iter(_db: Arc, shutdown: Arc) { + while !shutdown.load(Ordering::Relaxed) {} +} + +pub fn run_internal(args: Args, db: Db) { + let args = Arc::new(args); + let shutdown = Arc::new(AtomicBool::new(false)); + let db = Arc::new(db); + + let mut threads = Vec::new(); + + let start_commit = 0; + + let total_num_expected_tree_nodes: u32 = + data::DEPTH_CHILD_COUNT_HISTOGRAMS.iter().map(|x| x.1.iter().sum::()).sum(); + println!("Total num expected tree nodes: {}", total_num_expected_tree_nodes); + + let chain_generator = + ChainGenerator::new(data::DEPTH_CHILD_COUNT_HISTOGRAMS, data::VALUE_LENGTH_HISTOGRAM); + let chain_generator = Arc::new(chain_generator); + + let start_time = std::time::Instant::now(); + + COMMITS.store(start_commit, Ordering::SeqCst); + NEXT_COMMIT.store(start_commit, Ordering::SeqCst); + + { + let shutdown = shutdown.clone(); + threads.push(thread::spawn(move || informant(shutdown))); + } + + for i in 0..args.readers { + let db = db.clone(); + let shutdown = shutdown.clone(); + let args = args.clone(); + let chain_generator = chain_generator.clone(); + + threads.push( + thread::Builder::new() + .name(format!("reader {i}")) + .spawn(move || reader(db, args, chain_generator, i as u64, shutdown)) + .unwrap(), + ); + } + + for i in 0..args.iter { + let db = db.clone(); + let shutdown = shutdown.clone(); + + threads.push( + thread::Builder::new() + .name(format!("iter {i}")) + .spawn(move || iter(db, shutdown)) + .unwrap(), + ); + } + + for i in 0..args.writers { + let db = db.clone(); + let shutdown = shutdown.clone(); + let args = args.clone(); + let chain_generator = chain_generator.clone(); + + threads.push( + thread::Builder::new() + .name(format!("writer {i}")) + .spawn(move || writer(db, args, chain_generator, shutdown, start_commit)) + .unwrap(), + ); + } + + while COMMITS.load(Ordering::Relaxed) < start_commit + args.commits { + thread::sleep(std::time::Duration::from_millis(50)); + } + shutdown.store(true, Ordering::SeqCst); + + for t in threads.into_iter() { + t.join().unwrap(); + } + + let commits = COMMITS.load(Ordering::SeqCst); + let commits = commits - start_commit; + let elapsed_time = start_time.elapsed().as_secs_f64(); + + println!("Completed {} commits in {} seconds.", commits, elapsed_time); +} diff --git a/src/btree/mod.rs b/src/btree/mod.rs index e3c456d8..25ccfff2 100644 --- a/src/btree/mod.rs +++ b/src/btree/mod.rs @@ -383,13 +383,19 @@ pub mod commit_overlay { BTreeChangeSet { col, changes: Default::default() } } - pub fn push(&mut self, change: Operation) { + pub fn push(&mut self, change: Operation) -> Result<()> { // No key hashing self.changes.push(match change { Operation::Set(k, v) => Operation::Set(k.into(), v.into()), Operation::Dereference(k) => Operation::Dereference(k.into()), Operation::Reference(k) => Operation::Reference(k.into()), + Operation::InsertTree(..) | Operation::RemoveTree(..) => + return Err(Error::InvalidInput(format!( + "Invalid operation for column {}", + self.col + ))), }); + Ok(()) } pub fn copy_to_overlay( @@ -426,6 +432,11 @@ pub mod commit_overlay { ))) } }, + Operation::InsertTree(..) | Operation::RemoveTree(..) => + return Err(Error::InvalidInput(format!( + "Invalid operation for column {}", + self.col + ))), } } Ok(()) diff --git a/src/column.rs b/src/column.rs index 53521cfd..e112c8cd 100644 --- a/src/column.rs +++ b/src/column.rs @@ -9,6 +9,7 @@ use crate::{ error::{try_io, Error, Result}, index::{Address, IndexTable, PlanOutcome, TableId as IndexTableId}, log::{Log, LogAction, LogOverlays, LogQuery, LogReader, LogWriter}, + multitree::{NewNode, NodeAddress, NodeRef}, options::{ColumnOptions, Metadata, Options, DEFAULT_COMPRESSION_THRESHOLD}, parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, stats::{ColumnStatSummary, ColumnStats}, @@ -589,6 +590,8 @@ impl HashColumn { } Ok(PlanOutcome::Skipped) }, + Operation::InsertTree(..) | Operation::RemoveTree(..) => + Err(Error::InvalidConfiguration("Unsupported operation on hash column".into())), } } } @@ -663,6 +666,85 @@ impl HashColumn { Ok((outcome, tables, reindex)) } + fn write_children( + &self, + children: Vec, + tables: TablesRef, + writer: &mut LogWriter, + ) -> Result> { + let mut data = Vec::new(); + for child in children { + let address = match child { + NodeRef::New(node) => self.write_node(node, tables, writer)?, + NodeRef::Existing(address) => address, + }; + let mut data_buf = [0u8; 8]; + data_buf.copy_from_slice(&address.to_le_bytes()); + data.append(&mut data_buf.to_vec()); + } + Ok(data) + } + + fn write_node( + &self, + node: NewNode, + tables: TablesRef, + writer: &mut LogWriter, + ) -> Result { + let num_children = node.children.len(); + let data = self.pack_node_data( + node.data, + self.write_children(node.children, tables, writer)?, + num_children as u8, + ); + + let stats = self.collect_stats.then_some(&self.stats); + let table_key = TableKey::NoHash; + let address = + Column::write_new_value_plan(&table_key, tables, data.as_ref(), writer, stats)?; + + Ok(address.as_u64()) + } + + fn pack_node_data(&self, data: Vec, child_data: Vec, num_children: u8) -> Vec { + [vec![num_children], data, child_data].concat() + } + + pub fn write_insert_tree_plan_immediate( + &self, + change: Operation, + log: &Log, + bytes: &mut u64, + ) -> Result, Vec>>> { + match change { + Operation::InsertTree(key, node) => { + let mut writer = log.begin_record(); + let tables = self.tables.upgradable_read(); + + let num_children = node.children.len(); + let data = self.pack_node_data( + node.data, + self.write_children(node.children, self.as_ref(&tables.value), &mut writer)?, + num_children as u8, + ); + + self.complete_plan(&mut writer)?; + + let l = writer.drain(); + *bytes += log.end_record(l)?; + + return Ok(Some(Operation::Set(key, data))) + }, + Operation::RemoveTree(_key) => + return Err(Error::InvalidInput(format!("RemoveTree not implemented yet"))), + _ => + return Err(Error::InvalidInput(format!( + "Invalid operation for column {}", + self.col + ))), + } + } + pub fn enact_plan(&self, action: LogAction, log: &mut LogReader) -> Result<()> { let tables = self.tables.read(); let reindex = self.reindex.read(); @@ -1205,6 +1287,8 @@ impl Column { Ok((Some(PlanOutcome::Written), None)) } }, + Operation::InsertTree(..) | Operation::RemoveTree(..) => + Err(Error::InvalidInput(format!("Invalid operation for column {}", tables.col))), } } diff --git a/src/db.rs b/src/db.rs index 071f15cf..38208a48 100644 --- a/src/db.rs +++ b/src/db.rs @@ -25,6 +25,7 @@ use crate::{ hash::IdentityBuildHasher, index::PlanOutcome, log::{Log, LogAction}, + multitree::NewNode, options::{Options, CURRENT_VERSION}, parking_lot::{Condvar, Mutex, RwLock}, stats::StatSummary, @@ -138,6 +139,7 @@ struct DbInner { log: Log, commit_queue: Mutex, commit_queue_full_cv: Condvar, + log_writer_mutex: Mutex, log_worker_wait: WaitCondvar, commit_worker_wait: Arc>, // Overlay of most recent values in the commit queue. @@ -222,6 +224,7 @@ impl DbInner { log, commit_queue: Mutex::new(Default::default()), commit_queue_full_cv: Condvar::new(), + log_writer_mutex: Mutex::new(false), log_worker_wait: WaitCondvar::new(), commit_worker_wait: Arc::new(WaitCondvar::new()), commit_overlay: RwLock::new(commit_overlay), @@ -327,13 +330,38 @@ impl DbInner { .btree_indexed .entry(col) .or_insert_with(|| BTreeChangeSet::new(col)) - .push(change) + .push(change)? + } else if self.options.columns[col as usize].multitree { + let _log_writer = self.log_writer_mutex.lock(); + let mut bytes = 0; + + match &self.columns[col as usize] { + Column::Hash(column) => { + if let Some(operation) = column + .write_insert_tree_plan_immediate(change, &self.log, &mut bytes)? + { + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(operation, &self.options, self.db_version)? + } + }, + Column::Tree(_) => + return Err(Error::InvalidConfiguration("Not a HashColumn".to_string())), + } + + if bytes > 0 { + let mut logged_bytes = self.log_queue_wait.work.lock(); + *logged_bytes += bytes as i64; + self.flush_worker_wait.signal(); + } } else { commit.indexed.entry(col).or_insert_with(|| IndexedChangeSet::new(col)).push( change, &self.options, self.db_version, - ) + )? } } @@ -1360,6 +1388,12 @@ pub enum Operation { /// Increment the reference count counter of an existing value for a given key. /// If no value exists for the key, this operation is skipped. Reference(Key), + + /// Insert a new tree into a MultiTree column using root key and node structure. + InsertTree(Key, NewNode), + + /// Remove an existing tree (at root Key) from a MultiTree column. + RemoveTree(Key), } impl PartialOrd for Operation { @@ -1377,13 +1411,21 @@ impl Ord for Operation { impl Operation { pub fn key(&self) -> &Key { match self { - Operation::Set(k, _) | Operation::Dereference(k) | Operation::Reference(k) => k, + Operation::Set(k, _) | + Operation::Dereference(k) | + Operation::Reference(k) | + Operation::InsertTree(k, _) | + Operation::RemoveTree(k) => k, } } pub fn into_key(self) -> Key { match self { - Operation::Set(k, _) | Operation::Dereference(k) | Operation::Reference(k) => k, + Operation::Set(k, _) | + Operation::Dereference(k) | + Operation::Reference(k) | + Operation::InsertTree(k, _) | + Operation::RemoveTree(k) => k, } } } @@ -1394,6 +1436,8 @@ impl, Value> Operation { Operation::Set(k, v) => Operation::Set(k.as_ref().to_vec(), v), Operation::Dereference(k) => Operation::Dereference(k.as_ref().to_vec()), Operation::Reference(k) => Operation::Reference(k.as_ref().to_vec()), + Operation::InsertTree(k, n) => Operation::InsertTree(k.as_ref().to_vec(), n), + Operation::RemoveTree(k) => Operation::RemoveTree(k.as_ref().to_vec()), } } } @@ -1420,7 +1464,7 @@ impl IndexedChangeSet { change: Operation>, options: &Options, db_version: u32, - ) { + ) -> Result<()> { let salt = options.salt.unwrap_or_default(); let hash_key = |key: &[u8]| -> Key { hash_key(key, &salt, options.columns[self.col as usize].uniform, db_version) @@ -1430,7 +1474,14 @@ impl IndexedChangeSet { Operation::Set(k, v) => Operation::Set(hash_key(k.as_ref()), v.into()), Operation::Dereference(k) => Operation::Dereference(hash_key(k.as_ref())), Operation::Reference(k) => Operation::Reference(hash_key(k.as_ref())), - }) + Operation::InsertTree(..) | Operation::RemoveTree(..) => + return Err(Error::InvalidInput(format!( + "Invalid operation for column {}", + self.col + ))), + }); + + Ok(()) } fn push_change_hashed(&mut self, change: Operation) { @@ -1465,6 +1516,11 @@ impl IndexedChangeSet { return Err(Error::InvalidInput(format!("No Rc for column {}", self.col))) } }, + Operation::InsertTree(..) | Operation::RemoveTree(..) => + return Err(Error::InvalidInput(format!( + "Invalid operation for column {}", + self.col + ))), } } Ok(()) @@ -1505,7 +1561,9 @@ impl IndexedChangeSet { } } }, - Operation::Reference(..) => (), + Operation::Reference(..) | + Operation::InsertTree(..) | + Operation::RemoveTree(..) => (), } } } diff --git a/src/lib.rs b/src/lib.rs index ca2c155d..cfcc475d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ mod hash; mod index; mod log; mod migration; +mod multitree; mod options; mod parking_lot; mod stats; @@ -27,6 +28,7 @@ pub use db::{check::CheckOptions, Db, Operation, Value}; pub use error::set_number_of_allowed_io_operations; pub use error::{Error, Result}; pub use migration::{clear_column, migrate}; +pub use multitree::{Children, NewNode, NodeAddress, NodeRef}; pub use options::{ColumnOptions, Options}; pub use stats::{ColumnStatSummary, StatSummary}; diff --git a/src/multitree.rs b/src/multitree.rs new file mode 100644 index 00000000..79e6eb65 --- /dev/null +++ b/src/multitree.rs @@ -0,0 +1,17 @@ +// Copyright 2021-2022 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or MIT. + +pub type NodeAddress = u64; +pub type Children = Vec; + +#[derive(Debug, PartialEq, Eq)] +pub enum NodeRef { + New(NewNode), + Existing(NodeAddress), +} + +#[derive(Debug, PartialEq, Eq)] +pub struct NewNode { + pub data: Vec, + pub children: Vec, +} diff --git a/src/options.rs b/src/options.rs index abdb621b..5f22b55d 100644 --- a/src/options.rs +++ b/src/options.rs @@ -65,6 +65,9 @@ pub struct ColumnOptions { /// Column is configured to use Btree storage. Btree columns allow for ordered key iteration /// and key retrieval, but are significantly less performant and require more disk space. pub btree_index: bool, + /// Column supports Multitree operations. This allows committing and querying of tree + /// structures. + pub multitree: bool, } /// Database metadata. @@ -81,8 +84,13 @@ pub struct Metadata { impl ColumnOptions { fn as_string(&self) -> String { format!( - "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}", - self.preimage, self.uniform, self.ref_counted, self.compression as u8, self.btree_index, + "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}, multitree: {}", + self.preimage, + self.uniform, + self.ref_counted, + self.compression as u8, + self.btree_index, + self.multitree, ) } @@ -111,6 +119,7 @@ impl ColumnOptions { let ref_counted = vals.get("refc")?.parse().ok()?; let compression: u8 = vals.get("compression").and_then(|c| c.parse().ok()).unwrap_or(0); let btree_index = vals.get("ordered").and_then(|c| c.parse().ok()).unwrap_or(false); + let multitree = vals.get("multitree").and_then(|c| c.parse().ok()).unwrap_or(false); Some(ColumnOptions { preimage, @@ -118,6 +127,7 @@ impl ColumnOptions { ref_counted, compression: compression.into(), btree_index, + multitree, }) } } @@ -130,6 +140,7 @@ impl Default for ColumnOptions { ref_counted: false, compression: CompressionType::NoCompression, btree_index: false, + multitree: false, } } } From f088832c988cc28a88db8ce6f83dacc264bfe2d2 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 24 May 2023 11:46:37 +0100 Subject: [PATCH 02/53] fmt --- admin/src/multitree_bench/data.rs | 6410 +++++++++++++++++++++++++---- 1 file changed, 5701 insertions(+), 709 deletions(-) diff --git a/admin/src/multitree_bench/data.rs b/admin/src/multitree_bench/data.rs index e3a015f9..a45e4b82 100644 --- a/admin/src/multitree_bench/data.rs +++ b/admin/src/multitree_bench/data.rs @@ -9,8 +9,20 @@ pub const DEPTH_CHILD_COUNT_HISTOGRAMS: &[(u32, [u32; 17])] = &[ (4, [215, 0, 86, 56, 32, 40, 14, 22, 17, 26, 16, 13, 7, 12, 9, 11, 84]), (5, [1355, 0, 578, 255, 168, 122, 55, 35, 23, 16, 9, 8, 9, 8, 16, 6, 778]), (6, [3936, 0, 734, 287, 243, 234, 228, 354, 529, 752, 956, 965, 784, 537, 303, 293, 6120]), - (7, [36666, 0, 20515, 8277, 4180, 3330, 4509, 7107, 10629, 14209, 15995, 15107, 11277, 6318, 2522, 561, 1236]), - (8, [610349, 0, 272521, 75786, 16430, 3401, 1955, 2547, 2898, 2788, 2450, 1912, 1400, 641, 257, 96, 359]), + ( + 7, + [ + 36666, 0, 20515, 8277, 4180, 3330, 4509, 7107, 10629, 14209, 15995, 15107, 11277, 6318, + 2522, 561, 1236, + ], + ), + ( + 8, + [ + 610349, 0, 272521, 75786, 16430, 3401, 1955, 2547, 2898, 2788, 2450, 1912, 1400, 641, + 257, 96, 359, + ], + ), (9, [921168, 0, 65235, 9919, 1750, 334, 107, 203, 470, 656, 839, 963, 801, 470, 172, 57, 25]), (10, [188318, 0, 17655, 4333, 924, 203, 20, 2, 0, 0, 5, 11, 17, 7, 0, 0, 0]), (11, [50231, 0, 1485, 35, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), @@ -19,713 +31,5693 @@ pub const DEPTH_CHILD_COUNT_HISTOGRAMS: &[(u32, [u32; 17])] = &[ ]; pub const _KEY_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ - (5, 1), (20, 1), (32, 183), (36, 14), (44, 6247), (48, 1727), (52, 4381), (53, 1), (55, 32), - (56, 80), (64, 549), (65, 1), (66, 67), (68, 30), (69, 667), (72, 249742), (73, 16), (76, 304), - (77, 12321), (80, 1238143), (81, 503), (84, 19113), (92, 281057), (120, 70), + (5, 1), + (20, 1), + (32, 183), + (36, 14), + (44, 6247), + (48, 1727), + (52, 4381), + (53, 1), + (55, 32), + (56, 80), + (64, 549), + (65, 1), + (66, 67), + (68, 30), + (69, 667), + (72, 249742), + (73, 16), + (76, 304), + (77, 12321), + (80, 1238143), + (81, 503), + (84, 19113), + (92, 281057), + (120, 70), ]; pub const VALUE_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ - (1, 66581), (2, 95), (3, 1), (4, 283269), (5, 1308), (6, 169), (7, 3), (8, 73), (9, 10), - (10, 2), (11, 205), (12, 5), (13, 4), (14, 4), (15, 7), (16, 559), (17, 418), (18, 3), (19, 4), - (20, 609), (21, 57), (22, 1), (23, 1), (24, 6), (25, 5), (26, 69428), (27, 1), (28, 6), - (29, 8), (30, 9), (31, 12), (32, 85052), (33, 3212), (34, 116), (35, 220), (36, 454), - (37, 10344), (38, 9378), (39, 31), (40, 23), (41, 27), (42, 17), (43, 18), (44, 20), (45, 19), - (46, 74), (47, 7), (48, 175), (49, 3835), (50, 1851), (51, 890), (52, 29), (53, 85), - (54, 2992), (55, 15), (56, 98), (57, 688), (58, 34), (59, 22), (60, 21), (61, 12), (62, 14), - (63, 9), (64, 21), (65, 187), (66, 176), (67, 16), (68, 12), (69, 38), (70, 2318), (71, 20), - (72, 19), (73, 94), (74, 25), (75, 12), (76, 1778), (77, 50), (78, 22), (79, 21), - (80, 1098004), (81, 44), (82, 295), (83, 132), (84, 17), (85, 96), (86, 27), (87, 12), - (88, 150), (89, 360), (90, 517), (91, 85), (92, 22), (93, 7), (94, 22), (95, 79), (96, 86), - (97, 88), (98, 388), (99, 14), (100, 44), (101, 36), (102, 2957), (103, 11), (104, 22), - (105, 24), (106, 14), (107, 8), (108, 24), (109, 81), (110, 13), (111, 11), (112, 18), - (113, 23), (114, 45194), (115, 503), (116, 18), (117, 11), (118, 13), (119, 10), (120, 167), - (121, 38), (122, 43), (123, 67), (124, 17), (125, 10), (126, 23), (127, 17), (128, 191), - (129, 241), (130, 139), (131, 6), (132, 24), (133, 15), (134, 1944), (135, 14), (136, 16), - (137, 13), (138, 5), (139, 5), (140, 11), (141, 13), (142, 66), (143, 4), (144, 12), (145, 58), - (146, 16), (147, 2), (148, 20), (149, 2), (150, 1), (151, 2), (152, 128), (153, 29), (154, 2), - (155, 1), (156, 5), (157, 1), (158, 4), (159, 3), (160, 7), (161, 41), (162, 9), (163, 2), - (164, 41), (165, 29), (166, 1891), (167, 60), (168, 70), (169, 52), (170, 63), (171, 2), - (172, 6), (173, 28), (174, 8), (176, 3), (177, 5), (178, 7), (179, 1), (180, 2), (181, 52), - (182, 2), (184, 2), (185, 2), (186, 30), (188, 28), (189, 2), (190, 4), (192, 1918), (193, 27), - (194, 2), (195, 2), (196, 2), (197, 9), (198, 1454), (199, 23), (200, 1), (201, 4), (202, 26), - (203, 1), (205, 8), (206, 66), (207, 44), (208, 139), (209, 42), (210, 44), (211, 6), - (212, 22), (213, 6), (214, 5), (216, 6), (217, 29), (218, 2), (219, 1), (220, 3), (221, 2), - (222, 2), (223, 2), (225, 14), (226, 1), (228, 4), (229, 1), (230, 1178), (232, 1), (233, 3), - (234, 3), (237, 2), (238, 3), (239, 4), (241, 1), (242, 6), (243, 1), (244, 8), (245, 28), - (246, 38), (247, 41), (248, 17), (249, 32), (250, 81), (251, 18), (252, 24), (253, 36), - (254, 1), (255, 3), (257, 13), (258, 5), (259, 1), (260, 1), (261, 2), (262, 1306), (264, 16), - (265, 3), (266, 10), (268, 7), (269, 8), (270, 21), (272, 10), (273, 11), (274, 30), (276, 7), - (277, 3), (278, 10), (279, 7), (280, 10), (281, 7), (282, 4), (283, 9), (284, 56), (285, 39), - (286, 35), (287, 22), (288, 32), (289, 55), (290, 41), (291, 2), (292, 2), (293, 5), - (294, 992), (295, 8), (296, 10), (297, 1), (298, 6), (300, 1), (301, 2), (303, 7), (305, 5), - (306, 2), (307, 5), (308, 1), (309, 1), (311, 3), (313, 3), (315, 3), (317, 1), (318, 12), - (319, 1), (321, 22), (322, 3), (323, 33), (324, 39), (325, 29), (326, 1337), (327, 29), - (328, 20), (329, 32), (330, 17), (331, 12), (332, 1), (333, 4), (334, 4), (335, 9), (336, 2), - (337, 5), (338, 1), (339, 7), (340, 13), (341, 1), (342, 3), (343, 6), (344, 8), (345, 2), - (347, 8), (349, 2), (350, 3), (351, 5), (352, 1), (353, 13), (354, 2), (355, 12), (357, 3), - (358, 1063), (359, 9), (360, 6), (361, 9), (362, 22), (363, 62), (364, 17), (365, 26), - (366, 21), (367, 25), (368, 25), (369, 30), (370, 7), (371, 21), (373, 18), (374, 4), - (375, 90), (377, 27), (378, 8), (379, 125), (380, 2), (381, 34), (382, 51), (383, 18996), - (384, 52), (385, 33308), (386, 7601), (387, 949), (388, 3922), (389, 72), (390, 1089), - (391, 287), (392, 175), (393, 571), (394, 352), (395, 35), (396, 92), (397, 29), (398, 5), - (399, 9), (400, 14), (401, 44), (402, 50), (403, 54), (404, 26), (405, 19), (406, 12), - (407, 15), (408, 9), (409, 25), (410, 7), (412, 5), (413, 2), (415, 1), (417, 12), (418, 1), - (419, 2), (422, 1086), (424, 1), (425, 4), (426, 1), (427, 2), (428, 2), (429, 2), (431, 2), - (433, 3), (436, 7), (440, 8), (441, 48), (442, 38), (443, 25), (444, 11), (445, 9), (446, 14), - (447, 16), (448, 5), (449, 18), (450, 15), (452, 2), (454, 1085), (455, 5), (456, 1), (460, 1), - (461, 1), (465, 1), (469, 2), (471, 1), (472, 6), (477, 1), (478, 2), (479, 5), (480, 18), - (481, 90), (482, 31), (483, 9), (484, 7), (485, 12), (486, 1796), (487, 7), (488, 7), (489, 8), - (490, 5), (491, 3), (492, 1), (493, 2), (494, 2), (495, 1), (497, 1), (501, 1), (513, 7), - (516, 10), (518, 14326), (519, 21), (520, 35), (521, 20), (522, 3), (523, 10), (524, 17), - (525, 8), (526, 11), (527, 6), (528, 4), (529, 3), (530, 2), (533, 1), (534, 2), (538, 3), - (543, 1), (545, 7), (549, 1), (557, 1), (558, 13), (559, 17), (560, 13), (561, 7), (562, 18), - (563, 14), (564, 9), (565, 9), (566, 7), (567, 8), (568, 2), (569, 5), (570, 2), (572, 2), - (573, 2), (577, 1), (582, 4), (596, 11), (597, 4), (598, 7), (599, 4), (600, 8), (601, 20), - (602, 20), (603, 6), (604, 12), (605, 14), (606, 4), (607, 1), (608, 3), (609, 2), (610, 5), - (612, 1), (613, 1), (614, 1), (617, 1), (624, 1), (626, 1), (630, 1), (635, 15), (636, 6), - (637, 8), (638, 11), (639, 2), (640, 15), (641, 25), (642, 15), (643, 17), (644, 10), (645, 2), - (646, 2), (647, 16), (648, 5), (649, 2), (650, 2), (653, 1), (670, 4), (673, 6), (674, 15), - (676, 9), (677, 6), (678, 2), (679, 15), (680, 17), (681, 18), (682, 15), (683, 7), (685, 1), - (686, 1), (687, 1), (688, 1), (689, 1), (690, 1), (691, 2), (693, 1), (709, 1), (713, 13), - (714, 7), (715, 7), (716, 2), (717, 3), (718, 6), (719, 17), (720, 14), (721, 8), (722, 3), - (723, 4), (724, 4), (725, 1), (726, 3), (727, 1), (728, 1), (729, 1), (730, 2), (731, 1), - (736, 3), (737, 1), (752, 19), (753, 5), (754, 9), (755, 6), (756, 2), (757, 3), (758, 16), - (759, 9), (760, 12), (761, 11), (763, 1), (764, 3), (765, 5), (766, 1), (768, 1), (769, 2), - (770, 4), (772, 1), (780, 3), (785, 1), (789, 6), (791, 15), (792, 6), (793, 16), (794, 1), - (795, 2), (796, 5), (797, 12), (798, 15), (799, 18), (800, 6), (801, 1), (802, 8), (803, 1), - (808, 3), (809, 1), (810, 2), (814, 1), (824, 1), (830, 13), (831, 7), (832, 8), (833, 8), - (834, 7), (835, 3), (836, 13), (837, 8), (838, 9), (839, 4), (841, 3), (842, 2), (843, 4), - (844, 1), (846, 2), (847, 5), (849, 2), (853, 1), (854, 1), (855, 1), (868, 2), (869, 13), - (870, 6), (871, 10), (872, 2), (873, 2), (874, 2), (875, 10), (876, 15), (877, 14), (878, 5), - (879, 4), (880, 2), (881, 3), (882, 5), (883, 2), (884, 2), (886, 1), (888, 1), (889, 2), - (890, 2), (891, 2), (908, 3), (909, 5), (910, 10), (911, 5), (912, 6), (914, 3), (915, 3), - (916, 8), (917, 2), (918, 6), (919, 1), (920, 7), (921, 5), (922, 2), (923, 3), (926, 2), - (927, 2), (929, 2), (930, 5), (931, 2), (932, 5), (933, 2), (934, 3), (947, 3), (948, 6), - (949, 7), (950, 2), (951, 5), (952, 1), (953, 3), (954, 7), (955, 10), (956, 6), (957, 3), - (958, 6), (959, 10), (960, 3), (961, 4), (962, 1), (966, 1), (967, 1), (968, 3), (969, 10), - (970, 9), (971, 3), (972, 3), (977, 1), (978, 3), (986, 2), (987, 5), (988, 16), (989, 3), - (990, 3), (991, 1), (992, 7), (993, 7), (994, 11), (995, 4), (996, 10), (997, 6), (998, 4), - (999, 2), (1000, 1), (1001, 1), (1002, 2), (1005, 1), (1008, 7), (1009, 7), (1010, 9), - (1011, 6), (1012, 1), (1013, 1), (1014, 2), (1022, 3), (1025, 1), (1026, 10), (1027, 10), - (1028, 6), (1029, 2), (1030, 6), (1031, 6), (1032, 13), (1033, 10), (1034, 3), (1035, 6), - (1036, 7), (1037, 4), (1038, 1), (1040, 1), (1041, 1), (1044, 7), (1046, 5), (1047, 11), - (1048, 4), (1050, 1), (1052, 2), (1065, 10), (1066, 9), (1067, 4), (1068, 3), (1069, 4), - (1070, 1), (1071, 4), (1072, 11), (1073, 4), (1074, 4), (1075, 1), (1076, 2), (1077, 1), - (1078, 2), (1079, 5), (1085, 1), (1086, 7), (1087, 4), (1088, 3), (1089, 2), (1104, 4), - (1105, 9), (1106, 5), (1107, 2), (1108, 4), (1109, 4), (1110, 14), (1111, 12), (1112, 8), - (1113, 2), (1114, 3), (1115, 1), (1116, 1), (1117, 4), (1118, 3), (1124, 1), (1125, 4), - (1126, 10), (1127, 3), (1141, 6), (1143, 6), (1144, 12), (1145, 5), (1146, 3), (1147, 4), - (1148, 4), (1149, 6), (1150, 7), (1151, 7), (1152, 1), (1153, 2), (1154, 1), (1155, 2), - (1156, 2), (1164, 2), (1165, 8), (1166, 6), (1167, 3), (1168, 2), (1171, 1), (1176, 1), - (1181, 1), (1182, 3), (1183, 11), (1184, 3), (1185, 4), (1186, 4), (1187, 3), (1188, 7), - (1189, 6), (1190, 5), (1191, 1), (1193, 1), (1196, 1), (1198, 3), (1202, 1), (1203, 4), - (1204, 3), (1205, 9), (1206, 7), (1207, 3), (1208, 1), (1210, 1), (1220, 4), (1221, 3), - (1222, 5), (1223, 4), (1224, 1), (1225, 2), (1226, 5), (1227, 14), (1228, 6), (1229, 4), - (1230, 4), (1231, 3), (1232, 3), (1234, 1), (1242, 5), (1243, 1), (1244, 5), (1245, 6), - (1246, 2), (1247, 3), (1248, 1), (1249, 1), (1259, 4), (1260, 1), (1261, 1), (1262, 6), - (1263, 5), (1264, 4), (1265, 3), (1266, 3), (1267, 9), (1268, 2), (1269, 7), (1270, 2), - (1281, 2), (1283, 3), (1284, 3), (1286, 3), (1287, 1), (1288, 1), (1296, 6), (1298, 1), - (1299, 1), (1300, 7), (1301, 3), (1302, 3), (1303, 1), (1304, 8), (1305, 10), (1306, 11), - (1307, 4), (1308, 3), (1311, 1), (1320, 4), (1321, 1), (1322, 1), (1323, 2), (1324, 1), - (1325, 1), (1327, 1), (1330, 2), (1338, 2), (1339, 2), (1341, 4), (1342, 2), (1343, 3), - (1344, 17), (1345, 16), (1346, 7), (1347, 2), (1348, 1), (1350, 1), (1352, 3), (1359, 3), - (1360, 1), (1362, 2), (1365, 1), (1366, 1), (1374, 2), (1375, 1), (1376, 1), (1377, 1), - (1378, 2), (1380, 1), (1381, 2), (1382, 3), (1383, 9), (1384, 7), (1385, 13), (1386, 5), - (1388, 1), (1389, 1), (1394, 1), (1396, 2), (1400, 2), (1415, 2), (1416, 1), (1417, 1), - (1418, 4), (1419, 6), (1420, 5), (1421, 2), (1422, 3), (1423, 8), (1424, 10), (1425, 5), - (1426, 1), (1428, 1), (1443, 1), (1445, 2), (1454, 1), (1455, 3), (1456, 1), (1457, 2), - (1458, 4), (1459, 4), (1460, 10), (1461, 8), (1462, 11), (1463, 5), (1464, 5), (1465, 1), - (1480, 1), (1483, 1), (1485, 1), (1494, 2), (1495, 1), (1496, 7), (1497, 7), (1498, 5), - (1499, 4), (1500, 5), (1501, 12), (1502, 10), (1503, 3), (1504, 2), (1505, 2), (1507, 3), - (1520, 1), (1529, 3), (1532, 2), (1533, 23), (1535, 14), (1536, 8), (1537, 2), (1538, 3), - (1539, 10), (1540, 11), (1541, 13), (1542, 4), (1543, 2), (1546, 1), (1548, 1), (1551, 2), - (1571, 2), (1572, 6), (1573, 4), (1574, 4), (1575, 2), (1576, 7), (1577, 5), (1578, 8), - (1579, 12), (1580, 4), (1581, 5), (1582, 1), (1586, 1), (1595, 1), (1609, 2), (1610, 2), - (1611, 3), (1612, 3), (1613, 5), (1614, 6), (1615, 1), (1616, 8), (1617, 11), (1618, 12), - (1619, 11), (1620, 5), (1621, 1), (1622, 1), (1649, 2), (1650, 2), (1651, 8), (1652, 2), - (1653, 5), (1654, 5), (1655, 2), (1656, 13), (1657, 20), (1658, 10), (1659, 8), (1660, 4), - (1661, 2), (1663, 1), (1688, 2), (1689, 2), (1690, 1), (1691, 5), (1692, 3), (1693, 5), - (1694, 8), (1695, 13), (1696, 12), (1697, 5), (1698, 1), (1699, 2), (1700, 1), (1701, 1), - (1702, 1), (1703, 1), (1705, 1), (1727, 3), (1728, 3), (1729, 2), (1730, 3), (1731, 4), - (1732, 5), (1733, 3), (1734, 7), (1735, 15), (1736, 15), (1737, 7), (1738, 6), (1739, 1), - (1741, 1), (1742, 1), (1763, 6), (1766, 8), (1767, 2), (1768, 1), (1769, 4), (1770, 5), - (1771, 1), (1772, 5), (1773, 13), (1774, 10), (1775, 9), (1776, 9), (1777, 4), (1778, 2), - (1779, 2), (1804, 1), (1805, 2), (1807, 2), (1808, 2), (1809, 3), (1810, 3), (1811, 6), - (1812, 12), (1813, 13), (1814, 9), (1815, 3), (1816, 2), (1817, 4), (1821, 2), (1844, 2), - (1845, 1), (1846, 2), (1847, 8), (1848, 6), (1849, 5), (1850, 7), (1851, 4), (1852, 3), - (1853, 9), (1854, 5), (1855, 6), (1856, 3), (1858, 1), (1860, 1), (1882, 1), (1883, 2), - (1884, 1), (1885, 4), (1886, 1), (1887, 2), (1888, 3), (1889, 2), (1890, 8), (1891, 6), - (1892, 14), (1893, 3), (1894, 1), (1895, 1), (1896, 1), (1898, 1), (1922, 6), (1923, 1), - (1924, 3), (1925, 5), (1926, 4), (1927, 6), (1928, 7), (1929, 7), (1930, 13), (1931, 11), - (1932, 8), (1933, 3), (1934, 1), (1936, 2), (1937, 2), (1938, 1), (1939, 2), (1961, 3), - (1963, 3), (1964, 2), (1965, 5), (1966, 7), (1967, 4), (1968, 5), (1969, 9), (1970, 11), - (1971, 7), (1972, 5), (1973, 3), (1974, 2), (1977, 1), (1997, 2), (2000, 2), (2001, 1), - (2002, 4), (2003, 4), (2004, 7), (2005, 3), (2006, 9), (2007, 13), (2008, 22), (2009, 8), - (2010, 10), (2011, 5), (2012, 2), (2014, 1), (2016, 1), (2021, 1), (2039, 3), (2041, 5), - (2042, 5), (2043, 8), (2044, 6), (2045, 2), (2046, 12), (2047, 10), (2048, 9), (2049, 4), - (2050, 4), (2051, 2), (2054, 3), (2062, 1), (2070, 5), (2077, 1), (2078, 4), (2079, 4), - (2080, 2), (2081, 4), (2082, 5), (2083, 7), (2084, 4), (2085, 13), (2086, 4), (2087, 7), - (2088, 6), (2089, 8), (2090, 1), (2091, 1), (2092, 4), (2113, 6), (2117, 6), (2118, 2), - (2120, 3), (2121, 5), (2122, 9), (2123, 8), (2124, 8), (2125, 9), (2126, 6), (2127, 7), - (2128, 7), (2130, 2), (2133, 1), (2156, 4), (2157, 1), (2158, 3), (2159, 1), (2160, 6), - (2161, 3), (2162, 7), (2163, 10), (2164, 9), (2165, 9), (2166, 8), (2167, 5), (2170, 3), - (2171, 1), (2193, 1), (2194, 1), (2195, 2), (2196, 2), (2197, 2), (2198, 4), (2199, 5), - (2200, 9), (2201, 5), (2202, 13), (2203, 17), (2204, 13), (2205, 11), (2206, 1), (2207, 2), - (2209, 1), (2210, 2), (2234, 7), (2235, 1), (2236, 2), (2238, 6), (2239, 9), (2240, 7), - (2241, 13), (2242, 12), (2243, 9), (2244, 6), (2245, 4), (2246, 2), (2247, 3), (2273, 2), - (2274, 4), (2275, 2), (2277, 4), (2278, 9), (2279, 7), (2280, 8), (2281, 7), (2282, 4), - (2283, 3), (2284, 2), (2285, 2), (2286, 1), (2290, 1), (2311, 2), (2312, 3), (2313, 1), - (2314, 4), (2315, 3), (2316, 3), (2317, 10), (2318, 11), (2319, 12), (2320, 11), (2321, 17), - (2322, 9), (2323, 3), (2325, 3), (2326, 4), (2341, 1), (2351, 12), (2352, 3), (2353, 4), - (2354, 5), (2355, 7), (2356, 7), (2357, 5), (2358, 8), (2359, 7), (2360, 10), (2361, 7), - (2362, 4), (2363, 2), (2364, 2), (2365, 5), (2367, 1), (2369, 1), (2390, 1), (2391, 1), - (2392, 5), (2394, 4), (2395, 6), (2396, 7), (2397, 8), (2398, 7), (2399, 5), (2400, 10), - (2401, 3), (2402, 1), (2403, 1), (2408, 5), (2412, 1), (2428, 1), (2429, 12), (2430, 2), - (2431, 4), (2433, 2), (2434, 9), (2435, 8), (2436, 10), (2437, 11), (2438, 13), (2439, 11), - (2440, 3), (2441, 1), (2442, 1), (2443, 2), (2445, 1), (2464, 2), (2468, 1), (2469, 2), - (2470, 6), (2471, 3), (2472, 3), (2473, 5), (2474, 7), (2475, 6), (2476, 13), (2477, 16), - (2478, 10), (2479, 10), (2480, 1), (2482, 1), (2483, 1), (2484, 2), (2509, 1), (2510, 2), - (2511, 8), (2512, 6), (2513, 7), (2514, 12), (2515, 10), (2516, 10), (2517, 9), (2518, 9), - (2519, 4), (2520, 2), (2521, 3), (2522, 3), (2546, 2), (2547, 1), (2548, 1), (2549, 2), - (2550, 7), (2551, 2), (2552, 5), (2553, 6), (2554, 13), (2555, 14), (2556, 8), (2557, 5), - (2558, 2), (2559, 1), (2561, 1), (2589, 5), (2590, 6), (2591, 3), (2592, 8), (2593, 10), - (2594, 14), (2595, 3), (2596, 7), (2597, 8), (2598, 2), (2599, 2), (2600, 2), (2604, 1), - (2625, 1), (2628, 2), (2629, 5), (2630, 2), (2631, 4), (2632, 9), (2633, 8), (2634, 14), - (2635, 3), (2636, 6), (2637, 2), (2638, 1), (2639, 2), (2641, 1), (2642, 1), (2643, 1), - (2664, 4), (2665, 6), (2666, 7), (2667, 3), (2668, 3), (2669, 5), (2670, 9), (2671, 11), - (2672, 12), (2673, 15), (2674, 3), (2675, 6), (2676, 1), (2677, 2), (2678, 2), (2679, 1), - (2682, 1), (2683, 2), (2703, 3), (2704, 3), (2705, 2), (2706, 4), (2707, 4), (2708, 4), - (2709, 4), (2710, 8), (2711, 8), (2712, 11), (2713, 6), (2714, 7), (2715, 2), (2716, 2), - (2717, 1), (2718, 2), (2731, 2), (2742, 1), (2743, 2), (2745, 2), (2746, 8), (2747, 3), - (2748, 5), (2749, 8), (2750, 8), (2751, 6), (2752, 4), (2753, 5), (2755, 1), (2756, 1), - (2757, 4), (2758, 1), (2760, 5), (2775, 1), (2778, 1), (2781, 2), (2782, 2), (2783, 1), - (2784, 3), (2785, 3), (2786, 2), (2787, 11), (2788, 7), (2789, 8), (2790, 9), (2791, 4), - (2792, 4), (2793, 3), (2795, 3), (2796, 4), (2797, 1), (2798, 1), (2799, 1), (2820, 2), - (2822, 1), (2823, 2), (2825, 4), (2826, 4), (2827, 6), (2828, 4), (2829, 8), (2830, 5), - (2831, 3), (2832, 2), (2835, 3), (2836, 3), (2837, 1), (2859, 3), (2861, 5), (2862, 3), - (2863, 7), (2864, 3), (2865, 6), (2866, 5), (2867, 11), (2868, 9), (2869, 5), (2870, 6), - (2871, 1), (2873, 2), (2877, 1), (2898, 6), (2900, 1), (2901, 2), (2902, 7), (2903, 4), - (2904, 2), (2905, 7), (2906, 7), (2907, 9), (2908, 4), (2909, 3), (2910, 2), (2911, 2), - (2912, 2), (2913, 1), (2916, 1), (2937, 2), (2938, 1), (2940, 4), (2941, 4), (2942, 4), - (2943, 4), (2944, 16), (2945, 11), (2946, 3), (2947, 11), (2948, 3), (2949, 2), (2950, 2), - (2951, 1), (2954, 1), (2962, 6), (2976, 1), (2977, 1), (2978, 2), (2979, 2), (2980, 3), - (2981, 3), (2982, 2), (2983, 2), (2984, 5), (2985, 11), (2986, 6), (2987, 2), (2988, 1), - (2989, 2), (2992, 1), (3015, 2), (3016, 4), (3017, 4), (3018, 2), (3019, 3), (3020, 3), - (3021, 6), (3022, 11), (3023, 10), (3024, 2), (3025, 5), (3026, 1), (3027, 3), (3029, 2), - (3035, 1), (3054, 4), (3057, 2), (3058, 3), (3059, 5), (3060, 3), (3061, 8), (3062, 5), - (3063, 4), (3064, 6), (3065, 2), (3066, 1), (3086, 1), (3092, 2), (3093, 4), (3094, 1), - (3095, 4), (3096, 1), (3097, 2), (3098, 3), (3099, 3), (3100, 5), (3101, 6), (3102, 7), - (3103, 2), (3104, 3), (3105, 4), (3110, 1), (3124, 6), (3132, 4), (3134, 3), (3135, 1), - (3136, 5), (3137, 3), (3138, 5), (3139, 8), (3140, 7), (3141, 6), (3142, 9), (3143, 1), - (3144, 2), (3145, 1), (3147, 1), (3148, 2), (3171, 2), (3172, 1), (3173, 2), (3174, 3), - (3175, 4), (3176, 4), (3177, 4), (3178, 5), (3179, 2), (3180, 8), (3181, 4), (3182, 2), - (3183, 3), (3184, 1), (3189, 1), (3194, 4), (3210, 2), (3212, 2), (3213, 3), (3214, 7), - (3215, 7), (3216, 4), (3217, 4), (3218, 8), (3219, 5), (3220, 4), (3221, 1), (3223, 1), - (3249, 2), (3250, 2), (3251, 1), (3252, 2), (3253, 4), (3254, 5), (3255, 4), (3256, 6), - (3257, 4), (3258, 8), (3259, 4), (3260, 3), (3261, 2), (3262, 1), (3288, 3), (3290, 3), - (3291, 2), (3292, 4), (3293, 2), (3294, 4), (3295, 5), (3296, 11), (3297, 10), (3298, 2), - (3299, 4), (3300, 1), (3301, 2), (3303, 1), (3306, 1), (3327, 1), (3329, 2), (3330, 6), - (3331, 5), (3332, 2), (3333, 1), (3334, 5), (3335, 6), (3336, 5), (3337, 5), (3338, 2), - (3340, 1), (3342, 1), (3366, 13), (3368, 4), (3369, 2), (3370, 5), (3371, 5), (3372, 4), - (3373, 3), (3374, 7), (3375, 5), (3376, 2), (3377, 1), (3378, 1), (3380, 1), (3382, 1), - (3389, 6), (3394, 1), (3405, 6), (3406, 1), (3407, 2), (3408, 3), (3409, 5), (3410, 2), - (3411, 3), (3412, 4), (3413, 5), (3414, 6), (3415, 5), (3417, 2), (3418, 1), (3421, 1), - (3423, 1), (3424, 1), (3444, 3), (3445, 1), (3447, 3), (3448, 1), (3449, 2), (3450, 4), - (3451, 5), (3452, 6), (3453, 8), (3454, 6), (3455, 2), (3456, 4), (3477, 1), (3483, 1), - (3484, 4), (3485, 5), (3486, 2), (3487, 3), (3488, 3), (3489, 6), (3490, 8), (3491, 6), - (3492, 8), (3493, 5), (3494, 2), (3499, 1), (3512, 4), (3522, 1), (3523, 2), (3524, 3), - (3525, 3), (3526, 6), (3527, 5), (3528, 3), (3529, 10), (3530, 10), (3531, 7), (3532, 4), - (3533, 3), (3534, 1), (3535, 2), (3561, 1), (3562, 2), (3563, 3), (3564, 3), (3565, 2), - (3566, 6), (3567, 2), (3568, 2), (3569, 14), (3570, 7), (3571, 2), (3572, 2), (3573, 1), - (3574, 2), (3575, 1), (3576, 1), (3600, 4), (3601, 3), (3602, 5), (3603, 3), (3604, 4), - (3605, 4), (3606, 7), (3607, 8), (3608, 5), (3609, 3), (3610, 3), (3639, 3), (3640, 1), - (3641, 1), (3642, 5), (3643, 2), (3644, 6), (3645, 4), (3646, 4), (3647, 3), (3648, 2), - (3649, 1), (3650, 2), (3651, 1), (3678, 1), (3680, 4), (3681, 2), (3682, 7), (3683, 2), - (3684, 6), (3685, 4), (3686, 4), (3687, 4), (3688, 3), (3690, 2), (3691, 2), (3692, 1), - (3694, 1), (3717, 1), (3718, 1), (3719, 3), (3720, 5), (3721, 5), (3722, 8), (3723, 3), - (3724, 2), (3725, 2), (3726, 2), (3727, 4), (3728, 1), (3731, 1), (3732, 2), (3733, 1), - (3756, 4), (3758, 13), (3759, 2), (3760, 7), (3761, 3), (3762, 4), (3763, 2), (3764, 6), - (3765, 1), (3766, 2), (3769, 1), (3795, 1), (3797, 3), (3798, 4), (3799, 9), (3800, 3), - (3801, 6), (3802, 5), (3803, 2), (3804, 5), (3805, 2), (3807, 1), (3808, 1), (3834, 1), - (3835, 1), (3836, 4), (3837, 1), (3838, 4), (3839, 5), (3840, 4), (3841, 7), (3842, 8), - (3843, 5), (3844, 1), (3845, 3), (3846, 2), (3847, 1), (3874, 4), (3875, 3), (3876, 7), - (3877, 7), (3878, 3), (3879, 3), (3880, 2), (3881, 5), (3882, 3), (3883, 4), (3884, 1), - (3885, 1), (3886, 1), (3913, 1), (3914, 3), (3915, 4), (3916, 4), (3917, 6), (3920, 2), - (3921, 5), (3922, 4), (3923, 1), (3925, 1), (3928, 1), (3929, 1), (3951, 1), (3952, 1), - (3953, 3), (3954, 2), (3955, 1), (3956, 8), (3957, 4), (3958, 5), (3959, 3), (3960, 5), - (3961, 3), (3962, 1), (3963, 2), (3964, 1), (3991, 3), (3992, 4), (3993, 2), (3994, 5), - (3995, 3), (3996, 6), (3997, 8), (3998, 4), (3999, 4), (4000, 1), (4001, 3), (4002, 1), - (4003, 1), (4031, 2), (4032, 4), (4033, 7), (4034, 4), (4035, 3), (4036, 3), (4037, 1), - (4038, 3), (4039, 5), (4040, 4), (4041, 1), (4069, 1), (4070, 3), (4071, 4), (4072, 1), - (4073, 2), (4074, 4), (4075, 1), (4076, 2), (4077, 5), (4078, 4), (4079, 2), (4083, 1), - (4107, 1), (4108, 2), (4109, 2), (4110, 3), (4111, 4), (4112, 4), (4113, 6), (4114, 1), - (4115, 5), (4116, 1), (4117, 3), (4119, 1), (4120, 1), (4147, 2), (4148, 4), (4150, 3), - (4151, 3), (4152, 2), (4153, 5), (4154, 4), (4155, 4), (4156, 3), (4157, 3), (4158, 2), - (4161, 1), (4185, 2), (4187, 2), (4188, 7), (4189, 5), (4190, 2), (4191, 1), (4192, 5), - (4193, 2), (4194, 3), (4195, 2), (4196, 2), (4197, 2), (4198, 2), (4224, 2), (4225, 2), - (4226, 1), (4227, 2), (4228, 4), (4229, 4), (4230, 3), (4231, 3), (4232, 3), (4233, 3), - (4234, 3), (4236, 1), (4259, 2), (4263, 4), (4264, 1), (4265, 2), (4266, 4), (4267, 3), - (4268, 1), (4269, 5), (4270, 5), (4271, 4), (4272, 3), (4273, 3), (4274, 2), (4277, 1), - (4280, 5), (4300, 2), (4302, 3), (4303, 2), (4304, 4), (4305, 6), (4306, 2), (4307, 3), - (4308, 2), (4309, 4), (4310, 7), (4311, 2), (4312, 4), (4313, 4), (4314, 1), (4342, 1), - (4343, 3), (4344, 7), (4345, 7), (4346, 2), (4347, 2), (4348, 6), (4349, 3), (4350, 3), - (4351, 3), (4352, 2), (4353, 2), (4354, 1), (4356, 2), (4380, 4), (4383, 8), (4385, 3), - (4386, 8), (4387, 3), (4388, 5), (4389, 1), (4390, 1), (4391, 2), (4392, 2), (4393, 2), - (4419, 4), (4420, 2), (4421, 3), (4422, 5), (4423, 7), (4424, 3), (4425, 5), (4426, 5), - (4427, 3), (4428, 4), (4429, 1), (4430, 3), (4431, 1), (4432, 7), (4434, 1), (4458, 5), - (4460, 3), (4461, 2), (4462, 6), (4463, 3), (4464, 3), (4465, 3), (4466, 10), (4467, 3), - (4468, 2), (4469, 2), (4470, 1), (4473, 1), (4498, 2), (4500, 3), (4501, 8), (4502, 3), - (4503, 1), (4504, 6), (4505, 3), (4506, 3), (4507, 1), (4508, 2), (4509, 2), (4510, 2), - (4511, 2), (4536, 1), (4538, 3), (4539, 5), (4540, 3), (4541, 6), (4542, 2), (4543, 4), - (4544, 3), (4545, 3), (4546, 1), (4547, 1), (4550, 1), (4575, 3), (4576, 1), (4577, 5), - (4578, 3), (4579, 8), (4580, 3), (4581, 4), (4582, 4), (4583, 4), (4584, 5), (4587, 3), - (4588, 2), (4614, 1), (4616, 1), (4617, 4), (4618, 4), (4619, 1), (4620, 3), (4621, 3), - (4622, 2), (4623, 4), (4624, 3), (4627, 2), (4628, 2), (4653, 2), (4655, 3), (4656, 3), - (4657, 4), (4658, 3), (4659, 4), (4660, 3), (4661, 2), (4662, 7), (4663, 7), (4664, 1), - (4665, 2), (4666, 1), (4693, 1), (4694, 2), (4695, 2), (4696, 5), (4699, 1), (4700, 4), - (4701, 3), (4702, 2), (4703, 1), (4704, 1), (4731, 3), (4733, 2), (4734, 6), (4735, 1), - (4736, 2), (4737, 3), (4738, 3), (4739, 3), (4740, 4), (4741, 2), (4742, 3), (4743, 2), - (4744, 2), (4770, 1), (4771, 3), (4772, 2), (4773, 4), (4774, 5), (4775, 3), (4776, 5), - (4777, 8), (4778, 1), (4779, 2), (4780, 3), (4781, 1), (4782, 1), (4785, 2), (4809, 2), - (4811, 2), (4812, 6), (4813, 4), (4814, 1), (4815, 2), (4816, 2), (4817, 1), (4818, 5), - (4819, 2), (4820, 1), (4821, 2), (4834, 1), (4848, 1), (4850, 3), (4851, 2), (4852, 4), - (4853, 1), (4854, 1), (4855, 3), (4856, 8), (4857, 2), (4858, 2), (4859, 2), (4860, 2), - (4862, 2), (4887, 2), (4888, 1), (4890, 3), (4891, 4), (4893, 3), (4894, 2), (4895, 4), - (4896, 6), (4897, 3), (4899, 1), (4900, 1), (4926, 2), (4927, 1), (4928, 4), (4929, 2), - (4930, 2), (4931, 2), (4932, 4), (4933, 7), (4934, 1), (4935, 3), (4937, 1), (4938, 2), - (4939, 1), (4942, 1), (4964, 1), (4965, 1), (4966, 1), (4968, 1), (4969, 5), (4970, 5), - (4971, 3), (4972, 1), (4973, 7), (4974, 1), (4975, 2), (4977, 1), (4978, 1), (4979, 2), - (5004, 3), (5005, 2), (5006, 1), (5007, 1), (5008, 2), (5009, 3), (5010, 1), (5011, 4), - (5012, 4), (5013, 1), (5014, 2), (5015, 5), (5016, 1), (5018, 2), (5019, 1), (5043, 2), - (5046, 6), (5047, 1), (5048, 1), (5049, 1), (5050, 1), (5051, 1), (5052, 5), (5053, 4), - (5054, 2), (5055, 1), (5056, 1), (5082, 1), (5083, 1), (5084, 4), (5085, 4), (5086, 5), - (5087, 2), (5089, 1), (5090, 3), (5091, 6), (5092, 1), (5093, 1), (5094, 4), (5096, 1), - (5098, 2), (5121, 2), (5123, 3), (5124, 4), (5125, 1), (5126, 3), (5127, 1), (5128, 5), - (5130, 2), (5131, 1), (5132, 1), (5133, 2), (5134, 2), (5135, 1), (5136, 2), (5137, 1), - (5160, 1), (5162, 4), (5163, 1), (5164, 3), (5166, 1), (5167, 2), (5168, 8), (5169, 4), - (5170, 1), (5173, 1), (5198, 1), (5201, 2), (5202, 4), (5204, 1), (5205, 1), (5206, 1), - (5207, 3), (5208, 1), (5209, 5), (5210, 3), (5211, 1), (5213, 2), (5215, 1), (5238, 1), - (5239, 6), (5241, 1), (5242, 2), (5243, 2), (5244, 2), (5245, 2), (5246, 4), (5247, 5), - (5248, 3), (5250, 2), (5252, 2), (5280, 3), (5281, 1), (5283, 4), (5284, 2), (5285, 2), - (5286, 1), (5288, 3), (5289, 1), (5290, 1), (5291, 1), (5317, 1), (5318, 2), (5319, 2), - (5321, 3), (5322, 2), (5323, 6), (5324, 1), (5325, 1), (5326, 2), (5327, 3), (5328, 2), - (5329, 2), (5330, 1), (5331, 1), (5356, 1), (5357, 3), (5358, 4), (5360, 1), (5361, 1), - (5362, 2), (5363, 1), (5364, 1), (5366, 2), (5367, 1), (5369, 1), (5395, 2), (5396, 2), - (5397, 2), (5398, 2), (5400, 2), (5401, 2), (5402, 4), (5403, 3), (5404, 1), (5405, 3), - (5406, 1), (5408, 1), (5434, 1), (5435, 2), (5436, 2), (5437, 1), (5438, 4), (5439, 3), - (5440, 3), (5441, 5), (5442, 1), (5443, 1), (5445, 3), (5474, 4), (5475, 1), (5476, 3), - (5477, 1), (5478, 2), (5479, 2), (5480, 4), (5481, 5), (5482, 2), (5485, 2), (5486, 1), - (5512, 1), (5513, 2), (5514, 4), (5515, 4), (5517, 2), (5518, 2), (5519, 2), (5520, 4), - (5521, 2), (5523, 1), (5524, 3), (5525, 9), (5526, 1), (5542, 3), (5551, 1), (5552, 1), - (5553, 1), (5554, 4), (5555, 4), (5556, 1), (5557, 5), (5558, 3), (5559, 1), (5560, 2), - (5563, 1), (5564, 1), (5565, 2), (5566, 1), (5590, 1), (5591, 3), (5592, 5), (5593, 4), - (5594, 1), (5595, 1), (5596, 1), (5597, 3), (5598, 3), (5599, 3), (5601, 2), (5602, 2), - (5603, 1), (5604, 2), (5620, 6), (5628, 1), (5629, 1), (5630, 1), (5631, 1), (5632, 1), - (5633, 3), (5634, 2), (5635, 2), (5636, 2), (5637, 2), (5638, 4), (5639, 3), (5640, 1), - (5641, 1), (5642, 1), (5643, 2), (5668, 1), (5669, 1), (5670, 2), (5671, 3), (5672, 2), - (5673, 2), (5675, 1), (5676, 2), (5677, 2), (5678, 1), (5680, 2), (5706, 1), (5707, 1), - (5709, 2), (5710, 2), (5712, 4), (5713, 1), (5714, 3), (5715, 4), (5718, 1), (5719, 3), - (5721, 1), (5745, 5), (5746, 2), (5747, 2), (5748, 2), (5749, 2), (5750, 3), (5751, 3), - (5753, 2), (5754, 1), (5755, 2), (5756, 3), (5757, 1), (5759, 1), (5785, 2), (5786, 2), - (5787, 4), (5788, 2), (5789, 6), (5790, 5), (5791, 3), (5792, 3), (5793, 2), (5794, 1), - (5795, 1), (5797, 2), (5798, 2), (5799, 1), (5801, 1), (5825, 3), (5826, 1), (5827, 3), - (5828, 3), (5829, 5), (5831, 3), (5832, 5), (5833, 2), (5834, 1), (5835, 2), (5839, 2), - (5862, 1), (5863, 1), (5865, 3), (5868, 1), (5869, 3), (5870, 2), (5871, 4), (5872, 2), - (5874, 2), (5875, 3), (5876, 3), (5901, 1), (5903, 2), (5904, 1), (5905, 1), (5906, 1), - (5907, 3), (5908, 3), (5909, 1), (5910, 2), (5911, 2), (5912, 2), (5914, 1), (5915, 3), - (5917, 1), (5941, 1), (5942, 2), (5943, 2), (5944, 2), (5945, 2), (5946, 2), (5947, 4), - (5948, 1), (5949, 1), (5950, 2), (5951, 2), (5952, 2), (5953, 2), (5955, 2), (5957, 2), - (5980, 1), (5981, 2), (5982, 4), (5984, 3), (5985, 2), (5986, 2), (5987, 3), (5989, 4), - (5991, 2), (5993, 2), (5994, 2), (5995, 2), (5996, 1), (6019, 1), (6021, 2), (6022, 1), - (6023, 1), (6024, 5), (6025, 2), (6026, 1), (6027, 3), (6028, 6), (6030, 1), (6031, 1), - (6032, 1), (6034, 1), (6059, 4), (6060, 2), (6061, 3), (6062, 1), (6063, 1), (6065, 4), - (6066, 2), (6067, 2), (6068, 1), (6069, 2), (6070, 3), (6071, 2), (6073, 1), (6074, 2), - (6098, 1), (6099, 1), (6100, 1), (6101, 1), (6102, 3), (6103, 1), (6104, 2), (6105, 6), - (6106, 3), (6107, 1), (6108, 2), (6111, 2), (6112, 1), (6114, 1), (6130, 1), (6135, 1), - (6137, 1), (6138, 2), (6139, 1), (6141, 4), (6142, 1), (6143, 2), (6144, 1), (6146, 1), - (6148, 2), (6150, 2), (6151, 1), (6177, 3), (6178, 2), (6179, 2), (6180, 2), (6181, 2), - (6182, 1), (6185, 1), (6186, 2), (6187, 1), (6188, 2), (6189, 2), (6190, 2), (6215, 2), - (6216, 3), (6217, 3), (6218, 1), (6219, 3), (6220, 3), (6221, 6), (6222, 2), (6223, 3), - (6224, 3), (6225, 1), (6226, 2), (6227, 1), (6228, 1), (6254, 1), (6255, 1), (6256, 1), - (6257, 1), (6258, 1), (6259, 3), (6260, 3), (6261, 2), (6262, 2), (6264, 2), (6266, 1), - (6292, 1), (6293, 1), (6294, 1), (6295, 1), (6296, 3), (6298, 3), (6299, 5), (6300, 2), - (6301, 2), (6302, 2), (6303, 3), (6304, 1), (6305, 2), (6306, 2), (6307, 1), (6308, 2), - (6324, 1), (6330, 1), (6331, 2), (6332, 2), (6333, 4), (6334, 2), (6335, 1), (6337, 3), - (6338, 1), (6339, 1), (6341, 2), (6342, 2), (6343, 1), (6344, 2), (6345, 1), (6347, 1), - (6372, 1), (6374, 4), (6375, 2), (6376, 2), (6378, 3), (6379, 5), (6382, 1), (6383, 3), - (6384, 1), (6386, 1), (6402, 8), (6408, 1), (6410, 2), (6413, 1), (6414, 2), (6415, 1), - (6416, 2), (6417, 3), (6418, 3), (6419, 3), (6420, 1), (6421, 1), (6423, 2), (6426, 1), - (6430, 1), (6447, 1), (6448, 2), (6451, 2), (6452, 3), (6453, 2), (6454, 1), (6455, 4), - (6456, 3), (6457, 3), (6459, 3), (6461, 2), (6462, 2), (6463, 1), (6486, 2), (6490, 1), - (6492, 3), (6493, 1), (6494, 5), (6495, 3), (6496, 2), (6497, 2), (6498, 4), (6499, 2), - (6500, 1), (6501, 3), (6502, 1), (6503, 3), (6504, 1), (6505, 1), (6527, 1), (6528, 2), - (6530, 2), (6531, 4), (6533, 2), (6535, 1), (6536, 2), (6537, 1), (6538, 2), (6541, 1), - (6564, 1), (6565, 1), (6566, 1), (6567, 1), (6569, 3), (6570, 4), (6571, 2), (6572, 2), - (6573, 4), (6574, 5), (6575, 1), (6576, 1), (6577, 2), (6578, 2), (6579, 2), (6580, 1), - (6581, 1), (6582, 1), (6603, 2), (6604, 2), (6605, 1), (6606, 1), (6607, 1), (6608, 1), - (6609, 3), (6610, 3), (6611, 1), (6612, 2), (6613, 1), (6614, 2), (6615, 1), (6617, 4), - (6618, 4), (6619, 1), (6620, 4), (6644, 1), (6645, 1), (6646, 1), (6647, 1), (6648, 5), - (6649, 2), (6650, 1), (6651, 1), (6652, 3), (6653, 2), (6654, 3), (6655, 1), (6656, 2), - (6657, 2), (6658, 2), (6686, 1), (6687, 4), (6688, 5), (6689, 4), (6690, 1), (6692, 1), - (6693, 1), (6694, 3), (6695, 3), (6696, 1), (6697, 1), (6722, 2), (6723, 1), (6724, 1), - (6725, 3), (6726, 1), (6727, 2), (6728, 2), (6729, 6), (6731, 1), (6734, 1), (6735, 3), - (6736, 3), (6737, 1), (6761, 2), (6762, 1), (6763, 3), (6764, 2), (6765, 1), (6766, 5), - (6767, 1), (6769, 3), (6770, 2), (6771, 3), (6772, 3), (6773, 3), (6774, 4), (6775, 1), - (6777, 1), (6798, 1), (6800, 2), (6801, 1), (6802, 3), (6803, 2), (6804, 3), (6805, 2), - (6806, 7), (6807, 1), (6808, 2), (6809, 2), (6810, 4), (6811, 2), (6812, 3), (6813, 2), - (6814, 1), (6815, 1), (6816, 2), (6837, 1), (6839, 1), (6841, 5), (6842, 3), (6843, 4), - (6844, 5), (6845, 1), (6847, 3), (6848, 1), (6849, 2), (6850, 3), (6851, 1), (6852, 2), - (6853, 2), (6855, 1), (6863, 6), (6878, 1), (6879, 2), (6881, 2), (6882, 3), (6883, 2), - (6884, 4), (6885, 4), (6886, 2), (6887, 3), (6888, 3), (6889, 3), (6890, 1), (6891, 2), - (6892, 2), (6896, 1), (6915, 1), (6916, 2), (6917, 2), (6918, 1), (6919, 1), (6921, 1), - (6922, 2), (6923, 8), (6924, 3), (6926, 7), (6927, 2), (6928, 2), (6929, 1), (6932, 1), - (6952, 6), (6956, 1), (6957, 4), (6959, 5), (6960, 2), (6961, 6), (6962, 6), (6963, 1), - (6964, 2), (6965, 5), (6967, 4), (6969, 1), (6970, 3), (6971, 1), (6972, 1), (6993, 1), - (6995, 2), (6996, 1), (6997, 2), (6998, 1), (6999, 1), (7000, 5), (7001, 2), (7002, 4), - (7003, 3), (7004, 1), (7005, 1), (7007, 2), (7008, 2), (7009, 1), (7010, 1), (7014, 1), - (7033, 1), (7035, 2), (7037, 1), (7038, 3), (7039, 2), (7040, 8), (7041, 1), (7042, 2), - (7043, 2), (7044, 1), (7045, 1), (7046, 2), (7047, 1), (7048, 2), (7070, 1), (7073, 1), - (7075, 1), (7076, 1), (7077, 1), (7078, 3), (7079, 5), (7080, 4), (7081, 4), (7083, 1), - (7084, 2), (7085, 4), (7086, 2), (7088, 2), (7089, 3), (7098, 6), (7111, 1), (7113, 1), - (7114, 3), (7115, 7), (7117, 3), (7118, 6), (7119, 1), (7120, 2), (7121, 2), (7122, 3), - (7123, 1), (7125, 2), (7126, 2), (7130, 1), (7153, 5), (7155, 2), (7156, 4), (7157, 3), - (7158, 2), (7159, 1), (7160, 2), (7161, 1), (7162, 2), (7163, 4), (7164, 3), (7167, 3), - (7184, 2), (7190, 1), (7192, 1), (7194, 1), (7196, 4), (7198, 1), (7199, 2), (7200, 4), - (7201, 4), (7202, 2), (7203, 1), (7204, 2), (7230, 2), (7231, 1), (7232, 3), (7233, 3), - (7234, 1), (7235, 2), (7236, 3), (7238, 2), (7239, 4), (7240, 1), (7241, 3), (7242, 3), - (7243, 2), (7244, 1), (7245, 1), (7248, 1), (7266, 1), (7268, 1), (7270, 2), (7271, 4), - (7272, 1), (7273, 2), (7274, 6), (7275, 2), (7278, 3), (7279, 4), (7280, 2), (7281, 1), - (7282, 2), (7283, 1), (7289, 1), (7306, 1), (7307, 1), (7308, 2), (7309, 1), (7310, 2), - (7311, 2), (7312, 3), (7313, 3), (7314, 1), (7315, 4), (7316, 3), (7317, 2), (7318, 4), - (7319, 1), (7320, 2), (7321, 1), (7324, 1), (7345, 1), (7347, 2), (7348, 6), (7349, 2), - (7350, 6), (7351, 8), (7352, 2), (7353, 4), (7358, 2), (7359, 2), (7360, 2), (7361, 2), - (7372, 6), (7385, 1), (7386, 3), (7387, 1), (7388, 1), (7389, 3), (7390, 3), (7391, 1), - (7392, 4), (7394, 3), (7395, 3), (7396, 4), (7397, 2), (7398, 4), (7399, 2), (7401, 1), - (7403, 1), (7425, 1), (7426, 2), (7427, 5), (7428, 4), (7429, 5), (7430, 4), (7431, 1), - (7432, 1), (7434, 1), (7435, 2), (7436, 7), (7437, 1), (7438, 1), (7439, 1), (7446, 1), - (7464, 1), (7466, 2), (7467, 3), (7468, 2), (7469, 5), (7470, 3), (7471, 2), (7472, 1), - (7474, 1), (7475, 4), (7476, 4), (7489, 1), (7490, 6), (7503, 1), (7504, 2), (7505, 3), - (7506, 2), (7507, 2), (7508, 2), (7509, 1), (7510, 2), (7511, 3), (7512, 3), (7513, 5), - (7514, 1), (7515, 4), (7517, 1), (7518, 1), (7520, 1), (7522, 1), (7539, 1), (7541, 2), - (7544, 6), (7545, 3), (7546, 2), (7547, 5), (7548, 3), (7549, 2), (7550, 1), (7552, 1), - (7553, 5), (7554, 2), (7555, 2), (7556, 1), (7558, 1), (7559, 1), (7583, 2), (7584, 3), - (7585, 5), (7586, 3), (7587, 2), (7588, 5), (7589, 1), (7591, 2), (7592, 3), (7593, 4), - (7594, 1), (7595, 2), (7596, 2), (7620, 1), (7621, 3), (7623, 5), (7624, 3), (7625, 3), - (7626, 3), (7627, 4), (7628, 5), (7629, 1), (7630, 1), (7631, 1), (7632, 3), (7633, 2), - (7634, 1), (7635, 1), (7639, 1), (7648, 6), (7655, 6), (7659, 2), (7660, 2), (7662, 2), - (7663, 1), (7664, 3), (7665, 6), (7667, 1), (7670, 3), (7671, 3), (7672, 1), (7673, 2), - (7674, 1), (7675, 1), (7676, 1), (7685, 1), (7699, 2), (7700, 2), (7701, 5), (7702, 3), - (7703, 5), (7704, 3), (7705, 1), (7706, 2), (7707, 5), (7708, 4), (7709, 2), (7710, 1), - (7713, 1), (7714, 1), (7738, 2), (7739, 2), (7740, 3), (7741, 4), (7742, 3), (7743, 2), - (7744, 4), (7745, 3), (7746, 1), (7748, 2), (7750, 3), (7751, 1), (7752, 2), (7753, 1), - (7776, 2), (7777, 3), (7778, 2), (7779, 2), (7780, 3), (7781, 3), (7782, 5), (7783, 4), - (7784, 2), (7786, 4), (7787, 2), (7788, 2), (7789, 4), (7794, 1), (7812, 1), (7816, 1), - (7817, 3), (7818, 2), (7819, 3), (7820, 3), (7821, 8), (7822, 3), (7823, 3), (7824, 3), - (7825, 2), (7827, 1), (7828, 3), (7830, 2), (7831, 1), (7836, 6), (7851, 1), (7853, 1), - (7855, 1), (7857, 1), (7858, 1), (7859, 2), (7860, 3), (7861, 1), (7863, 1), (7864, 6), - (7865, 4), (7866, 4), (7867, 4), (7868, 1), (7869, 1), (7871, 1), (7894, 2), (7895, 5), - (7896, 6), (7897, 5), (7898, 1), (7899, 1), (7900, 1), (7901, 3), (7902, 1), (7903, 1), - (7904, 9), (7905, 2), (7906, 1), (7907, 2), (7909, 1), (7910, 1), (7932, 3), (7933, 9), - (7934, 1), (7935, 4), (7936, 3), (7937, 7), (7938, 2), (7939, 4), (7940, 3), (7941, 1), - (7942, 2), (7943, 4), (7944, 2), (7945, 5), (7946, 2), (7948, 1), (7949, 1), (7960, 6), - (7967, 2), (7970, 2), (7972, 2), (7973, 1), (7974, 2), (7975, 1), (7976, 3), (7977, 2), - (7978, 2), (7979, 1), (7980, 5), (7981, 1), (7982, 2), (7983, 3), (7984, 3), (7985, 1), - (7986, 4), (7987, 1), (7988, 1), (8011, 4), (8012, 5), (8013, 1), (8014, 3), (8015, 3), - (8016, 1), (8017, 5), (8018, 1), (8019, 3), (8021, 1), (8022, 6), (8023, 4), (8024, 1), - (8025, 1), (8027, 1), (8028, 2), (8029, 2), (8050, 2), (8051, 3), (8052, 1), (8053, 6), - (8054, 3), (8055, 1), (8056, 2), (8057, 4), (8058, 2), (8059, 4), (8060, 3), (8061, 3), - (8062, 2), (8063, 1), (8064, 2), (8065, 1), (8066, 1), (8067, 1), (8079, 1), (8088, 2), - (8090, 2), (8091, 5), (8092, 3), (8093, 4), (8094, 1), (8095, 3), (8096, 2), (8097, 3), - (8098, 2), (8099, 2), (8100, 2), (8101, 2), (8103, 6), (8104, 1), (8106, 1), (8108, 1), - (8128, 2), (8129, 3), (8130, 13), (8131, 4), (8132, 2), (8133, 2), (8134, 3), (8136, 2), - (8137, 2), (8139, 7), (8140, 7), (8141, 3), (8142, 1), (8143, 2), (8145, 1), (8167, 1), - (8168, 1), (8169, 5), (8171, 6), (8172, 2), (8173, 1), (8174, 2), (8175, 1), (8176, 1), - (8177, 7), (8180, 2), (8182, 1), (8206, 1), (8207, 6), (8208, 4), (8209, 5), (8210, 3), - (8211, 7), (8212, 4), (8213, 3), (8214, 4), (8215, 2), (8216, 4), (8217, 2), (8218, 4), - (8219, 3), (8220, 2), (8221, 1), (8222, 1), (8240, 6), (8244, 2), (8245, 1), (8246, 2), - (8247, 5), (8248, 6), (8249, 1), (8250, 1), (8251, 2), (8252, 5), (8253, 1), (8254, 7), - (8255, 4), (8256, 2), (8257, 3), (8258, 4), (8259, 2), (8260, 3), (8261, 1), (8282, 1), - (8284, 2), (8285, 3), (8286, 4), (8287, 5), (8288, 1), (8289, 3), (8290, 4), (8291, 3), - (8292, 2), (8294, 1), (8295, 1), (8296, 3), (8297, 3), (8298, 2), (8299, 2), (8302, 1), - (8314, 1), (8320, 1), (8321, 1), (8322, 1), (8323, 1), (8324, 2), (8325, 2), (8326, 2), - (8327, 2), (8328, 4), (8329, 2), (8330, 1), (8331, 1), (8332, 4), (8333, 3), (8334, 3), - (8335, 3), (8336, 1), (8337, 1), (8339, 2), (8340, 1), (8342, 6), (8360, 1), (8362, 1), - (8363, 5), (8364, 6), (8365, 3), (8366, 2), (8367, 6), (8368, 2), (8369, 2), (8370, 3), - (8372, 5), (8373, 2), (8374, 7), (8375, 3), (8377, 2), (8398, 1), (8400, 2), (8402, 2), - (8403, 4), (8404, 1), (8405, 2), (8406, 2), (8407, 2), (8408, 4), (8409, 3), (8410, 4), - (8411, 3), (8412, 2), (8413, 2), (8414, 5), (8415, 2), (8416, 1), (8439, 2), (8440, 1), - (8441, 3), (8442, 4), (8443, 2), (8444, 5), (8445, 2), (8446, 1), (8447, 3), (8448, 1), - (8449, 4), (8450, 3), (8451, 6), (8452, 2), (8453, 3), (8455, 3), (8456, 2), (8465, 1), - (8480, 4), (8481, 5), (8482, 7), (8483, 4), (8484, 2), (8485, 3), (8487, 1), (8488, 3), - (8489, 3), (8490, 6), (8491, 4), (8492, 5), (8495, 1), (8518, 2), (8519, 1), (8520, 3), - (8521, 1), (8522, 4), (8523, 2), (8524, 1), (8525, 1), (8526, 2), (8527, 5), (8528, 1), - (8529, 2), (8530, 5), (8531, 4), (8532, 3), (8533, 3), (8534, 1), (8536, 1), (8557, 4), - (8558, 4), (8559, 3), (8561, 3), (8562, 1), (8563, 1), (8564, 1), (8566, 1), (8567, 1), - (8568, 4), (8569, 2), (8570, 6), (8571, 4), (8572, 4), (8573, 3), (8574, 1), (8575, 1), - (8576, 6), (8583, 1), (8587, 4), (8596, 1), (8597, 3), (8598, 1), (8599, 3), (8600, 2), - (8601, 2), (8602, 2), (8603, 2), (8604, 1), (8605, 2), (8606, 2), (8607, 2), (8608, 1), - (8609, 2), (8610, 2), (8611, 2), (8612, 2), (8633, 1), (8634, 8), (8635, 3), (8636, 1), - (8637, 3), (8638, 3), (8639, 1), (8640, 2), (8641, 1), (8642, 2), (8643, 2), (8645, 4), - (8646, 2), (8647, 8), (8648, 5), (8649, 1), (8650, 3), (8653, 5), (8673, 1), (8675, 1), - (8676, 1), (8677, 5), (8678, 4), (8679, 4), (8680, 2), (8681, 3), (8682, 3), (8683, 3), - (8684, 2), (8685, 2), (8686, 2), (8687, 1), (8688, 3), (8689, 2), (8701, 6), (8705, 6), - (8710, 1), (8712, 1), (8713, 1), (8714, 1), (8716, 1), (8717, 6), (8718, 2), (8719, 2), - (8721, 1), (8723, 6), (8724, 1), (8725, 1), (8726, 2), (8727, 1), (8728, 1), (8731, 1), - (8753, 1), (8754, 3), (8755, 2), (8756, 1), (8757, 1), (8759, 6), (8760, 1), (8762, 2), - (8763, 3), (8764, 3), (8765, 2), (8768, 2), (8770, 2), (8791, 2), (8793, 1), (8794, 2), - (8795, 1), (8796, 1), (8797, 1), (8799, 1), (8800, 3), (8801, 3), (8802, 2), (8803, 4), - (8804, 6), (8805, 3), (8809, 1), (8816, 1), (8827, 1), (8829, 1), (8830, 1), (8832, 2), - (8833, 5), (8834, 3), (8835, 2), (8836, 1), (8837, 3), (8838, 2), (8839, 1), (8840, 3), - (8841, 3), (8842, 2), (8843, 2), (8845, 1), (8869, 2), (8870, 6), (8871, 1), (8872, 6), - (8875, 5), (8876, 4), (8877, 1), (8878, 5), (8879, 2), (8880, 3), (8882, 1), (8884, 3), - (8885, 1), (8886, 1), (8887, 6), (8888, 1), (8909, 1), (8910, 1), (8911, 2), (8912, 2), - (8914, 3), (8917, 5), (8918, 1), (8919, 6), (8920, 3), (8921, 4), (8922, 6), (8923, 1), - (8928, 1), (8946, 1), (8948, 1), (8949, 2), (8950, 9), (8951, 2), (8952, 2), (8953, 2), - (8954, 2), (8956, 2), (8957, 1), (8958, 3), (8959, 5), (8960, 1), (8961, 4), (8962, 2), - (8985, 1), (8987, 1), (8990, 2), (8991, 3), (8992, 2), (8993, 2), (8994, 1), (8995, 1), - (8997, 6), (8998, 3), (8999, 1), (9001, 1), (9002, 1), (9003, 1), (9004, 5), (9007, 5), - (9026, 1), (9027, 2), (9028, 3), (9029, 2), (9030, 2), (9031, 1), (9034, 1), (9035, 3), - (9036, 2), (9037, 4), (9038, 5), (9039, 2), (9064, 2), (9065, 1), (9066, 2), (9067, 4), - (9069, 3), (9070, 2), (9071, 3), (9072, 2), (9074, 2), (9075, 3), (9076, 1), (9078, 3), - (9079, 2), (9080, 1), (9087, 1), (9104, 1), (9106, 1), (9107, 2), (9108, 1), (9109, 1), - (9110, 1), (9111, 2), (9112, 1), (9113, 2), (9114, 3), (9115, 1), (9116, 2), (9117, 3), - (9120, 1), (9139, 1), (9145, 3), (9146, 1), (9147, 5), (9148, 1), (9149, 3), (9150, 3), - (9151, 3), (9152, 2), (9153, 9), (9154, 1), (9155, 2), (9156, 1), (9157, 1), (9181, 1), - (9183, 4), (9184, 7), (9185, 1), (9186, 1), (9187, 1), (9189, 2), (9190, 1), (9191, 1), - (9192, 4), (9193, 3), (9194, 1), (9195, 2), (9196, 1), (9197, 2), (9198, 1), (9204, 6), - (9219, 1), (9221, 3), (9222, 2), (9223, 3), (9224, 1), (9227, 2), (9228, 1), (9229, 2), - (9230, 3), (9232, 1), (9233, 2), (9235, 1), (9259, 1), (9260, 1), (9261, 1), (9262, 2), - (9264, 2), (9265, 1), (9268, 1), (9269, 2), (9270, 2), (9271, 1), (9272, 6), (9273, 2), - (9274, 1), (9298, 1), (9299, 2), (9301, 2), (9302, 3), (9303, 2), (9305, 1), (9306, 1), - (9307, 3), (9308, 1), (9309, 1), (9310, 3), (9311, 2), (9312, 3), (9313, 2), (9334, 3), - (9339, 1), (9340, 2), (9342, 1), (9343, 1), (9346, 2), (9347, 4), (9348, 3), (9350, 2), - (9351, 4), (9352, 2), (9353, 1), (9376, 1), (9377, 2), (9378, 2), (9379, 3), (9380, 1), - (9381, 2), (9382, 3), (9384, 3), (9386, 3), (9387, 2), (9388, 3), (9389, 8), (9390, 1), - (9391, 1), (9415, 2), (9419, 1), (9420, 3), (9421, 2), (9422, 2), (9425, 3), (9426, 6), - (9427, 3), (9428, 1), (9429, 3), (9430, 1), (9431, 1), (9455, 2), (9456, 1), (9457, 2), - (9458, 1), (9459, 1), (9460, 1), (9461, 1), (9462, 2), (9463, 3), (9464, 2), (9465, 3), - (9466, 2), (9467, 2), (9468, 4), (9474, 1), (9491, 1), (9494, 3), (9496, 1), (9497, 2), - (9498, 1), (9501, 2), (9503, 2), (9504, 3), (9505, 3), (9506, 10), (9507, 3), (9508, 4), - (9509, 2), (9510, 1), (9533, 2), (9534, 6), (9535, 1), (9536, 1), (9537, 1), (9538, 1), - (9539, 1), (9541, 1), (9542, 1), (9543, 1), (9544, 2), (9545, 3), (9546, 3), (9547, 2), - (9562, 6), (9570, 1), (9571, 1), (9572, 2), (9573, 1), (9574, 1), (9576, 4), (9577, 1), - (9581, 3), (9582, 8), (9584, 2), (9585, 1), (9586, 3), (9609, 1), (9611, 1), (9612, 5), - (9613, 1), (9614, 1), (9616, 2), (9618, 2), (9619, 1), (9621, 3), (9622, 1), (9623, 2), - (9624, 3), (9625, 4), (9626, 1), (9628, 1), (9650, 2), (9653, 2), (9656, 1), (9657, 2), - (9658, 1), (9659, 2), (9660, 1), (9661, 4), (9662, 2), (9666, 2), (9668, 1), (9689, 1), - (9690, 1), (9693, 1), (9694, 2), (9695, 1), (9696, 1), (9698, 2), (9699, 3), (9700, 1), - (9701, 4), (9703, 1), (9705, 1), (9727, 1), (9729, 1), (9731, 1), (9732, 1), (9733, 1), - (9734, 3), (9735, 1), (9736, 1), (9737, 1), (9738, 1), (9739, 1), (9740, 3), (9742, 1), - (9743, 2), (9744, 1), (9767, 1), (9769, 2), (9770, 1), (9771, 3), (9772, 3), (9773, 2), - (9776, 3), (9777, 5), (9778, 1), (9779, 3), (9780, 1), (9783, 1), (9808, 1), (9809, 1), - (9811, 2), (9814, 1), (9815, 4), (9816, 3), (9817, 2), (9818, 2), (9819, 1), (9820, 2), - (9821, 2), (9824, 1), (9840, 3), (9847, 3), (9849, 8), (9852, 1), (9853, 1), (9854, 4), - (9855, 5), (9856, 1), (9857, 3), (9858, 2), (9859, 1), (9884, 5), (9886, 2), (9888, 1), - (9889, 1), (9891, 2), (9892, 1), (9893, 1), (9895, 2), (9896, 3), (9897, 4), (9903, 1), - (9923, 2), (9924, 2), (9925, 3), (9927, 1), (9928, 2), (9929, 1), (9932, 2), (9933, 1), - (9935, 4), (9936, 2), (9937, 3), (9939, 1), (9940, 1), (9964, 4), (9966, 1), (9967, 1), - (9970, 1), (9971, 1), (9972, 1), (9973, 2), (9974, 5), (9975, 1), (9976, 2), (9977, 3), - (9996, 1), (9999, 1), (10002, 1), (10003, 2), (10004, 2), (10005, 2), (10011, 4), (10012, 2), - (10013, 2), (10015, 1), (10016, 1), (10040, 1), (10042, 1), (10043, 4), (10044, 3), (10048, 1), - (10049, 1), (10050, 1), (10051, 1), (10052, 2), (10053, 2), (10054, 2), (10081, 2), (10082, 1), - (10084, 1), (10085, 1), (10086, 1), (10087, 2), (10089, 2), (10090, 2), (10092, 2), (10093, 2), - (10094, 1), (10096, 6), (10117, 5), (10118, 3), (10119, 2), (10121, 1), (10122, 2), (10123, 5), - (10124, 3), (10125, 1), (10126, 3), (10127, 1), (10129, 4), (10130, 2), (10131, 1), (10132, 2), - (10134, 1), (10139, 6), (10155, 1), (10157, 2), (10158, 2), (10161, 2), (10163, 1), (10165, 2), - (10168, 1), (10169, 1), (10170, 2), (10171, 2), (10172, 1), (10197, 1), (10198, 1), (10202, 1), - (10205, 1), (10206, 1), (10207, 1), (10208, 2), (10210, 2), (10211, 1), (10232, 1), (10234, 1), - (10236, 1), (10237, 1), (10238, 1), (10239, 2), (10240, 1), (10242, 1), (10243, 2), (10244, 2), - (10245, 2), (10246, 4), (10247, 3), (10248, 1), (10251, 1), (10259, 1), (10278, 1), (10279, 1), - (10280, 2), (10282, 1), (10283, 1), (10285, 3), (10286, 1), (10287, 3), (10289, 1), (10312, 1), - (10313, 1), (10314, 1), (10315, 1), (10317, 3), (10319, 1), (10322, 2), (10323, 1), (10324, 1), - (10325, 2), (10326, 1), (10327, 1), (10329, 2), (10350, 1), (10353, 1), (10355, 3), (10356, 1), - (10358, 1), (10360, 1), (10362, 1), (10363, 1), (10364, 2), (10365, 1), (10366, 4), (10391, 1), - (10393, 1), (10394, 2), (10395, 3), (10400, 4), (10404, 3), (10405, 1), (10407, 1), (10416, 6), - (10430, 2), (10431, 1), (10432, 1), (10434, 3), (10435, 1), (10437, 1), (10438, 2), (10439, 2), - (10440, 2), (10441, 1), (10442, 1), (10445, 2), (10446, 2), (10469, 2), (10470, 1), (10471, 1), - (10472, 1), (10473, 2), (10474, 1), (10476, 1), (10477, 1), (10481, 1), (10482, 1), (10483, 3), - (10485, 1), (10487, 1), (10488, 1), (10510, 1), (10511, 2), (10512, 1), (10514, 1), (10515, 1), - (10518, 2), (10519, 1), (10520, 1), (10522, 2), (10548, 2), (10549, 2), (10550, 3), (10553, 1), - (10554, 1), (10555, 2), (10556, 1), (10557, 3), (10559, 1), (10563, 1), (10586, 1), (10587, 2), - (10589, 3), (10590, 2), (10591, 1), (10592, 1), (10593, 2), (10594, 2), (10597, 1), (10598, 2), - (10599, 2), (10602, 1), (10603, 1), (10604, 2), (10625, 2), (10626, 2), (10627, 3), (10629, 6), - (10630, 2), (10631, 1), (10636, 1), (10638, 1), (10639, 1), (10640, 1), (10662, 6), (10664, 2), - (10667, 1), (10672, 1), (10673, 2), (10674, 1), (10675, 1), (10679, 1), (10698, 77), - (10703, 2), (10704, 1), (10705, 1), (10707, 5), (10708, 1), (10711, 1), (10712, 1), (10714, 1), - (10716, 3), (10717, 1), (10718, 1), (10720, 1), (10742, 2), (10744, 1), (10746, 1), (10747, 1), - (10752, 1), (10753, 1), (10754, 3), (10755, 1), (10757, 1), (10788, 1), (10789, 1), (10790, 1), - (10791, 6), (10793, 2), (10794, 2), (10795, 2), (10798, 1), (10818, 1), (10821, 1), (10826, 1), - (10830, 1), (10832, 1), (10834, 1), (10835, 1), (10837, 1), (10857, 1), (10861, 2), (10862, 1), - (10864, 1), (10865, 1), (10868, 4), (10869, 1), (10870, 2), (10871, 4), (10872, 1), (10875, 1), - (10898, 3), (10899, 1), (10903, 1), (10904, 1), (10905, 1), (10907, 4), (10908, 1), (10909, 2), - (10911, 2), (10912, 1), (10913, 1), (10916, 1), (10931, 5), (10933, 1), (10937, 1), (10938, 1), - (10939, 1), (10943, 1), (10945, 1), (10946, 3), (10947, 1), (10948, 1), (10949, 3), (10952, 1), - (10977, 1), (10978, 1), (10979, 1), (10980, 1), (10981, 1), (10982, 1), (10984, 1), (10985, 2), - (10986, 1), (10987, 1), (10988, 1), (10991, 2), (10992, 1), (11014, 1), (11016, 1), (11018, 2), - (11019, 1), (11020, 4), (11022, 1), (11023, 1), (11025, 1), (11026, 1), (11028, 4), (11029, 2), - (11052, 1), (11056, 1), (11057, 1), (11062, 3), (11063, 2), (11064, 2), (11065, 1), (11067, 1), - (11069, 1), (11070, 1), (11084, 1), (11093, 1), (11103, 1), (11104, 2), (11105, 3), (11106, 2), - (11107, 1), (11132, 1), (11133, 1), (11134, 1), (11135, 3), (11136, 1), (11139, 1), (11141, 1), - (11144, 2), (11146, 1), (11147, 1), (11148, 1), (11171, 1), (11173, 1), (11174, 1), (11176, 1), - (11180, 1), (11183, 1), (11186, 1), (11210, 1), (11212, 1), (11219, 1), (11220, 2), (11222, 3), - (11223, 2), (11224, 1), (11225, 1), (11226, 1), (11231, 1), (11249, 1), (11250, 1), (11253, 1), - (11254, 5), (11257, 1), (11258, 3), (11259, 3), (11261, 1), (11264, 2), (11287, 1), (11289, 1), - (11290, 2), (11291, 1), (11293, 1), (11296, 1), (11300, 1), (11301, 1), (11302, 1), (11326, 1), - (11328, 5), (11329, 1), (11335, 1), (11336, 2), (11337, 1), (11338, 1), (11339, 1), (11340, 1), - (11366, 3), (11368, 1), (11369, 2), (11370, 1), (11374, 2), (11375, 1), (11378, 2), (11379, 1), - (11404, 2), (11407, 1), (11409, 2), (11410, 2), (11411, 1), (11414, 1), (11415, 3), (11417, 1), - (11422, 1), (11443, 1), (11446, 1), (11450, 1), (11454, 1), (11455, 2), (11481, 6), (11485, 1), - (11487, 1), (11488, 1), (11492, 1), (11493, 1), (11494, 1), (11495, 1), (11498, 3), (11499, 1), - (11521, 1), (11522, 1), (11524, 2), (11525, 2), (11526, 1), (11528, 1), (11532, 1), (11564, 1), - (11565, 2), (11572, 1), (11576, 1), (11577, 1), (11599, 1), (11601, 1), (11602, 2), (11603, 1), - (11607, 1), (11609, 1), (11614, 1), (11616, 1), (11631, 1), (11640, 2), (11641, 1), (11642, 1), - (11643, 4), (11651, 3), (11653, 2), (11654, 1), (11655, 1), (11679, 2), (11682, 5), (11686, 1), - (11687, 1), (11689, 1), (11690, 3), (11691, 1), (11693, 1), (11717, 2), (11719, 3), (11720, 4), - (11721, 6), (11726, 1), (11727, 1), (11728, 1), (11750, 6), (11755, 3), (11756, 2), (11757, 2), - (11759, 1), (11762, 1), (11763, 1), (11764, 1), (11765, 3), (11766, 1), (11768, 1), (11769, 1), - (11770, 2), (11796, 2), (11797, 2), (11798, 1), (11801, 1), (11804, 1), (11806, 1), (11807, 3), - (11808, 1), (11810, 1), (11811, 1), (11813, 1), (11837, 2), (11841, 2), (11843, 2), (11844, 1), - (11845, 1), (11846, 1), (11871, 1), (11876, 2), (11877, 1), (11878, 1), (11880, 1), (11881, 2), - (11882, 4), (11883, 5), (11884, 3), (11885, 1), (11888, 1), (11912, 2), (11913, 1), (11923, 1), - (11926, 1), (11927, 1), (11928, 1), (11951, 1), (11953, 2), (11955, 1), (11956, 2), (11959, 2), - (11961, 1), (11962, 1), (11964, 1), (11966, 2), (11990, 1), (11992, 3), (12003, 2), (12028, 1), - (12031, 1), (12033, 1), (12035, 1), (12037, 1), (12038, 1), (12039, 2), (12040, 1), (12041, 1), - (12043, 2), (12072, 4), (12077, 2), (12078, 3), (12079, 2), (12080, 1), (12108, 2), (12109, 2), - (12112, 1), (12114, 1), (12115, 2), (12116, 1), (12117, 2), (12118, 1), (12123, 2), (12145, 1), - (12146, 1), (12147, 3), (12148, 1), (12151, 1), (12156, 1), (12158, 2), (12183, 1), (12190, 1), - (12192, 1), (12194, 2), (12195, 1), (12196, 2), (12197, 3), (12198, 3), (12201, 1), (12224, 1), - (12225, 1), (12226, 1), (12230, 1), (12231, 1), (12234, 1), (12236, 1), (12237, 3), (12263, 1), - (12265, 1), (12266, 1), (12267, 1), (12269, 1), (12272, 1), (12273, 2), (12274, 2), (12276, 2), - (12277, 1), (12279, 1), (12280, 1), (12300, 1), (12303, 1), (12305, 1), (12307, 2), (12309, 1), - (12310, 2), (12311, 1), (12315, 2), (12321, 1), (12341, 1), (12344, 2), (12350, 2), (12351, 1), - (12352, 1), (12353, 1), (12383, 1), (12389, 2), (12390, 1), (12391, 1), (12392, 4), (12395, 1), - (12421, 3), (12423, 1), (12428, 1), (12429, 1), (12430, 1), (12457, 1), (12461, 1), (12463, 1), - (12468, 1), (12471, 1), (12473, 1), (12498, 5), (12499, 2), (12502, 1), (12503, 1), (12505, 1), - (12506, 1), (12508, 2), (12509, 1), (12510, 1), (12511, 1), (12513, 1), (12535, 1), (12536, 1), - (12537, 1), (12538, 1), (12539, 1), (12540, 1), (12542, 1), (12545, 1), (12547, 2), (12548, 1), - (12550, 1), (12577, 1), (12581, 1), (12583, 1), (12585, 1), (12586, 3), (12618, 1), (12624, 1), - (12626, 1), (12655, 1), (12657, 3), (12658, 1), (12663, 1), (12664, 3), (12665, 2), (12667, 1), - (12682, 1), (12693, 1), (12697, 1), (12699, 1), (12701, 1), (12702, 1), (12705, 2), (12706, 1), - (12730, 1), (12732, 2), (12733, 2), (12737, 1), (12739, 1), (12740, 1), (12742, 3), (12771, 1), - (12773, 1), (12780, 1), (12781, 3), (12782, 1), (12809, 1), (12811, 1), (12812, 1), (12819, 1), - (12821, 1), (12822, 1), (12824, 1), (12826, 1), (12848, 1), (12851, 2), (12853, 1), (12860, 3), - (12861, 1), (12862, 1), (12863, 1), (12889, 1), (12890, 1), (12896, 1), (12899, 1), (12928, 1), - (12929, 2), (12930, 1), (12936, 1), (12937, 3), (12938, 1), (12941, 1), (12964, 1), (12969, 1), - (12971, 1), (12973, 1), (12976, 1), (12977, 2), (13005, 1), (13006, 1), (13008, 1), (13010, 1), - (13013, 2), (13015, 2), (13018, 1), (13046, 1), (13047, 1), (13053, 2), (13055, 2), (13081, 1), - (13083, 1), (13085, 4), (13086, 1), (13091, 2), (13092, 2), (13094, 2), (13095, 1), (13096, 1), - (13097, 1), (13123, 2), (13127, 1), (13130, 1), (13131, 1), (13132, 1), (13134, 1), (13136, 1), - (13159, 1), (13161, 2), (13162, 1), (13167, 2), (13168, 1), (13172, 1), (13174, 1), (13175, 1), - (13176, 1), (13206, 1), (13207, 1), (13209, 2), (13212, 1), (13213, 2), (13239, 2), (13242, 1), - (13247, 1), (13249, 2), (13252, 1), (13279, 1), (13280, 2), (13282, 5), (13284, 1), (13286, 1), - (13288, 1), (13289, 1), (13290, 1), (13291, 1), (13317, 1), (13318, 1), (13319, 1), (13320, 1), - (13325, 1), (13326, 1), (13328, 2), (13330, 2), (13354, 2), (13356, 6), (13360, 2), (13362, 1), - (13363, 2), (13364, 3), (13367, 2), (13368, 3), (13370, 1), (13393, 1), (13397, 2), (13406, 1), - (13408, 1), (13435, 1), (13436, 1), (13438, 1), (13440, 2), (13442, 1), (13443, 1), (13444, 1), - (13445, 1), (13449, 1), (13473, 2), (13474, 1), (13475, 1), (13479, 2), (13481, 2), (13482, 1), - (13484, 1), (13485, 1), (13491, 1), (13511, 1), (13520, 1), (13521, 2), (13522, 1), (13527, 1), - (13550, 1), (13551, 1), (13552, 3), (13555, 1), (13557, 1), (13559, 2), (13562, 2), (13564, 1), - (13590, 1), (13592, 1), (13596, 1), (13600, 2), (13602, 1), (13603, 1), (13630, 1), (13633, 1), - (13634, 1), (13637, 1), (13640, 1), (13643, 1), (13668, 1), (13669, 2), (13670, 2), (13674, 1), - (13676, 1), (13677, 1), (13678, 4), (13679, 1), (13680, 1), (13713, 1), (13714, 1), (13716, 6), - (13717, 2), (13745, 1), (13752, 2), (13753, 1), (13754, 1), (13755, 1), (13757, 1), (13758, 1), - (13791, 1), (13795, 1), (13796, 2), (13823, 2), (13831, 1), (13834, 1), (13836, 1), (13837, 1), - (13862, 1), (13863, 1), (13864, 1), (13867, 1), (13875, 1), (13876, 1), (13877, 1), (13878, 1), - (13906, 1), (13910, 2), (13911, 1), (13912, 2), (13914, 2), (13942, 1), (13947, 2), (13948, 2), - (13950, 3), (13951, 1), (13952, 1), (13953, 1), (13954, 1), (13980, 1), (13985, 1), (13987, 1), - (13988, 1), (13989, 1), (14016, 1), (14018, 7), (14020, 2), (14021, 1), (14022, 1), (14023, 1), - (14024, 1), (14026, 1), (14027, 1), (14030, 1), (14061, 1), (14063, 6), (14064, 1), (14068, 1), - (14074, 1), (14098, 1), (14099, 2), (14102, 5), (14104, 2), (14108, 1), (14136, 1), (14140, 1), - (14143, 1), (14145, 1), (14146, 1), (14148, 1), (14174, 2), (14176, 1), (14177, 1), (14186, 1), - (14188, 1), (14189, 1), (14190, 1), (14213, 1), (14216, 1), (14225, 1), (14226, 1), (14253, 1), - (14257, 1), (14258, 1), (14261, 2), (14264, 1), (14265, 1), (14266, 1), (14292, 1), (14293, 1), - (14294, 1), (14303, 1), (14328, 1), (14336, 1), (14337, 1), (14340, 1), (14341, 1), (14342, 1), - (14370, 1), (14371, 1), (14373, 5), (14375, 1), (14378, 1), (14382, 2), (14409, 1), (14410, 1), - (14412, 1), (14417, 1), (14420, 4), (14421, 1), (14424, 1), (14448, 5), (14449, 2), (14455, 1), - (14459, 1), (14460, 1), (14491, 1), (14492, 1), (14494, 1), (14495, 1), (14500, 1), (14522, 1), - (14530, 2), (14532, 3), (14534, 1), (14537, 2), (14563, 1), (14565, 1), (14567, 1), (14575, 1), - (14576, 1), (14578, 2), (14606, 2), (14607, 2), (14608, 1), (14610, 1), (14611, 1), (14614, 1), - (14618, 2), (14645, 2), (14648, 1), (14651, 1), (14652, 1), (14653, 1), (14655, 1), (14685, 1), - (14687, 1), (14688, 1), (14689, 1), (14691, 4), (14692, 1), (14694, 1), (14695, 1), (14720, 1), - (14722, 1), (14723, 1), (14724, 1), (14725, 1), (14727, 1), (14728, 1), (14730, 2), (14731, 1), - (14732, 2), (14735, 2), (14757, 1), (14763, 1), (14765, 1), (14767, 1), (14769, 2), (14797, 1), - (14798, 1), (14801, 1), (14806, 2), (14810, 2), (14811, 1), (14813, 2), (14842, 1), (14847, 2), - (14849, 2), (14875, 1), (14881, 1), (14884, 1), (14885, 2), (14886, 2), (14889, 2), (14917, 1), - (14919, 1), (14921, 2), (14923, 1), (14924, 1), (14926, 1), (14927, 1), (14928, 1), (14956, 2), - (14957, 1), (14958, 1), (14961, 1), (14963, 3), (14968, 1), (15003, 2), (15007, 1), (15034, 1), - (15041, 2), (15043, 1), (15044, 1), (15045, 1), (15076, 1), (15080, 1), (15081, 1), (15082, 1), - (15083, 1), (15085, 1), (15112, 1), (15114, 1), (15117, 1), (15118, 1), (15120, 2), (15123, 1), - (15124, 1), (15155, 1), (15156, 1), (15165, 1), (15186, 1), (15196, 1), (15197, 1), (15199, 1), - (15200, 1), (15231, 1), (15232, 2), (15233, 1), (15235, 3), (15237, 2), (15238, 1), (15266, 1), - (15270, 1), (15275, 2), (15276, 1), (15280, 1), (15309, 1), (15314, 1), (15345, 1), (15352, 1), - (15353, 2), (15355, 2), (15356, 1), (15384, 1), (15385, 1), (15386, 1), (15388, 1), (15396, 1), - (15421, 1), (15422, 1), (15425, 1), (15434, 1), (15435, 1), (15436, 1), (15461, 1), (15462, 1), - (15463, 1), (15469, 1), (15474, 1), (15475, 1), (15500, 1), (15504, 1), (15505, 1), (15507, 1), - (15508, 1), (15509, 1), (15512, 1), (15513, 1), (15539, 1), (15542, 1), (15544, 1), (15548, 2), - (15550, 1), (15551, 1), (15580, 1), (15586, 1), (15587, 1), (15589, 1), (15590, 1), (15618, 1), - (15620, 1), (15624, 1), (15626, 1), (15659, 2), (15662, 1), (15665, 1), (15667, 1), (15668, 1), - (15695, 1), (15697, 1), (15698, 1), (15701, 1), (15702, 1), (15704, 1), (15709, 2), (15740, 1), - (15741, 1), (15742, 1), (15743, 1), (15746, 1), (15778, 1), (15779, 1), (15782, 1), (15784, 1), - (15786, 1), (15825, 1), (15849, 1), (15853, 1), (15857, 1), (15860, 1), (15864, 1), (15891, 1), - (15893, 2), (15895, 1), (15896, 1), (15898, 1), (15900, 1), (15932, 1), (15937, 1), (15938, 1), - (15967, 1), (15973, 1), (15977, 1), (15980, 1), (16007, 1), (16010, 1), (16012, 1), (16014, 1), - (16016, 1), (16018, 1), (16019, 1), (16053, 1), (16058, 1), (16086, 1), (16091, 1), (16093, 1), - (16098, 1), (16137, 1), (16162, 1), (16163, 1), (16167, 1), (16168, 2), (16171, 1), (16172, 2), - (16202, 1), (16206, 1), (16210, 2), (16212, 1), (16213, 1), (16215, 1), (16245, 1), (16249, 1), - (16280, 1), (16283, 1), (16284, 1), (16288, 1), (16319, 1), (16322, 2), (16326, 1), (16327, 3), - (16329, 1), (16331, 1), (16370, 1), (16403, 1), (16404, 1), (16406, 1), (16409, 1), (16410, 1), - (16411, 1), (16434, 1), (16440, 1), (16441, 1), (16443, 2), (16444, 1), (16445, 1), (16460, 1), - (16475, 1), (16479, 1), (16482, 1), (16483, 2), (16488, 1), (16521, 2), (16523, 2), (16524, 1), - (16525, 2), (16551, 1), (16552, 1), (16553, 2), (16558, 1), (16563, 1), (16565, 1), (16567, 1), - (16593, 1), (16595, 1), (16596, 1), (16600, 1), (16639, 2), (16644, 1), (16673, 2), (16674, 1), - (16678, 1), (16712, 1), (16714, 1), (16717, 1), (16718, 1), (16750, 1), (16751, 1), (16753, 1), - (16756, 1), (16792, 1), (16796, 1), (16798, 2), (16827, 1), (16875, 1), (16906, 1), (16909, 1), - (16910, 1), (16911, 2), (16941, 1), (16943, 1), (16948, 1), (16949, 1), (16954, 1), (16957, 1), - (16985, 1), (16993, 1), (17022, 2), (17024, 1), (17028, 1), (17032, 1), (17066, 2), (17103, 1), - (17104, 2), (17106, 1), (17109, 1), (17139, 1), (17143, 1), (17179, 1), (17183, 2), (17187, 1), - (17189, 1), (17217, 1), (17223, 2), (17255, 1), (17262, 1), (17265, 1), (17278, 1), (17298, 1), - (17302, 2), (17334, 1), (17338, 1), (17371, 2), (17378, 1), (17381, 1), (17415, 1), (17416, 1), - (17457, 1), (17458, 1), (17490, 1), (17499, 1), (17536, 1), (17539, 1), (17568, 1), (17571, 1), - (17572, 1), (17616, 1), (17617, 1), (17619, 1), (17682, 5), (17687, 1), (17729, 1), (17731, 1), - (17763, 1), (17769, 1), (17803, 1), (17806, 1), (17812, 1), (17841, 1), (17887, 1), (17889, 1), - (17920, 1), (17922, 1), (17925, 1), (17961, 1), (17965, 1), (17967, 1), (18004, 1), (18030, 1), - (18040, 2), (18042, 1), (18043, 1), (18044, 1), (18045, 1), (18078, 1), (18157, 1), (18167, 1), - (18236, 1), (18239, 1), (18270, 1), (18314, 1), (18355, 1), (18394, 1), (18396, 1), (18436, 1), - (18465, 1), (18469, 1), (18505, 1), (18542, 2), (18547, 1), (18550, 1), (18584, 1), (18587, 1), - (18588, 1), (18667, 1), (18668, 1), (18702, 1), (18741, 1), (18742, 1), (18783, 1), (18784, 1), - (18818, 1), (18855, 1), (18900, 1), (18904, 1), (18939, 1), (18943, 1), (18977, 1), (19013, 1), - (19019, 1), (19021, 1), (19048, 1), (19053, 1), (19056, 1), (19133, 2), (19172, 1), (19176, 2), - (19201, 5), (19211, 1), (19248, 1), (19249, 1), (19280, 1), (19288, 1), (19295, 1), (19325, 1), - (19327, 1), (19328, 2), (19330, 2), (19337, 6), (19365, 1), (19406, 1), (19407, 1), (19450, 1), - (19487, 1), (19526, 1), (19561, 2), (19564, 1), (19600, 1), (19605, 1), (19640, 1), (19680, 1), - (19720, 1), (19758, 1), (19800, 1), (19952, 2), (19954, 1), (19955, 1), (19956, 1), (19988, 1), - (19989, 26), (19990, 21), (19991, 30), (19992, 21), (19993, 13), (19994, 12), (19995, 9), - (19996, 6), (20000, 1), (20010, 1), (20030, 1), (20031, 1), (20066, 1), (20069, 1), (20070, 1), - (20073, 1), (20109, 1), (20111, 1), (20132, 1), (20150, 1), (20186, 1), (20266, 1), (20267, 1), - (20268, 1), (20302, 1), (20303, 1), (20423, 1), (20424, 1), (20540, 1), (20577, 1), (20616, 1), - (20654, 1), (20655, 2), (20693, 1), (20696, 1), (20732, 2), (20773, 2), (20883, 1), (20888, 1), - (20892, 1), (20925, 1), (20928, 1), (21045, 1), (21047, 1), (21083, 2), (21126, 1), (21165, 1), - (21201, 1), (21202, 1), (21276, 1), (21315, 1), (21357, 1), (21399, 2), (21439, 1), (21476, 1), - (21510, 1), (21513, 1), (21550, 1), (21551, 1), (21593, 1), (21633, 1), (21665, 1), (21666, 1), - (21669, 1), (21751, 1), (21826, 1), (21921, 1), (21939, 1), (21943, 1), (21977, 1), (21980, 2), - (21981, 1), (22017, 1), (22018, 1), (22133, 1), (22134, 1), (22135, 2), (22172, 1), (22211, 1), - (22212, 1), (22213, 1), (22251, 1), (22254, 1), (22256, 1), (22290, 1), (22371, 1), (22406, 1), - (22408, 1), (22410, 1), (22451, 1), (22485, 1), (22486, 2), (22525, 1), (22526, 1), (22562, 1), - (22563, 3), (22564, 1), (22607, 1), (22644, 1), (22680, 1), (22758, 1), (22759, 1), (22798, 2), - (22837, 2), (22838, 1), (22875, 1), (22877, 1), (22914, 1), (22916, 1), (22918, 1), (22993, 1), - (23031, 1), (23033, 2), (23070, 1), (23109, 1), (23111, 1), (23148, 1), (23151, 1), (23188, 1), - (23189, 1), (23226, 1), (23227, 1), (23304, 1), (23305, 1), (23381, 5), (23384, 2), (23388, 1), - (23424, 1), (23462, 1), (23498, 1), (23542, 1), (23579, 1), (23580, 1), (23654, 1), (23657, 1), - (23820, 1), (24019, 7), (24047, 1), (24204, 1), (24390, 1), (27166, 6), (31645, 5), (37476, 6), - (50442, 1), (66530, 1), (236741, 1), (266960, 1), (410116, 1), (452279, 1), (521150, 1), - (531415, 1), (531469, 1), (533889, 1), (534391, 1), (537072, 1), (537491, 1), (546820, 1), - (554056, 1), (562513, 1), (570304, 1), (571882, 1), (580008, 1), (582755, 1), (586561, 1), - (589436, 1), (593061, 2), (618859, 1), (619082, 1), (625907, 1), (633533, 1), (644603, 1), - (646180, 1), (655481, 1), (693987, 1), (701633, 1), (728784, 1), (745886, 1), (752140, 1), - (771376, 1), (848764, 1), (902834, 1), (952321, 1), (964030, 1), (974008, 1), (977740, 1), - (992978, 1), (1019553, 1), (1057259, 1), (1094674, 1), (1105518, 1), (1116659, 1), - (1121314, 1), (1135487, 1), (1151345, 1), (1173415, 1), (1189567, 1), (1238079, 1), - (1282021, 1), (1290980, 1), (1293007, 1), (1318405, 1), (1328926, 1), (1338999, 1), - (1373382, 1), (1402596, 1), (1422519, 1), (1446480, 1), (1460046, 1), (1475924, 1), - (1478227, 1), (1482046, 1), (1597051, 1), -]; \ No newline at end of file + (1, 66581), + (2, 95), + (3, 1), + (4, 283269), + (5, 1308), + (6, 169), + (7, 3), + (8, 73), + (9, 10), + (10, 2), + (11, 205), + (12, 5), + (13, 4), + (14, 4), + (15, 7), + (16, 559), + (17, 418), + (18, 3), + (19, 4), + (20, 609), + (21, 57), + (22, 1), + (23, 1), + (24, 6), + (25, 5), + (26, 69428), + (27, 1), + (28, 6), + (29, 8), + (30, 9), + (31, 12), + (32, 85052), + (33, 3212), + (34, 116), + (35, 220), + (36, 454), + (37, 10344), + (38, 9378), + (39, 31), + (40, 23), + (41, 27), + (42, 17), + (43, 18), + (44, 20), + (45, 19), + (46, 74), + (47, 7), + (48, 175), + (49, 3835), + (50, 1851), + (51, 890), + (52, 29), + (53, 85), + (54, 2992), + (55, 15), + (56, 98), + (57, 688), + (58, 34), + (59, 22), + (60, 21), + (61, 12), + (62, 14), + (63, 9), + (64, 21), + (65, 187), + (66, 176), + (67, 16), + (68, 12), + (69, 38), + (70, 2318), + (71, 20), + (72, 19), + (73, 94), + (74, 25), + (75, 12), + (76, 1778), + (77, 50), + (78, 22), + (79, 21), + (80, 1098004), + (81, 44), + (82, 295), + (83, 132), + (84, 17), + (85, 96), + (86, 27), + (87, 12), + (88, 150), + (89, 360), + (90, 517), + (91, 85), + (92, 22), + (93, 7), + (94, 22), + (95, 79), + (96, 86), + (97, 88), + (98, 388), + (99, 14), + (100, 44), + (101, 36), + (102, 2957), + (103, 11), + (104, 22), + (105, 24), + (106, 14), + (107, 8), + (108, 24), + (109, 81), + (110, 13), + (111, 11), + (112, 18), + (113, 23), + (114, 45194), + (115, 503), + (116, 18), + (117, 11), + (118, 13), + (119, 10), + (120, 167), + (121, 38), + (122, 43), + (123, 67), + (124, 17), + (125, 10), + (126, 23), + (127, 17), + (128, 191), + (129, 241), + (130, 139), + (131, 6), + (132, 24), + (133, 15), + (134, 1944), + (135, 14), + (136, 16), + (137, 13), + (138, 5), + (139, 5), + (140, 11), + (141, 13), + (142, 66), + (143, 4), + (144, 12), + (145, 58), + (146, 16), + (147, 2), + (148, 20), + (149, 2), + (150, 1), + (151, 2), + (152, 128), + (153, 29), + (154, 2), + (155, 1), + (156, 5), + (157, 1), + (158, 4), + (159, 3), + (160, 7), + (161, 41), + (162, 9), + (163, 2), + (164, 41), + (165, 29), + (166, 1891), + (167, 60), + (168, 70), + (169, 52), + (170, 63), + (171, 2), + (172, 6), + (173, 28), + (174, 8), + (176, 3), + (177, 5), + (178, 7), + (179, 1), + (180, 2), + (181, 52), + (182, 2), + (184, 2), + (185, 2), + (186, 30), + (188, 28), + (189, 2), + (190, 4), + (192, 1918), + (193, 27), + (194, 2), + (195, 2), + (196, 2), + (197, 9), + (198, 1454), + (199, 23), + (200, 1), + (201, 4), + (202, 26), + (203, 1), + (205, 8), + (206, 66), + (207, 44), + (208, 139), + (209, 42), + (210, 44), + (211, 6), + (212, 22), + (213, 6), + (214, 5), + (216, 6), + (217, 29), + (218, 2), + (219, 1), + (220, 3), + (221, 2), + (222, 2), + (223, 2), + (225, 14), + (226, 1), + (228, 4), + (229, 1), + (230, 1178), + (232, 1), + (233, 3), + (234, 3), + (237, 2), + (238, 3), + (239, 4), + (241, 1), + (242, 6), + (243, 1), + (244, 8), + (245, 28), + (246, 38), + (247, 41), + (248, 17), + (249, 32), + (250, 81), + (251, 18), + (252, 24), + (253, 36), + (254, 1), + (255, 3), + (257, 13), + (258, 5), + (259, 1), + (260, 1), + (261, 2), + (262, 1306), + (264, 16), + (265, 3), + (266, 10), + (268, 7), + (269, 8), + (270, 21), + (272, 10), + (273, 11), + (274, 30), + (276, 7), + (277, 3), + (278, 10), + (279, 7), + (280, 10), + (281, 7), + (282, 4), + (283, 9), + (284, 56), + (285, 39), + (286, 35), + (287, 22), + (288, 32), + (289, 55), + (290, 41), + (291, 2), + (292, 2), + (293, 5), + (294, 992), + (295, 8), + (296, 10), + (297, 1), + (298, 6), + (300, 1), + (301, 2), + (303, 7), + (305, 5), + (306, 2), + (307, 5), + (308, 1), + (309, 1), + (311, 3), + (313, 3), + (315, 3), + (317, 1), + (318, 12), + (319, 1), + (321, 22), + (322, 3), + (323, 33), + (324, 39), + (325, 29), + (326, 1337), + (327, 29), + (328, 20), + (329, 32), + (330, 17), + (331, 12), + (332, 1), + (333, 4), + (334, 4), + (335, 9), + (336, 2), + (337, 5), + (338, 1), + (339, 7), + (340, 13), + (341, 1), + (342, 3), + (343, 6), + (344, 8), + (345, 2), + (347, 8), + (349, 2), + (350, 3), + (351, 5), + (352, 1), + (353, 13), + (354, 2), + (355, 12), + (357, 3), + (358, 1063), + (359, 9), + (360, 6), + (361, 9), + (362, 22), + (363, 62), + (364, 17), + (365, 26), + (366, 21), + (367, 25), + (368, 25), + (369, 30), + (370, 7), + (371, 21), + (373, 18), + (374, 4), + (375, 90), + (377, 27), + (378, 8), + (379, 125), + (380, 2), + (381, 34), + (382, 51), + (383, 18996), + (384, 52), + (385, 33308), + (386, 7601), + (387, 949), + (388, 3922), + (389, 72), + (390, 1089), + (391, 287), + (392, 175), + (393, 571), + (394, 352), + (395, 35), + (396, 92), + (397, 29), + (398, 5), + (399, 9), + (400, 14), + (401, 44), + (402, 50), + (403, 54), + (404, 26), + (405, 19), + (406, 12), + (407, 15), + (408, 9), + (409, 25), + (410, 7), + (412, 5), + (413, 2), + (415, 1), + (417, 12), + (418, 1), + (419, 2), + (422, 1086), + (424, 1), + (425, 4), + (426, 1), + (427, 2), + (428, 2), + (429, 2), + (431, 2), + (433, 3), + (436, 7), + (440, 8), + (441, 48), + (442, 38), + (443, 25), + (444, 11), + (445, 9), + (446, 14), + (447, 16), + (448, 5), + (449, 18), + (450, 15), + (452, 2), + (454, 1085), + (455, 5), + (456, 1), + (460, 1), + (461, 1), + (465, 1), + (469, 2), + (471, 1), + (472, 6), + (477, 1), + (478, 2), + (479, 5), + (480, 18), + (481, 90), + (482, 31), + (483, 9), + (484, 7), + (485, 12), + (486, 1796), + (487, 7), + (488, 7), + (489, 8), + (490, 5), + (491, 3), + (492, 1), + (493, 2), + (494, 2), + (495, 1), + (497, 1), + (501, 1), + (513, 7), + (516, 10), + (518, 14326), + (519, 21), + (520, 35), + (521, 20), + (522, 3), + (523, 10), + (524, 17), + (525, 8), + (526, 11), + (527, 6), + (528, 4), + (529, 3), + (530, 2), + (533, 1), + (534, 2), + (538, 3), + (543, 1), + (545, 7), + (549, 1), + (557, 1), + (558, 13), + (559, 17), + (560, 13), + (561, 7), + (562, 18), + (563, 14), + (564, 9), + (565, 9), + (566, 7), + (567, 8), + (568, 2), + (569, 5), + (570, 2), + (572, 2), + (573, 2), + (577, 1), + (582, 4), + (596, 11), + (597, 4), + (598, 7), + (599, 4), + (600, 8), + (601, 20), + (602, 20), + (603, 6), + (604, 12), + (605, 14), + (606, 4), + (607, 1), + (608, 3), + (609, 2), + (610, 5), + (612, 1), + (613, 1), + (614, 1), + (617, 1), + (624, 1), + (626, 1), + (630, 1), + (635, 15), + (636, 6), + (637, 8), + (638, 11), + (639, 2), + (640, 15), + (641, 25), + (642, 15), + (643, 17), + (644, 10), + (645, 2), + (646, 2), + (647, 16), + (648, 5), + (649, 2), + (650, 2), + (653, 1), + (670, 4), + (673, 6), + (674, 15), + (676, 9), + (677, 6), + (678, 2), + (679, 15), + (680, 17), + (681, 18), + (682, 15), + (683, 7), + (685, 1), + (686, 1), + (687, 1), + (688, 1), + (689, 1), + (690, 1), + (691, 2), + (693, 1), + (709, 1), + (713, 13), + (714, 7), + (715, 7), + (716, 2), + (717, 3), + (718, 6), + (719, 17), + (720, 14), + (721, 8), + (722, 3), + (723, 4), + (724, 4), + (725, 1), + (726, 3), + (727, 1), + (728, 1), + (729, 1), + (730, 2), + (731, 1), + (736, 3), + (737, 1), + (752, 19), + (753, 5), + (754, 9), + (755, 6), + (756, 2), + (757, 3), + (758, 16), + (759, 9), + (760, 12), + (761, 11), + (763, 1), + (764, 3), + (765, 5), + (766, 1), + (768, 1), + (769, 2), + (770, 4), + (772, 1), + (780, 3), + (785, 1), + (789, 6), + (791, 15), + (792, 6), + (793, 16), + (794, 1), + (795, 2), + (796, 5), + (797, 12), + (798, 15), + (799, 18), + (800, 6), + (801, 1), + (802, 8), + (803, 1), + (808, 3), + (809, 1), + (810, 2), + (814, 1), + (824, 1), + (830, 13), + (831, 7), + (832, 8), + (833, 8), + (834, 7), + (835, 3), + (836, 13), + (837, 8), + (838, 9), + (839, 4), + (841, 3), + (842, 2), + (843, 4), + (844, 1), + (846, 2), + (847, 5), + (849, 2), + (853, 1), + (854, 1), + (855, 1), + (868, 2), + (869, 13), + (870, 6), + (871, 10), + (872, 2), + (873, 2), + (874, 2), + (875, 10), + (876, 15), + (877, 14), + (878, 5), + (879, 4), + (880, 2), + (881, 3), + (882, 5), + (883, 2), + (884, 2), + (886, 1), + (888, 1), + (889, 2), + (890, 2), + (891, 2), + (908, 3), + (909, 5), + (910, 10), + (911, 5), + (912, 6), + (914, 3), + (915, 3), + (916, 8), + (917, 2), + (918, 6), + (919, 1), + (920, 7), + (921, 5), + (922, 2), + (923, 3), + (926, 2), + (927, 2), + (929, 2), + (930, 5), + (931, 2), + (932, 5), + (933, 2), + (934, 3), + (947, 3), + (948, 6), + (949, 7), + (950, 2), + (951, 5), + (952, 1), + (953, 3), + (954, 7), + (955, 10), + (956, 6), + (957, 3), + (958, 6), + (959, 10), + (960, 3), + (961, 4), + (962, 1), + (966, 1), + (967, 1), + (968, 3), + (969, 10), + (970, 9), + (971, 3), + (972, 3), + (977, 1), + (978, 3), + (986, 2), + (987, 5), + (988, 16), + (989, 3), + (990, 3), + (991, 1), + (992, 7), + (993, 7), + (994, 11), + (995, 4), + (996, 10), + (997, 6), + (998, 4), + (999, 2), + (1000, 1), + (1001, 1), + (1002, 2), + (1005, 1), + (1008, 7), + (1009, 7), + (1010, 9), + (1011, 6), + (1012, 1), + (1013, 1), + (1014, 2), + (1022, 3), + (1025, 1), + (1026, 10), + (1027, 10), + (1028, 6), + (1029, 2), + (1030, 6), + (1031, 6), + (1032, 13), + (1033, 10), + (1034, 3), + (1035, 6), + (1036, 7), + (1037, 4), + (1038, 1), + (1040, 1), + (1041, 1), + (1044, 7), + (1046, 5), + (1047, 11), + (1048, 4), + (1050, 1), + (1052, 2), + (1065, 10), + (1066, 9), + (1067, 4), + (1068, 3), + (1069, 4), + (1070, 1), + (1071, 4), + (1072, 11), + (1073, 4), + (1074, 4), + (1075, 1), + (1076, 2), + (1077, 1), + (1078, 2), + (1079, 5), + (1085, 1), + (1086, 7), + (1087, 4), + (1088, 3), + (1089, 2), + (1104, 4), + (1105, 9), + (1106, 5), + (1107, 2), + (1108, 4), + (1109, 4), + (1110, 14), + (1111, 12), + (1112, 8), + (1113, 2), + (1114, 3), + (1115, 1), + (1116, 1), + (1117, 4), + (1118, 3), + (1124, 1), + (1125, 4), + (1126, 10), + (1127, 3), + (1141, 6), + (1143, 6), + (1144, 12), + (1145, 5), + (1146, 3), + (1147, 4), + (1148, 4), + (1149, 6), + (1150, 7), + (1151, 7), + (1152, 1), + (1153, 2), + (1154, 1), + (1155, 2), + (1156, 2), + (1164, 2), + (1165, 8), + (1166, 6), + (1167, 3), + (1168, 2), + (1171, 1), + (1176, 1), + (1181, 1), + (1182, 3), + (1183, 11), + (1184, 3), + (1185, 4), + (1186, 4), + (1187, 3), + (1188, 7), + (1189, 6), + (1190, 5), + (1191, 1), + (1193, 1), + (1196, 1), + (1198, 3), + (1202, 1), + (1203, 4), + (1204, 3), + (1205, 9), + (1206, 7), + (1207, 3), + (1208, 1), + (1210, 1), + (1220, 4), + (1221, 3), + (1222, 5), + (1223, 4), + (1224, 1), + (1225, 2), + (1226, 5), + (1227, 14), + (1228, 6), + (1229, 4), + (1230, 4), + (1231, 3), + (1232, 3), + (1234, 1), + (1242, 5), + (1243, 1), + (1244, 5), + (1245, 6), + (1246, 2), + (1247, 3), + (1248, 1), + (1249, 1), + (1259, 4), + (1260, 1), + (1261, 1), + (1262, 6), + (1263, 5), + (1264, 4), + (1265, 3), + (1266, 3), + (1267, 9), + (1268, 2), + (1269, 7), + (1270, 2), + (1281, 2), + (1283, 3), + (1284, 3), + (1286, 3), + (1287, 1), + (1288, 1), + (1296, 6), + (1298, 1), + (1299, 1), + (1300, 7), + (1301, 3), + (1302, 3), + (1303, 1), + (1304, 8), + (1305, 10), + (1306, 11), + (1307, 4), + (1308, 3), + (1311, 1), + (1320, 4), + (1321, 1), + (1322, 1), + (1323, 2), + (1324, 1), + (1325, 1), + (1327, 1), + (1330, 2), + (1338, 2), + (1339, 2), + (1341, 4), + (1342, 2), + (1343, 3), + (1344, 17), + (1345, 16), + (1346, 7), + (1347, 2), + (1348, 1), + (1350, 1), + (1352, 3), + (1359, 3), + (1360, 1), + (1362, 2), + (1365, 1), + (1366, 1), + (1374, 2), + (1375, 1), + (1376, 1), + (1377, 1), + (1378, 2), + (1380, 1), + (1381, 2), + (1382, 3), + (1383, 9), + (1384, 7), + (1385, 13), + (1386, 5), + (1388, 1), + (1389, 1), + (1394, 1), + (1396, 2), + (1400, 2), + (1415, 2), + (1416, 1), + (1417, 1), + (1418, 4), + (1419, 6), + (1420, 5), + (1421, 2), + (1422, 3), + (1423, 8), + (1424, 10), + (1425, 5), + (1426, 1), + (1428, 1), + (1443, 1), + (1445, 2), + (1454, 1), + (1455, 3), + (1456, 1), + (1457, 2), + (1458, 4), + (1459, 4), + (1460, 10), + (1461, 8), + (1462, 11), + (1463, 5), + (1464, 5), + (1465, 1), + (1480, 1), + (1483, 1), + (1485, 1), + (1494, 2), + (1495, 1), + (1496, 7), + (1497, 7), + (1498, 5), + (1499, 4), + (1500, 5), + (1501, 12), + (1502, 10), + (1503, 3), + (1504, 2), + (1505, 2), + (1507, 3), + (1520, 1), + (1529, 3), + (1532, 2), + (1533, 23), + (1535, 14), + (1536, 8), + (1537, 2), + (1538, 3), + (1539, 10), + (1540, 11), + (1541, 13), + (1542, 4), + (1543, 2), + (1546, 1), + (1548, 1), + (1551, 2), + (1571, 2), + (1572, 6), + (1573, 4), + (1574, 4), + (1575, 2), + (1576, 7), + (1577, 5), + (1578, 8), + (1579, 12), + (1580, 4), + (1581, 5), + (1582, 1), + (1586, 1), + (1595, 1), + (1609, 2), + (1610, 2), + (1611, 3), + (1612, 3), + (1613, 5), + (1614, 6), + (1615, 1), + (1616, 8), + (1617, 11), + (1618, 12), + (1619, 11), + (1620, 5), + (1621, 1), + (1622, 1), + (1649, 2), + (1650, 2), + (1651, 8), + (1652, 2), + (1653, 5), + (1654, 5), + (1655, 2), + (1656, 13), + (1657, 20), + (1658, 10), + (1659, 8), + (1660, 4), + (1661, 2), + (1663, 1), + (1688, 2), + (1689, 2), + (1690, 1), + (1691, 5), + (1692, 3), + (1693, 5), + (1694, 8), + (1695, 13), + (1696, 12), + (1697, 5), + (1698, 1), + (1699, 2), + (1700, 1), + (1701, 1), + (1702, 1), + (1703, 1), + (1705, 1), + (1727, 3), + (1728, 3), + (1729, 2), + (1730, 3), + (1731, 4), + (1732, 5), + (1733, 3), + (1734, 7), + (1735, 15), + (1736, 15), + (1737, 7), + (1738, 6), + (1739, 1), + (1741, 1), + (1742, 1), + (1763, 6), + (1766, 8), + (1767, 2), + (1768, 1), + (1769, 4), + (1770, 5), + (1771, 1), + (1772, 5), + (1773, 13), + (1774, 10), + (1775, 9), + (1776, 9), + (1777, 4), + (1778, 2), + (1779, 2), + (1804, 1), + (1805, 2), + (1807, 2), + (1808, 2), + (1809, 3), + (1810, 3), + (1811, 6), + (1812, 12), + (1813, 13), + (1814, 9), + (1815, 3), + (1816, 2), + (1817, 4), + (1821, 2), + (1844, 2), + (1845, 1), + (1846, 2), + (1847, 8), + (1848, 6), + (1849, 5), + (1850, 7), + (1851, 4), + (1852, 3), + (1853, 9), + (1854, 5), + (1855, 6), + (1856, 3), + (1858, 1), + (1860, 1), + (1882, 1), + (1883, 2), + (1884, 1), + (1885, 4), + (1886, 1), + (1887, 2), + (1888, 3), + (1889, 2), + (1890, 8), + (1891, 6), + (1892, 14), + (1893, 3), + (1894, 1), + (1895, 1), + (1896, 1), + (1898, 1), + (1922, 6), + (1923, 1), + (1924, 3), + (1925, 5), + (1926, 4), + (1927, 6), + (1928, 7), + (1929, 7), + (1930, 13), + (1931, 11), + (1932, 8), + (1933, 3), + (1934, 1), + (1936, 2), + (1937, 2), + (1938, 1), + (1939, 2), + (1961, 3), + (1963, 3), + (1964, 2), + (1965, 5), + (1966, 7), + (1967, 4), + (1968, 5), + (1969, 9), + (1970, 11), + (1971, 7), + (1972, 5), + (1973, 3), + (1974, 2), + (1977, 1), + (1997, 2), + (2000, 2), + (2001, 1), + (2002, 4), + (2003, 4), + (2004, 7), + (2005, 3), + (2006, 9), + (2007, 13), + (2008, 22), + (2009, 8), + (2010, 10), + (2011, 5), + (2012, 2), + (2014, 1), + (2016, 1), + (2021, 1), + (2039, 3), + (2041, 5), + (2042, 5), + (2043, 8), + (2044, 6), + (2045, 2), + (2046, 12), + (2047, 10), + (2048, 9), + (2049, 4), + (2050, 4), + (2051, 2), + (2054, 3), + (2062, 1), + (2070, 5), + (2077, 1), + (2078, 4), + (2079, 4), + (2080, 2), + (2081, 4), + (2082, 5), + (2083, 7), + (2084, 4), + (2085, 13), + (2086, 4), + (2087, 7), + (2088, 6), + (2089, 8), + (2090, 1), + (2091, 1), + (2092, 4), + (2113, 6), + (2117, 6), + (2118, 2), + (2120, 3), + (2121, 5), + (2122, 9), + (2123, 8), + (2124, 8), + (2125, 9), + (2126, 6), + (2127, 7), + (2128, 7), + (2130, 2), + (2133, 1), + (2156, 4), + (2157, 1), + (2158, 3), + (2159, 1), + (2160, 6), + (2161, 3), + (2162, 7), + (2163, 10), + (2164, 9), + (2165, 9), + (2166, 8), + (2167, 5), + (2170, 3), + (2171, 1), + (2193, 1), + (2194, 1), + (2195, 2), + (2196, 2), + (2197, 2), + (2198, 4), + (2199, 5), + (2200, 9), + (2201, 5), + (2202, 13), + (2203, 17), + (2204, 13), + (2205, 11), + (2206, 1), + (2207, 2), + (2209, 1), + (2210, 2), + (2234, 7), + (2235, 1), + (2236, 2), + (2238, 6), + (2239, 9), + (2240, 7), + (2241, 13), + (2242, 12), + (2243, 9), + (2244, 6), + (2245, 4), + (2246, 2), + (2247, 3), + (2273, 2), + (2274, 4), + (2275, 2), + (2277, 4), + (2278, 9), + (2279, 7), + (2280, 8), + (2281, 7), + (2282, 4), + (2283, 3), + (2284, 2), + (2285, 2), + (2286, 1), + (2290, 1), + (2311, 2), + (2312, 3), + (2313, 1), + (2314, 4), + (2315, 3), + (2316, 3), + (2317, 10), + (2318, 11), + (2319, 12), + (2320, 11), + (2321, 17), + (2322, 9), + (2323, 3), + (2325, 3), + (2326, 4), + (2341, 1), + (2351, 12), + (2352, 3), + (2353, 4), + (2354, 5), + (2355, 7), + (2356, 7), + (2357, 5), + (2358, 8), + (2359, 7), + (2360, 10), + (2361, 7), + (2362, 4), + (2363, 2), + (2364, 2), + (2365, 5), + (2367, 1), + (2369, 1), + (2390, 1), + (2391, 1), + (2392, 5), + (2394, 4), + (2395, 6), + (2396, 7), + (2397, 8), + (2398, 7), + (2399, 5), + (2400, 10), + (2401, 3), + (2402, 1), + (2403, 1), + (2408, 5), + (2412, 1), + (2428, 1), + (2429, 12), + (2430, 2), + (2431, 4), + (2433, 2), + (2434, 9), + (2435, 8), + (2436, 10), + (2437, 11), + (2438, 13), + (2439, 11), + (2440, 3), + (2441, 1), + (2442, 1), + (2443, 2), + (2445, 1), + (2464, 2), + (2468, 1), + (2469, 2), + (2470, 6), + (2471, 3), + (2472, 3), + (2473, 5), + (2474, 7), + (2475, 6), + (2476, 13), + (2477, 16), + (2478, 10), + (2479, 10), + (2480, 1), + (2482, 1), + (2483, 1), + (2484, 2), + (2509, 1), + (2510, 2), + (2511, 8), + (2512, 6), + (2513, 7), + (2514, 12), + (2515, 10), + (2516, 10), + (2517, 9), + (2518, 9), + (2519, 4), + (2520, 2), + (2521, 3), + (2522, 3), + (2546, 2), + (2547, 1), + (2548, 1), + (2549, 2), + (2550, 7), + (2551, 2), + (2552, 5), + (2553, 6), + (2554, 13), + (2555, 14), + (2556, 8), + (2557, 5), + (2558, 2), + (2559, 1), + (2561, 1), + (2589, 5), + (2590, 6), + (2591, 3), + (2592, 8), + (2593, 10), + (2594, 14), + (2595, 3), + (2596, 7), + (2597, 8), + (2598, 2), + (2599, 2), + (2600, 2), + (2604, 1), + (2625, 1), + (2628, 2), + (2629, 5), + (2630, 2), + (2631, 4), + (2632, 9), + (2633, 8), + (2634, 14), + (2635, 3), + (2636, 6), + (2637, 2), + (2638, 1), + (2639, 2), + (2641, 1), + (2642, 1), + (2643, 1), + (2664, 4), + (2665, 6), + (2666, 7), + (2667, 3), + (2668, 3), + (2669, 5), + (2670, 9), + (2671, 11), + (2672, 12), + (2673, 15), + (2674, 3), + (2675, 6), + (2676, 1), + (2677, 2), + (2678, 2), + (2679, 1), + (2682, 1), + (2683, 2), + (2703, 3), + (2704, 3), + (2705, 2), + (2706, 4), + (2707, 4), + (2708, 4), + (2709, 4), + (2710, 8), + (2711, 8), + (2712, 11), + (2713, 6), + (2714, 7), + (2715, 2), + (2716, 2), + (2717, 1), + (2718, 2), + (2731, 2), + (2742, 1), + (2743, 2), + (2745, 2), + (2746, 8), + (2747, 3), + (2748, 5), + (2749, 8), + (2750, 8), + (2751, 6), + (2752, 4), + (2753, 5), + (2755, 1), + (2756, 1), + (2757, 4), + (2758, 1), + (2760, 5), + (2775, 1), + (2778, 1), + (2781, 2), + (2782, 2), + (2783, 1), + (2784, 3), + (2785, 3), + (2786, 2), + (2787, 11), + (2788, 7), + (2789, 8), + (2790, 9), + (2791, 4), + (2792, 4), + (2793, 3), + (2795, 3), + (2796, 4), + (2797, 1), + (2798, 1), + (2799, 1), + (2820, 2), + (2822, 1), + (2823, 2), + (2825, 4), + (2826, 4), + (2827, 6), + (2828, 4), + (2829, 8), + (2830, 5), + (2831, 3), + (2832, 2), + (2835, 3), + (2836, 3), + (2837, 1), + (2859, 3), + (2861, 5), + (2862, 3), + (2863, 7), + (2864, 3), + (2865, 6), + (2866, 5), + (2867, 11), + (2868, 9), + (2869, 5), + (2870, 6), + (2871, 1), + (2873, 2), + (2877, 1), + (2898, 6), + (2900, 1), + (2901, 2), + (2902, 7), + (2903, 4), + (2904, 2), + (2905, 7), + (2906, 7), + (2907, 9), + (2908, 4), + (2909, 3), + (2910, 2), + (2911, 2), + (2912, 2), + (2913, 1), + (2916, 1), + (2937, 2), + (2938, 1), + (2940, 4), + (2941, 4), + (2942, 4), + (2943, 4), + (2944, 16), + (2945, 11), + (2946, 3), + (2947, 11), + (2948, 3), + (2949, 2), + (2950, 2), + (2951, 1), + (2954, 1), + (2962, 6), + (2976, 1), + (2977, 1), + (2978, 2), + (2979, 2), + (2980, 3), + (2981, 3), + (2982, 2), + (2983, 2), + (2984, 5), + (2985, 11), + (2986, 6), + (2987, 2), + (2988, 1), + (2989, 2), + (2992, 1), + (3015, 2), + (3016, 4), + (3017, 4), + (3018, 2), + (3019, 3), + (3020, 3), + (3021, 6), + (3022, 11), + (3023, 10), + (3024, 2), + (3025, 5), + (3026, 1), + (3027, 3), + (3029, 2), + (3035, 1), + (3054, 4), + (3057, 2), + (3058, 3), + (3059, 5), + (3060, 3), + (3061, 8), + (3062, 5), + (3063, 4), + (3064, 6), + (3065, 2), + (3066, 1), + (3086, 1), + (3092, 2), + (3093, 4), + (3094, 1), + (3095, 4), + (3096, 1), + (3097, 2), + (3098, 3), + (3099, 3), + (3100, 5), + (3101, 6), + (3102, 7), + (3103, 2), + (3104, 3), + (3105, 4), + (3110, 1), + (3124, 6), + (3132, 4), + (3134, 3), + (3135, 1), + (3136, 5), + (3137, 3), + (3138, 5), + (3139, 8), + (3140, 7), + (3141, 6), + (3142, 9), + (3143, 1), + (3144, 2), + (3145, 1), + (3147, 1), + (3148, 2), + (3171, 2), + (3172, 1), + (3173, 2), + (3174, 3), + (3175, 4), + (3176, 4), + (3177, 4), + (3178, 5), + (3179, 2), + (3180, 8), + (3181, 4), + (3182, 2), + (3183, 3), + (3184, 1), + (3189, 1), + (3194, 4), + (3210, 2), + (3212, 2), + (3213, 3), + (3214, 7), + (3215, 7), + (3216, 4), + (3217, 4), + (3218, 8), + (3219, 5), + (3220, 4), + (3221, 1), + (3223, 1), + (3249, 2), + (3250, 2), + (3251, 1), + (3252, 2), + (3253, 4), + (3254, 5), + (3255, 4), + (3256, 6), + (3257, 4), + (3258, 8), + (3259, 4), + (3260, 3), + (3261, 2), + (3262, 1), + (3288, 3), + (3290, 3), + (3291, 2), + (3292, 4), + (3293, 2), + (3294, 4), + (3295, 5), + (3296, 11), + (3297, 10), + (3298, 2), + (3299, 4), + (3300, 1), + (3301, 2), + (3303, 1), + (3306, 1), + (3327, 1), + (3329, 2), + (3330, 6), + (3331, 5), + (3332, 2), + (3333, 1), + (3334, 5), + (3335, 6), + (3336, 5), + (3337, 5), + (3338, 2), + (3340, 1), + (3342, 1), + (3366, 13), + (3368, 4), + (3369, 2), + (3370, 5), + (3371, 5), + (3372, 4), + (3373, 3), + (3374, 7), + (3375, 5), + (3376, 2), + (3377, 1), + (3378, 1), + (3380, 1), + (3382, 1), + (3389, 6), + (3394, 1), + (3405, 6), + (3406, 1), + (3407, 2), + (3408, 3), + (3409, 5), + (3410, 2), + (3411, 3), + (3412, 4), + (3413, 5), + (3414, 6), + (3415, 5), + (3417, 2), + (3418, 1), + (3421, 1), + (3423, 1), + (3424, 1), + (3444, 3), + (3445, 1), + (3447, 3), + (3448, 1), + (3449, 2), + (3450, 4), + (3451, 5), + (3452, 6), + (3453, 8), + (3454, 6), + (3455, 2), + (3456, 4), + (3477, 1), + (3483, 1), + (3484, 4), + (3485, 5), + (3486, 2), + (3487, 3), + (3488, 3), + (3489, 6), + (3490, 8), + (3491, 6), + (3492, 8), + (3493, 5), + (3494, 2), + (3499, 1), + (3512, 4), + (3522, 1), + (3523, 2), + (3524, 3), + (3525, 3), + (3526, 6), + (3527, 5), + (3528, 3), + (3529, 10), + (3530, 10), + (3531, 7), + (3532, 4), + (3533, 3), + (3534, 1), + (3535, 2), + (3561, 1), + (3562, 2), + (3563, 3), + (3564, 3), + (3565, 2), + (3566, 6), + (3567, 2), + (3568, 2), + (3569, 14), + (3570, 7), + (3571, 2), + (3572, 2), + (3573, 1), + (3574, 2), + (3575, 1), + (3576, 1), + (3600, 4), + (3601, 3), + (3602, 5), + (3603, 3), + (3604, 4), + (3605, 4), + (3606, 7), + (3607, 8), + (3608, 5), + (3609, 3), + (3610, 3), + (3639, 3), + (3640, 1), + (3641, 1), + (3642, 5), + (3643, 2), + (3644, 6), + (3645, 4), + (3646, 4), + (3647, 3), + (3648, 2), + (3649, 1), + (3650, 2), + (3651, 1), + (3678, 1), + (3680, 4), + (3681, 2), + (3682, 7), + (3683, 2), + (3684, 6), + (3685, 4), + (3686, 4), + (3687, 4), + (3688, 3), + (3690, 2), + (3691, 2), + (3692, 1), + (3694, 1), + (3717, 1), + (3718, 1), + (3719, 3), + (3720, 5), + (3721, 5), + (3722, 8), + (3723, 3), + (3724, 2), + (3725, 2), + (3726, 2), + (3727, 4), + (3728, 1), + (3731, 1), + (3732, 2), + (3733, 1), + (3756, 4), + (3758, 13), + (3759, 2), + (3760, 7), + (3761, 3), + (3762, 4), + (3763, 2), + (3764, 6), + (3765, 1), + (3766, 2), + (3769, 1), + (3795, 1), + (3797, 3), + (3798, 4), + (3799, 9), + (3800, 3), + (3801, 6), + (3802, 5), + (3803, 2), + (3804, 5), + (3805, 2), + (3807, 1), + (3808, 1), + (3834, 1), + (3835, 1), + (3836, 4), + (3837, 1), + (3838, 4), + (3839, 5), + (3840, 4), + (3841, 7), + (3842, 8), + (3843, 5), + (3844, 1), + (3845, 3), + (3846, 2), + (3847, 1), + (3874, 4), + (3875, 3), + (3876, 7), + (3877, 7), + (3878, 3), + (3879, 3), + (3880, 2), + (3881, 5), + (3882, 3), + (3883, 4), + (3884, 1), + (3885, 1), + (3886, 1), + (3913, 1), + (3914, 3), + (3915, 4), + (3916, 4), + (3917, 6), + (3920, 2), + (3921, 5), + (3922, 4), + (3923, 1), + (3925, 1), + (3928, 1), + (3929, 1), + (3951, 1), + (3952, 1), + (3953, 3), + (3954, 2), + (3955, 1), + (3956, 8), + (3957, 4), + (3958, 5), + (3959, 3), + (3960, 5), + (3961, 3), + (3962, 1), + (3963, 2), + (3964, 1), + (3991, 3), + (3992, 4), + (3993, 2), + (3994, 5), + (3995, 3), + (3996, 6), + (3997, 8), + (3998, 4), + (3999, 4), + (4000, 1), + (4001, 3), + (4002, 1), + (4003, 1), + (4031, 2), + (4032, 4), + (4033, 7), + (4034, 4), + (4035, 3), + (4036, 3), + (4037, 1), + (4038, 3), + (4039, 5), + (4040, 4), + (4041, 1), + (4069, 1), + (4070, 3), + (4071, 4), + (4072, 1), + (4073, 2), + (4074, 4), + (4075, 1), + (4076, 2), + (4077, 5), + (4078, 4), + (4079, 2), + (4083, 1), + (4107, 1), + (4108, 2), + (4109, 2), + (4110, 3), + (4111, 4), + (4112, 4), + (4113, 6), + (4114, 1), + (4115, 5), + (4116, 1), + (4117, 3), + (4119, 1), + (4120, 1), + (4147, 2), + (4148, 4), + (4150, 3), + (4151, 3), + (4152, 2), + (4153, 5), + (4154, 4), + (4155, 4), + (4156, 3), + (4157, 3), + (4158, 2), + (4161, 1), + (4185, 2), + (4187, 2), + (4188, 7), + (4189, 5), + (4190, 2), + (4191, 1), + (4192, 5), + (4193, 2), + (4194, 3), + (4195, 2), + (4196, 2), + (4197, 2), + (4198, 2), + (4224, 2), + (4225, 2), + (4226, 1), + (4227, 2), + (4228, 4), + (4229, 4), + (4230, 3), + (4231, 3), + (4232, 3), + (4233, 3), + (4234, 3), + (4236, 1), + (4259, 2), + (4263, 4), + (4264, 1), + (4265, 2), + (4266, 4), + (4267, 3), + (4268, 1), + (4269, 5), + (4270, 5), + (4271, 4), + (4272, 3), + (4273, 3), + (4274, 2), + (4277, 1), + (4280, 5), + (4300, 2), + (4302, 3), + (4303, 2), + (4304, 4), + (4305, 6), + (4306, 2), + (4307, 3), + (4308, 2), + (4309, 4), + (4310, 7), + (4311, 2), + (4312, 4), + (4313, 4), + (4314, 1), + (4342, 1), + (4343, 3), + (4344, 7), + (4345, 7), + (4346, 2), + (4347, 2), + (4348, 6), + (4349, 3), + (4350, 3), + (4351, 3), + (4352, 2), + (4353, 2), + (4354, 1), + (4356, 2), + (4380, 4), + (4383, 8), + (4385, 3), + (4386, 8), + (4387, 3), + (4388, 5), + (4389, 1), + (4390, 1), + (4391, 2), + (4392, 2), + (4393, 2), + (4419, 4), + (4420, 2), + (4421, 3), + (4422, 5), + (4423, 7), + (4424, 3), + (4425, 5), + (4426, 5), + (4427, 3), + (4428, 4), + (4429, 1), + (4430, 3), + (4431, 1), + (4432, 7), + (4434, 1), + (4458, 5), + (4460, 3), + (4461, 2), + (4462, 6), + (4463, 3), + (4464, 3), + (4465, 3), + (4466, 10), + (4467, 3), + (4468, 2), + (4469, 2), + (4470, 1), + (4473, 1), + (4498, 2), + (4500, 3), + (4501, 8), + (4502, 3), + (4503, 1), + (4504, 6), + (4505, 3), + (4506, 3), + (4507, 1), + (4508, 2), + (4509, 2), + (4510, 2), + (4511, 2), + (4536, 1), + (4538, 3), + (4539, 5), + (4540, 3), + (4541, 6), + (4542, 2), + (4543, 4), + (4544, 3), + (4545, 3), + (4546, 1), + (4547, 1), + (4550, 1), + (4575, 3), + (4576, 1), + (4577, 5), + (4578, 3), + (4579, 8), + (4580, 3), + (4581, 4), + (4582, 4), + (4583, 4), + (4584, 5), + (4587, 3), + (4588, 2), + (4614, 1), + (4616, 1), + (4617, 4), + (4618, 4), + (4619, 1), + (4620, 3), + (4621, 3), + (4622, 2), + (4623, 4), + (4624, 3), + (4627, 2), + (4628, 2), + (4653, 2), + (4655, 3), + (4656, 3), + (4657, 4), + (4658, 3), + (4659, 4), + (4660, 3), + (4661, 2), + (4662, 7), + (4663, 7), + (4664, 1), + (4665, 2), + (4666, 1), + (4693, 1), + (4694, 2), + (4695, 2), + (4696, 5), + (4699, 1), + (4700, 4), + (4701, 3), + (4702, 2), + (4703, 1), + (4704, 1), + (4731, 3), + (4733, 2), + (4734, 6), + (4735, 1), + (4736, 2), + (4737, 3), + (4738, 3), + (4739, 3), + (4740, 4), + (4741, 2), + (4742, 3), + (4743, 2), + (4744, 2), + (4770, 1), + (4771, 3), + (4772, 2), + (4773, 4), + (4774, 5), + (4775, 3), + (4776, 5), + (4777, 8), + (4778, 1), + (4779, 2), + (4780, 3), + (4781, 1), + (4782, 1), + (4785, 2), + (4809, 2), + (4811, 2), + (4812, 6), + (4813, 4), + (4814, 1), + (4815, 2), + (4816, 2), + (4817, 1), + (4818, 5), + (4819, 2), + (4820, 1), + (4821, 2), + (4834, 1), + (4848, 1), + (4850, 3), + (4851, 2), + (4852, 4), + (4853, 1), + (4854, 1), + (4855, 3), + (4856, 8), + (4857, 2), + (4858, 2), + (4859, 2), + (4860, 2), + (4862, 2), + (4887, 2), + (4888, 1), + (4890, 3), + (4891, 4), + (4893, 3), + (4894, 2), + (4895, 4), + (4896, 6), + (4897, 3), + (4899, 1), + (4900, 1), + (4926, 2), + (4927, 1), + (4928, 4), + (4929, 2), + (4930, 2), + (4931, 2), + (4932, 4), + (4933, 7), + (4934, 1), + (4935, 3), + (4937, 1), + (4938, 2), + (4939, 1), + (4942, 1), + (4964, 1), + (4965, 1), + (4966, 1), + (4968, 1), + (4969, 5), + (4970, 5), + (4971, 3), + (4972, 1), + (4973, 7), + (4974, 1), + (4975, 2), + (4977, 1), + (4978, 1), + (4979, 2), + (5004, 3), + (5005, 2), + (5006, 1), + (5007, 1), + (5008, 2), + (5009, 3), + (5010, 1), + (5011, 4), + (5012, 4), + (5013, 1), + (5014, 2), + (5015, 5), + (5016, 1), + (5018, 2), + (5019, 1), + (5043, 2), + (5046, 6), + (5047, 1), + (5048, 1), + (5049, 1), + (5050, 1), + (5051, 1), + (5052, 5), + (5053, 4), + (5054, 2), + (5055, 1), + (5056, 1), + (5082, 1), + (5083, 1), + (5084, 4), + (5085, 4), + (5086, 5), + (5087, 2), + (5089, 1), + (5090, 3), + (5091, 6), + (5092, 1), + (5093, 1), + (5094, 4), + (5096, 1), + (5098, 2), + (5121, 2), + (5123, 3), + (5124, 4), + (5125, 1), + (5126, 3), + (5127, 1), + (5128, 5), + (5130, 2), + (5131, 1), + (5132, 1), + (5133, 2), + (5134, 2), + (5135, 1), + (5136, 2), + (5137, 1), + (5160, 1), + (5162, 4), + (5163, 1), + (5164, 3), + (5166, 1), + (5167, 2), + (5168, 8), + (5169, 4), + (5170, 1), + (5173, 1), + (5198, 1), + (5201, 2), + (5202, 4), + (5204, 1), + (5205, 1), + (5206, 1), + (5207, 3), + (5208, 1), + (5209, 5), + (5210, 3), + (5211, 1), + (5213, 2), + (5215, 1), + (5238, 1), + (5239, 6), + (5241, 1), + (5242, 2), + (5243, 2), + (5244, 2), + (5245, 2), + (5246, 4), + (5247, 5), + (5248, 3), + (5250, 2), + (5252, 2), + (5280, 3), + (5281, 1), + (5283, 4), + (5284, 2), + (5285, 2), + (5286, 1), + (5288, 3), + (5289, 1), + (5290, 1), + (5291, 1), + (5317, 1), + (5318, 2), + (5319, 2), + (5321, 3), + (5322, 2), + (5323, 6), + (5324, 1), + (5325, 1), + (5326, 2), + (5327, 3), + (5328, 2), + (5329, 2), + (5330, 1), + (5331, 1), + (5356, 1), + (5357, 3), + (5358, 4), + (5360, 1), + (5361, 1), + (5362, 2), + (5363, 1), + (5364, 1), + (5366, 2), + (5367, 1), + (5369, 1), + (5395, 2), + (5396, 2), + (5397, 2), + (5398, 2), + (5400, 2), + (5401, 2), + (5402, 4), + (5403, 3), + (5404, 1), + (5405, 3), + (5406, 1), + (5408, 1), + (5434, 1), + (5435, 2), + (5436, 2), + (5437, 1), + (5438, 4), + (5439, 3), + (5440, 3), + (5441, 5), + (5442, 1), + (5443, 1), + (5445, 3), + (5474, 4), + (5475, 1), + (5476, 3), + (5477, 1), + (5478, 2), + (5479, 2), + (5480, 4), + (5481, 5), + (5482, 2), + (5485, 2), + (5486, 1), + (5512, 1), + (5513, 2), + (5514, 4), + (5515, 4), + (5517, 2), + (5518, 2), + (5519, 2), + (5520, 4), + (5521, 2), + (5523, 1), + (5524, 3), + (5525, 9), + (5526, 1), + (5542, 3), + (5551, 1), + (5552, 1), + (5553, 1), + (5554, 4), + (5555, 4), + (5556, 1), + (5557, 5), + (5558, 3), + (5559, 1), + (5560, 2), + (5563, 1), + (5564, 1), + (5565, 2), + (5566, 1), + (5590, 1), + (5591, 3), + (5592, 5), + (5593, 4), + (5594, 1), + (5595, 1), + (5596, 1), + (5597, 3), + (5598, 3), + (5599, 3), + (5601, 2), + (5602, 2), + (5603, 1), + (5604, 2), + (5620, 6), + (5628, 1), + (5629, 1), + (5630, 1), + (5631, 1), + (5632, 1), + (5633, 3), + (5634, 2), + (5635, 2), + (5636, 2), + (5637, 2), + (5638, 4), + (5639, 3), + (5640, 1), + (5641, 1), + (5642, 1), + (5643, 2), + (5668, 1), + (5669, 1), + (5670, 2), + (5671, 3), + (5672, 2), + (5673, 2), + (5675, 1), + (5676, 2), + (5677, 2), + (5678, 1), + (5680, 2), + (5706, 1), + (5707, 1), + (5709, 2), + (5710, 2), + (5712, 4), + (5713, 1), + (5714, 3), + (5715, 4), + (5718, 1), + (5719, 3), + (5721, 1), + (5745, 5), + (5746, 2), + (5747, 2), + (5748, 2), + (5749, 2), + (5750, 3), + (5751, 3), + (5753, 2), + (5754, 1), + (5755, 2), + (5756, 3), + (5757, 1), + (5759, 1), + (5785, 2), + (5786, 2), + (5787, 4), + (5788, 2), + (5789, 6), + (5790, 5), + (5791, 3), + (5792, 3), + (5793, 2), + (5794, 1), + (5795, 1), + (5797, 2), + (5798, 2), + (5799, 1), + (5801, 1), + (5825, 3), + (5826, 1), + (5827, 3), + (5828, 3), + (5829, 5), + (5831, 3), + (5832, 5), + (5833, 2), + (5834, 1), + (5835, 2), + (5839, 2), + (5862, 1), + (5863, 1), + (5865, 3), + (5868, 1), + (5869, 3), + (5870, 2), + (5871, 4), + (5872, 2), + (5874, 2), + (5875, 3), + (5876, 3), + (5901, 1), + (5903, 2), + (5904, 1), + (5905, 1), + (5906, 1), + (5907, 3), + (5908, 3), + (5909, 1), + (5910, 2), + (5911, 2), + (5912, 2), + (5914, 1), + (5915, 3), + (5917, 1), + (5941, 1), + (5942, 2), + (5943, 2), + (5944, 2), + (5945, 2), + (5946, 2), + (5947, 4), + (5948, 1), + (5949, 1), + (5950, 2), + (5951, 2), + (5952, 2), + (5953, 2), + (5955, 2), + (5957, 2), + (5980, 1), + (5981, 2), + (5982, 4), + (5984, 3), + (5985, 2), + (5986, 2), + (5987, 3), + (5989, 4), + (5991, 2), + (5993, 2), + (5994, 2), + (5995, 2), + (5996, 1), + (6019, 1), + (6021, 2), + (6022, 1), + (6023, 1), + (6024, 5), + (6025, 2), + (6026, 1), + (6027, 3), + (6028, 6), + (6030, 1), + (6031, 1), + (6032, 1), + (6034, 1), + (6059, 4), + (6060, 2), + (6061, 3), + (6062, 1), + (6063, 1), + (6065, 4), + (6066, 2), + (6067, 2), + (6068, 1), + (6069, 2), + (6070, 3), + (6071, 2), + (6073, 1), + (6074, 2), + (6098, 1), + (6099, 1), + (6100, 1), + (6101, 1), + (6102, 3), + (6103, 1), + (6104, 2), + (6105, 6), + (6106, 3), + (6107, 1), + (6108, 2), + (6111, 2), + (6112, 1), + (6114, 1), + (6130, 1), + (6135, 1), + (6137, 1), + (6138, 2), + (6139, 1), + (6141, 4), + (6142, 1), + (6143, 2), + (6144, 1), + (6146, 1), + (6148, 2), + (6150, 2), + (6151, 1), + (6177, 3), + (6178, 2), + (6179, 2), + (6180, 2), + (6181, 2), + (6182, 1), + (6185, 1), + (6186, 2), + (6187, 1), + (6188, 2), + (6189, 2), + (6190, 2), + (6215, 2), + (6216, 3), + (6217, 3), + (6218, 1), + (6219, 3), + (6220, 3), + (6221, 6), + (6222, 2), + (6223, 3), + (6224, 3), + (6225, 1), + (6226, 2), + (6227, 1), + (6228, 1), + (6254, 1), + (6255, 1), + (6256, 1), + (6257, 1), + (6258, 1), + (6259, 3), + (6260, 3), + (6261, 2), + (6262, 2), + (6264, 2), + (6266, 1), + (6292, 1), + (6293, 1), + (6294, 1), + (6295, 1), + (6296, 3), + (6298, 3), + (6299, 5), + (6300, 2), + (6301, 2), + (6302, 2), + (6303, 3), + (6304, 1), + (6305, 2), + (6306, 2), + (6307, 1), + (6308, 2), + (6324, 1), + (6330, 1), + (6331, 2), + (6332, 2), + (6333, 4), + (6334, 2), + (6335, 1), + (6337, 3), + (6338, 1), + (6339, 1), + (6341, 2), + (6342, 2), + (6343, 1), + (6344, 2), + (6345, 1), + (6347, 1), + (6372, 1), + (6374, 4), + (6375, 2), + (6376, 2), + (6378, 3), + (6379, 5), + (6382, 1), + (6383, 3), + (6384, 1), + (6386, 1), + (6402, 8), + (6408, 1), + (6410, 2), + (6413, 1), + (6414, 2), + (6415, 1), + (6416, 2), + (6417, 3), + (6418, 3), + (6419, 3), + (6420, 1), + (6421, 1), + (6423, 2), + (6426, 1), + (6430, 1), + (6447, 1), + (6448, 2), + (6451, 2), + (6452, 3), + (6453, 2), + (6454, 1), + (6455, 4), + (6456, 3), + (6457, 3), + (6459, 3), + (6461, 2), + (6462, 2), + (6463, 1), + (6486, 2), + (6490, 1), + (6492, 3), + (6493, 1), + (6494, 5), + (6495, 3), + (6496, 2), + (6497, 2), + (6498, 4), + (6499, 2), + (6500, 1), + (6501, 3), + (6502, 1), + (6503, 3), + (6504, 1), + (6505, 1), + (6527, 1), + (6528, 2), + (6530, 2), + (6531, 4), + (6533, 2), + (6535, 1), + (6536, 2), + (6537, 1), + (6538, 2), + (6541, 1), + (6564, 1), + (6565, 1), + (6566, 1), + (6567, 1), + (6569, 3), + (6570, 4), + (6571, 2), + (6572, 2), + (6573, 4), + (6574, 5), + (6575, 1), + (6576, 1), + (6577, 2), + (6578, 2), + (6579, 2), + (6580, 1), + (6581, 1), + (6582, 1), + (6603, 2), + (6604, 2), + (6605, 1), + (6606, 1), + (6607, 1), + (6608, 1), + (6609, 3), + (6610, 3), + (6611, 1), + (6612, 2), + (6613, 1), + (6614, 2), + (6615, 1), + (6617, 4), + (6618, 4), + (6619, 1), + (6620, 4), + (6644, 1), + (6645, 1), + (6646, 1), + (6647, 1), + (6648, 5), + (6649, 2), + (6650, 1), + (6651, 1), + (6652, 3), + (6653, 2), + (6654, 3), + (6655, 1), + (6656, 2), + (6657, 2), + (6658, 2), + (6686, 1), + (6687, 4), + (6688, 5), + (6689, 4), + (6690, 1), + (6692, 1), + (6693, 1), + (6694, 3), + (6695, 3), + (6696, 1), + (6697, 1), + (6722, 2), + (6723, 1), + (6724, 1), + (6725, 3), + (6726, 1), + (6727, 2), + (6728, 2), + (6729, 6), + (6731, 1), + (6734, 1), + (6735, 3), + (6736, 3), + (6737, 1), + (6761, 2), + (6762, 1), + (6763, 3), + (6764, 2), + (6765, 1), + (6766, 5), + (6767, 1), + (6769, 3), + (6770, 2), + (6771, 3), + (6772, 3), + (6773, 3), + (6774, 4), + (6775, 1), + (6777, 1), + (6798, 1), + (6800, 2), + (6801, 1), + (6802, 3), + (6803, 2), + (6804, 3), + (6805, 2), + (6806, 7), + (6807, 1), + (6808, 2), + (6809, 2), + (6810, 4), + (6811, 2), + (6812, 3), + (6813, 2), + (6814, 1), + (6815, 1), + (6816, 2), + (6837, 1), + (6839, 1), + (6841, 5), + (6842, 3), + (6843, 4), + (6844, 5), + (6845, 1), + (6847, 3), + (6848, 1), + (6849, 2), + (6850, 3), + (6851, 1), + (6852, 2), + (6853, 2), + (6855, 1), + (6863, 6), + (6878, 1), + (6879, 2), + (6881, 2), + (6882, 3), + (6883, 2), + (6884, 4), + (6885, 4), + (6886, 2), + (6887, 3), + (6888, 3), + (6889, 3), + (6890, 1), + (6891, 2), + (6892, 2), + (6896, 1), + (6915, 1), + (6916, 2), + (6917, 2), + (6918, 1), + (6919, 1), + (6921, 1), + (6922, 2), + (6923, 8), + (6924, 3), + (6926, 7), + (6927, 2), + (6928, 2), + (6929, 1), + (6932, 1), + (6952, 6), + (6956, 1), + (6957, 4), + (6959, 5), + (6960, 2), + (6961, 6), + (6962, 6), + (6963, 1), + (6964, 2), + (6965, 5), + (6967, 4), + (6969, 1), + (6970, 3), + (6971, 1), + (6972, 1), + (6993, 1), + (6995, 2), + (6996, 1), + (6997, 2), + (6998, 1), + (6999, 1), + (7000, 5), + (7001, 2), + (7002, 4), + (7003, 3), + (7004, 1), + (7005, 1), + (7007, 2), + (7008, 2), + (7009, 1), + (7010, 1), + (7014, 1), + (7033, 1), + (7035, 2), + (7037, 1), + (7038, 3), + (7039, 2), + (7040, 8), + (7041, 1), + (7042, 2), + (7043, 2), + (7044, 1), + (7045, 1), + (7046, 2), + (7047, 1), + (7048, 2), + (7070, 1), + (7073, 1), + (7075, 1), + (7076, 1), + (7077, 1), + (7078, 3), + (7079, 5), + (7080, 4), + (7081, 4), + (7083, 1), + (7084, 2), + (7085, 4), + (7086, 2), + (7088, 2), + (7089, 3), + (7098, 6), + (7111, 1), + (7113, 1), + (7114, 3), + (7115, 7), + (7117, 3), + (7118, 6), + (7119, 1), + (7120, 2), + (7121, 2), + (7122, 3), + (7123, 1), + (7125, 2), + (7126, 2), + (7130, 1), + (7153, 5), + (7155, 2), + (7156, 4), + (7157, 3), + (7158, 2), + (7159, 1), + (7160, 2), + (7161, 1), + (7162, 2), + (7163, 4), + (7164, 3), + (7167, 3), + (7184, 2), + (7190, 1), + (7192, 1), + (7194, 1), + (7196, 4), + (7198, 1), + (7199, 2), + (7200, 4), + (7201, 4), + (7202, 2), + (7203, 1), + (7204, 2), + (7230, 2), + (7231, 1), + (7232, 3), + (7233, 3), + (7234, 1), + (7235, 2), + (7236, 3), + (7238, 2), + (7239, 4), + (7240, 1), + (7241, 3), + (7242, 3), + (7243, 2), + (7244, 1), + (7245, 1), + (7248, 1), + (7266, 1), + (7268, 1), + (7270, 2), + (7271, 4), + (7272, 1), + (7273, 2), + (7274, 6), + (7275, 2), + (7278, 3), + (7279, 4), + (7280, 2), + (7281, 1), + (7282, 2), + (7283, 1), + (7289, 1), + (7306, 1), + (7307, 1), + (7308, 2), + (7309, 1), + (7310, 2), + (7311, 2), + (7312, 3), + (7313, 3), + (7314, 1), + (7315, 4), + (7316, 3), + (7317, 2), + (7318, 4), + (7319, 1), + (7320, 2), + (7321, 1), + (7324, 1), + (7345, 1), + (7347, 2), + (7348, 6), + (7349, 2), + (7350, 6), + (7351, 8), + (7352, 2), + (7353, 4), + (7358, 2), + (7359, 2), + (7360, 2), + (7361, 2), + (7372, 6), + (7385, 1), + (7386, 3), + (7387, 1), + (7388, 1), + (7389, 3), + (7390, 3), + (7391, 1), + (7392, 4), + (7394, 3), + (7395, 3), + (7396, 4), + (7397, 2), + (7398, 4), + (7399, 2), + (7401, 1), + (7403, 1), + (7425, 1), + (7426, 2), + (7427, 5), + (7428, 4), + (7429, 5), + (7430, 4), + (7431, 1), + (7432, 1), + (7434, 1), + (7435, 2), + (7436, 7), + (7437, 1), + (7438, 1), + (7439, 1), + (7446, 1), + (7464, 1), + (7466, 2), + (7467, 3), + (7468, 2), + (7469, 5), + (7470, 3), + (7471, 2), + (7472, 1), + (7474, 1), + (7475, 4), + (7476, 4), + (7489, 1), + (7490, 6), + (7503, 1), + (7504, 2), + (7505, 3), + (7506, 2), + (7507, 2), + (7508, 2), + (7509, 1), + (7510, 2), + (7511, 3), + (7512, 3), + (7513, 5), + (7514, 1), + (7515, 4), + (7517, 1), + (7518, 1), + (7520, 1), + (7522, 1), + (7539, 1), + (7541, 2), + (7544, 6), + (7545, 3), + (7546, 2), + (7547, 5), + (7548, 3), + (7549, 2), + (7550, 1), + (7552, 1), + (7553, 5), + (7554, 2), + (7555, 2), + (7556, 1), + (7558, 1), + (7559, 1), + (7583, 2), + (7584, 3), + (7585, 5), + (7586, 3), + (7587, 2), + (7588, 5), + (7589, 1), + (7591, 2), + (7592, 3), + (7593, 4), + (7594, 1), + (7595, 2), + (7596, 2), + (7620, 1), + (7621, 3), + (7623, 5), + (7624, 3), + (7625, 3), + (7626, 3), + (7627, 4), + (7628, 5), + (7629, 1), + (7630, 1), + (7631, 1), + (7632, 3), + (7633, 2), + (7634, 1), + (7635, 1), + (7639, 1), + (7648, 6), + (7655, 6), + (7659, 2), + (7660, 2), + (7662, 2), + (7663, 1), + (7664, 3), + (7665, 6), + (7667, 1), + (7670, 3), + (7671, 3), + (7672, 1), + (7673, 2), + (7674, 1), + (7675, 1), + (7676, 1), + (7685, 1), + (7699, 2), + (7700, 2), + (7701, 5), + (7702, 3), + (7703, 5), + (7704, 3), + (7705, 1), + (7706, 2), + (7707, 5), + (7708, 4), + (7709, 2), + (7710, 1), + (7713, 1), + (7714, 1), + (7738, 2), + (7739, 2), + (7740, 3), + (7741, 4), + (7742, 3), + (7743, 2), + (7744, 4), + (7745, 3), + (7746, 1), + (7748, 2), + (7750, 3), + (7751, 1), + (7752, 2), + (7753, 1), + (7776, 2), + (7777, 3), + (7778, 2), + (7779, 2), + (7780, 3), + (7781, 3), + (7782, 5), + (7783, 4), + (7784, 2), + (7786, 4), + (7787, 2), + (7788, 2), + (7789, 4), + (7794, 1), + (7812, 1), + (7816, 1), + (7817, 3), + (7818, 2), + (7819, 3), + (7820, 3), + (7821, 8), + (7822, 3), + (7823, 3), + (7824, 3), + (7825, 2), + (7827, 1), + (7828, 3), + (7830, 2), + (7831, 1), + (7836, 6), + (7851, 1), + (7853, 1), + (7855, 1), + (7857, 1), + (7858, 1), + (7859, 2), + (7860, 3), + (7861, 1), + (7863, 1), + (7864, 6), + (7865, 4), + (7866, 4), + (7867, 4), + (7868, 1), + (7869, 1), + (7871, 1), + (7894, 2), + (7895, 5), + (7896, 6), + (7897, 5), + (7898, 1), + (7899, 1), + (7900, 1), + (7901, 3), + (7902, 1), + (7903, 1), + (7904, 9), + (7905, 2), + (7906, 1), + (7907, 2), + (7909, 1), + (7910, 1), + (7932, 3), + (7933, 9), + (7934, 1), + (7935, 4), + (7936, 3), + (7937, 7), + (7938, 2), + (7939, 4), + (7940, 3), + (7941, 1), + (7942, 2), + (7943, 4), + (7944, 2), + (7945, 5), + (7946, 2), + (7948, 1), + (7949, 1), + (7960, 6), + (7967, 2), + (7970, 2), + (7972, 2), + (7973, 1), + (7974, 2), + (7975, 1), + (7976, 3), + (7977, 2), + (7978, 2), + (7979, 1), + (7980, 5), + (7981, 1), + (7982, 2), + (7983, 3), + (7984, 3), + (7985, 1), + (7986, 4), + (7987, 1), + (7988, 1), + (8011, 4), + (8012, 5), + (8013, 1), + (8014, 3), + (8015, 3), + (8016, 1), + (8017, 5), + (8018, 1), + (8019, 3), + (8021, 1), + (8022, 6), + (8023, 4), + (8024, 1), + (8025, 1), + (8027, 1), + (8028, 2), + (8029, 2), + (8050, 2), + (8051, 3), + (8052, 1), + (8053, 6), + (8054, 3), + (8055, 1), + (8056, 2), + (8057, 4), + (8058, 2), + (8059, 4), + (8060, 3), + (8061, 3), + (8062, 2), + (8063, 1), + (8064, 2), + (8065, 1), + (8066, 1), + (8067, 1), + (8079, 1), + (8088, 2), + (8090, 2), + (8091, 5), + (8092, 3), + (8093, 4), + (8094, 1), + (8095, 3), + (8096, 2), + (8097, 3), + (8098, 2), + (8099, 2), + (8100, 2), + (8101, 2), + (8103, 6), + (8104, 1), + (8106, 1), + (8108, 1), + (8128, 2), + (8129, 3), + (8130, 13), + (8131, 4), + (8132, 2), + (8133, 2), + (8134, 3), + (8136, 2), + (8137, 2), + (8139, 7), + (8140, 7), + (8141, 3), + (8142, 1), + (8143, 2), + (8145, 1), + (8167, 1), + (8168, 1), + (8169, 5), + (8171, 6), + (8172, 2), + (8173, 1), + (8174, 2), + (8175, 1), + (8176, 1), + (8177, 7), + (8180, 2), + (8182, 1), + (8206, 1), + (8207, 6), + (8208, 4), + (8209, 5), + (8210, 3), + (8211, 7), + (8212, 4), + (8213, 3), + (8214, 4), + (8215, 2), + (8216, 4), + (8217, 2), + (8218, 4), + (8219, 3), + (8220, 2), + (8221, 1), + (8222, 1), + (8240, 6), + (8244, 2), + (8245, 1), + (8246, 2), + (8247, 5), + (8248, 6), + (8249, 1), + (8250, 1), + (8251, 2), + (8252, 5), + (8253, 1), + (8254, 7), + (8255, 4), + (8256, 2), + (8257, 3), + (8258, 4), + (8259, 2), + (8260, 3), + (8261, 1), + (8282, 1), + (8284, 2), + (8285, 3), + (8286, 4), + (8287, 5), + (8288, 1), + (8289, 3), + (8290, 4), + (8291, 3), + (8292, 2), + (8294, 1), + (8295, 1), + (8296, 3), + (8297, 3), + (8298, 2), + (8299, 2), + (8302, 1), + (8314, 1), + (8320, 1), + (8321, 1), + (8322, 1), + (8323, 1), + (8324, 2), + (8325, 2), + (8326, 2), + (8327, 2), + (8328, 4), + (8329, 2), + (8330, 1), + (8331, 1), + (8332, 4), + (8333, 3), + (8334, 3), + (8335, 3), + (8336, 1), + (8337, 1), + (8339, 2), + (8340, 1), + (8342, 6), + (8360, 1), + (8362, 1), + (8363, 5), + (8364, 6), + (8365, 3), + (8366, 2), + (8367, 6), + (8368, 2), + (8369, 2), + (8370, 3), + (8372, 5), + (8373, 2), + (8374, 7), + (8375, 3), + (8377, 2), + (8398, 1), + (8400, 2), + (8402, 2), + (8403, 4), + (8404, 1), + (8405, 2), + (8406, 2), + (8407, 2), + (8408, 4), + (8409, 3), + (8410, 4), + (8411, 3), + (8412, 2), + (8413, 2), + (8414, 5), + (8415, 2), + (8416, 1), + (8439, 2), + (8440, 1), + (8441, 3), + (8442, 4), + (8443, 2), + (8444, 5), + (8445, 2), + (8446, 1), + (8447, 3), + (8448, 1), + (8449, 4), + (8450, 3), + (8451, 6), + (8452, 2), + (8453, 3), + (8455, 3), + (8456, 2), + (8465, 1), + (8480, 4), + (8481, 5), + (8482, 7), + (8483, 4), + (8484, 2), + (8485, 3), + (8487, 1), + (8488, 3), + (8489, 3), + (8490, 6), + (8491, 4), + (8492, 5), + (8495, 1), + (8518, 2), + (8519, 1), + (8520, 3), + (8521, 1), + (8522, 4), + (8523, 2), + (8524, 1), + (8525, 1), + (8526, 2), + (8527, 5), + (8528, 1), + (8529, 2), + (8530, 5), + (8531, 4), + (8532, 3), + (8533, 3), + (8534, 1), + (8536, 1), + (8557, 4), + (8558, 4), + (8559, 3), + (8561, 3), + (8562, 1), + (8563, 1), + (8564, 1), + (8566, 1), + (8567, 1), + (8568, 4), + (8569, 2), + (8570, 6), + (8571, 4), + (8572, 4), + (8573, 3), + (8574, 1), + (8575, 1), + (8576, 6), + (8583, 1), + (8587, 4), + (8596, 1), + (8597, 3), + (8598, 1), + (8599, 3), + (8600, 2), + (8601, 2), + (8602, 2), + (8603, 2), + (8604, 1), + (8605, 2), + (8606, 2), + (8607, 2), + (8608, 1), + (8609, 2), + (8610, 2), + (8611, 2), + (8612, 2), + (8633, 1), + (8634, 8), + (8635, 3), + (8636, 1), + (8637, 3), + (8638, 3), + (8639, 1), + (8640, 2), + (8641, 1), + (8642, 2), + (8643, 2), + (8645, 4), + (8646, 2), + (8647, 8), + (8648, 5), + (8649, 1), + (8650, 3), + (8653, 5), + (8673, 1), + (8675, 1), + (8676, 1), + (8677, 5), + (8678, 4), + (8679, 4), + (8680, 2), + (8681, 3), + (8682, 3), + (8683, 3), + (8684, 2), + (8685, 2), + (8686, 2), + (8687, 1), + (8688, 3), + (8689, 2), + (8701, 6), + (8705, 6), + (8710, 1), + (8712, 1), + (8713, 1), + (8714, 1), + (8716, 1), + (8717, 6), + (8718, 2), + (8719, 2), + (8721, 1), + (8723, 6), + (8724, 1), + (8725, 1), + (8726, 2), + (8727, 1), + (8728, 1), + (8731, 1), + (8753, 1), + (8754, 3), + (8755, 2), + (8756, 1), + (8757, 1), + (8759, 6), + (8760, 1), + (8762, 2), + (8763, 3), + (8764, 3), + (8765, 2), + (8768, 2), + (8770, 2), + (8791, 2), + (8793, 1), + (8794, 2), + (8795, 1), + (8796, 1), + (8797, 1), + (8799, 1), + (8800, 3), + (8801, 3), + (8802, 2), + (8803, 4), + (8804, 6), + (8805, 3), + (8809, 1), + (8816, 1), + (8827, 1), + (8829, 1), + (8830, 1), + (8832, 2), + (8833, 5), + (8834, 3), + (8835, 2), + (8836, 1), + (8837, 3), + (8838, 2), + (8839, 1), + (8840, 3), + (8841, 3), + (8842, 2), + (8843, 2), + (8845, 1), + (8869, 2), + (8870, 6), + (8871, 1), + (8872, 6), + (8875, 5), + (8876, 4), + (8877, 1), + (8878, 5), + (8879, 2), + (8880, 3), + (8882, 1), + (8884, 3), + (8885, 1), + (8886, 1), + (8887, 6), + (8888, 1), + (8909, 1), + (8910, 1), + (8911, 2), + (8912, 2), + (8914, 3), + (8917, 5), + (8918, 1), + (8919, 6), + (8920, 3), + (8921, 4), + (8922, 6), + (8923, 1), + (8928, 1), + (8946, 1), + (8948, 1), + (8949, 2), + (8950, 9), + (8951, 2), + (8952, 2), + (8953, 2), + (8954, 2), + (8956, 2), + (8957, 1), + (8958, 3), + (8959, 5), + (8960, 1), + (8961, 4), + (8962, 2), + (8985, 1), + (8987, 1), + (8990, 2), + (8991, 3), + (8992, 2), + (8993, 2), + (8994, 1), + (8995, 1), + (8997, 6), + (8998, 3), + (8999, 1), + (9001, 1), + (9002, 1), + (9003, 1), + (9004, 5), + (9007, 5), + (9026, 1), + (9027, 2), + (9028, 3), + (9029, 2), + (9030, 2), + (9031, 1), + (9034, 1), + (9035, 3), + (9036, 2), + (9037, 4), + (9038, 5), + (9039, 2), + (9064, 2), + (9065, 1), + (9066, 2), + (9067, 4), + (9069, 3), + (9070, 2), + (9071, 3), + (9072, 2), + (9074, 2), + (9075, 3), + (9076, 1), + (9078, 3), + (9079, 2), + (9080, 1), + (9087, 1), + (9104, 1), + (9106, 1), + (9107, 2), + (9108, 1), + (9109, 1), + (9110, 1), + (9111, 2), + (9112, 1), + (9113, 2), + (9114, 3), + (9115, 1), + (9116, 2), + (9117, 3), + (9120, 1), + (9139, 1), + (9145, 3), + (9146, 1), + (9147, 5), + (9148, 1), + (9149, 3), + (9150, 3), + (9151, 3), + (9152, 2), + (9153, 9), + (9154, 1), + (9155, 2), + (9156, 1), + (9157, 1), + (9181, 1), + (9183, 4), + (9184, 7), + (9185, 1), + (9186, 1), + (9187, 1), + (9189, 2), + (9190, 1), + (9191, 1), + (9192, 4), + (9193, 3), + (9194, 1), + (9195, 2), + (9196, 1), + (9197, 2), + (9198, 1), + (9204, 6), + (9219, 1), + (9221, 3), + (9222, 2), + (9223, 3), + (9224, 1), + (9227, 2), + (9228, 1), + (9229, 2), + (9230, 3), + (9232, 1), + (9233, 2), + (9235, 1), + (9259, 1), + (9260, 1), + (9261, 1), + (9262, 2), + (9264, 2), + (9265, 1), + (9268, 1), + (9269, 2), + (9270, 2), + (9271, 1), + (9272, 6), + (9273, 2), + (9274, 1), + (9298, 1), + (9299, 2), + (9301, 2), + (9302, 3), + (9303, 2), + (9305, 1), + (9306, 1), + (9307, 3), + (9308, 1), + (9309, 1), + (9310, 3), + (9311, 2), + (9312, 3), + (9313, 2), + (9334, 3), + (9339, 1), + (9340, 2), + (9342, 1), + (9343, 1), + (9346, 2), + (9347, 4), + (9348, 3), + (9350, 2), + (9351, 4), + (9352, 2), + (9353, 1), + (9376, 1), + (9377, 2), + (9378, 2), + (9379, 3), + (9380, 1), + (9381, 2), + (9382, 3), + (9384, 3), + (9386, 3), + (9387, 2), + (9388, 3), + (9389, 8), + (9390, 1), + (9391, 1), + (9415, 2), + (9419, 1), + (9420, 3), + (9421, 2), + (9422, 2), + (9425, 3), + (9426, 6), + (9427, 3), + (9428, 1), + (9429, 3), + (9430, 1), + (9431, 1), + (9455, 2), + (9456, 1), + (9457, 2), + (9458, 1), + (9459, 1), + (9460, 1), + (9461, 1), + (9462, 2), + (9463, 3), + (9464, 2), + (9465, 3), + (9466, 2), + (9467, 2), + (9468, 4), + (9474, 1), + (9491, 1), + (9494, 3), + (9496, 1), + (9497, 2), + (9498, 1), + (9501, 2), + (9503, 2), + (9504, 3), + (9505, 3), + (9506, 10), + (9507, 3), + (9508, 4), + (9509, 2), + (9510, 1), + (9533, 2), + (9534, 6), + (9535, 1), + (9536, 1), + (9537, 1), + (9538, 1), + (9539, 1), + (9541, 1), + (9542, 1), + (9543, 1), + (9544, 2), + (9545, 3), + (9546, 3), + (9547, 2), + (9562, 6), + (9570, 1), + (9571, 1), + (9572, 2), + (9573, 1), + (9574, 1), + (9576, 4), + (9577, 1), + (9581, 3), + (9582, 8), + (9584, 2), + (9585, 1), + (9586, 3), + (9609, 1), + (9611, 1), + (9612, 5), + (9613, 1), + (9614, 1), + (9616, 2), + (9618, 2), + (9619, 1), + (9621, 3), + (9622, 1), + (9623, 2), + (9624, 3), + (9625, 4), + (9626, 1), + (9628, 1), + (9650, 2), + (9653, 2), + (9656, 1), + (9657, 2), + (9658, 1), + (9659, 2), + (9660, 1), + (9661, 4), + (9662, 2), + (9666, 2), + (9668, 1), + (9689, 1), + (9690, 1), + (9693, 1), + (9694, 2), + (9695, 1), + (9696, 1), + (9698, 2), + (9699, 3), + (9700, 1), + (9701, 4), + (9703, 1), + (9705, 1), + (9727, 1), + (9729, 1), + (9731, 1), + (9732, 1), + (9733, 1), + (9734, 3), + (9735, 1), + (9736, 1), + (9737, 1), + (9738, 1), + (9739, 1), + (9740, 3), + (9742, 1), + (9743, 2), + (9744, 1), + (9767, 1), + (9769, 2), + (9770, 1), + (9771, 3), + (9772, 3), + (9773, 2), + (9776, 3), + (9777, 5), + (9778, 1), + (9779, 3), + (9780, 1), + (9783, 1), + (9808, 1), + (9809, 1), + (9811, 2), + (9814, 1), + (9815, 4), + (9816, 3), + (9817, 2), + (9818, 2), + (9819, 1), + (9820, 2), + (9821, 2), + (9824, 1), + (9840, 3), + (9847, 3), + (9849, 8), + (9852, 1), + (9853, 1), + (9854, 4), + (9855, 5), + (9856, 1), + (9857, 3), + (9858, 2), + (9859, 1), + (9884, 5), + (9886, 2), + (9888, 1), + (9889, 1), + (9891, 2), + (9892, 1), + (9893, 1), + (9895, 2), + (9896, 3), + (9897, 4), + (9903, 1), + (9923, 2), + (9924, 2), + (9925, 3), + (9927, 1), + (9928, 2), + (9929, 1), + (9932, 2), + (9933, 1), + (9935, 4), + (9936, 2), + (9937, 3), + (9939, 1), + (9940, 1), + (9964, 4), + (9966, 1), + (9967, 1), + (9970, 1), + (9971, 1), + (9972, 1), + (9973, 2), + (9974, 5), + (9975, 1), + (9976, 2), + (9977, 3), + (9996, 1), + (9999, 1), + (10002, 1), + (10003, 2), + (10004, 2), + (10005, 2), + (10011, 4), + (10012, 2), + (10013, 2), + (10015, 1), + (10016, 1), + (10040, 1), + (10042, 1), + (10043, 4), + (10044, 3), + (10048, 1), + (10049, 1), + (10050, 1), + (10051, 1), + (10052, 2), + (10053, 2), + (10054, 2), + (10081, 2), + (10082, 1), + (10084, 1), + (10085, 1), + (10086, 1), + (10087, 2), + (10089, 2), + (10090, 2), + (10092, 2), + (10093, 2), + (10094, 1), + (10096, 6), + (10117, 5), + (10118, 3), + (10119, 2), + (10121, 1), + (10122, 2), + (10123, 5), + (10124, 3), + (10125, 1), + (10126, 3), + (10127, 1), + (10129, 4), + (10130, 2), + (10131, 1), + (10132, 2), + (10134, 1), + (10139, 6), + (10155, 1), + (10157, 2), + (10158, 2), + (10161, 2), + (10163, 1), + (10165, 2), + (10168, 1), + (10169, 1), + (10170, 2), + (10171, 2), + (10172, 1), + (10197, 1), + (10198, 1), + (10202, 1), + (10205, 1), + (10206, 1), + (10207, 1), + (10208, 2), + (10210, 2), + (10211, 1), + (10232, 1), + (10234, 1), + (10236, 1), + (10237, 1), + (10238, 1), + (10239, 2), + (10240, 1), + (10242, 1), + (10243, 2), + (10244, 2), + (10245, 2), + (10246, 4), + (10247, 3), + (10248, 1), + (10251, 1), + (10259, 1), + (10278, 1), + (10279, 1), + (10280, 2), + (10282, 1), + (10283, 1), + (10285, 3), + (10286, 1), + (10287, 3), + (10289, 1), + (10312, 1), + (10313, 1), + (10314, 1), + (10315, 1), + (10317, 3), + (10319, 1), + (10322, 2), + (10323, 1), + (10324, 1), + (10325, 2), + (10326, 1), + (10327, 1), + (10329, 2), + (10350, 1), + (10353, 1), + (10355, 3), + (10356, 1), + (10358, 1), + (10360, 1), + (10362, 1), + (10363, 1), + (10364, 2), + (10365, 1), + (10366, 4), + (10391, 1), + (10393, 1), + (10394, 2), + (10395, 3), + (10400, 4), + (10404, 3), + (10405, 1), + (10407, 1), + (10416, 6), + (10430, 2), + (10431, 1), + (10432, 1), + (10434, 3), + (10435, 1), + (10437, 1), + (10438, 2), + (10439, 2), + (10440, 2), + (10441, 1), + (10442, 1), + (10445, 2), + (10446, 2), + (10469, 2), + (10470, 1), + (10471, 1), + (10472, 1), + (10473, 2), + (10474, 1), + (10476, 1), + (10477, 1), + (10481, 1), + (10482, 1), + (10483, 3), + (10485, 1), + (10487, 1), + (10488, 1), + (10510, 1), + (10511, 2), + (10512, 1), + (10514, 1), + (10515, 1), + (10518, 2), + (10519, 1), + (10520, 1), + (10522, 2), + (10548, 2), + (10549, 2), + (10550, 3), + (10553, 1), + (10554, 1), + (10555, 2), + (10556, 1), + (10557, 3), + (10559, 1), + (10563, 1), + (10586, 1), + (10587, 2), + (10589, 3), + (10590, 2), + (10591, 1), + (10592, 1), + (10593, 2), + (10594, 2), + (10597, 1), + (10598, 2), + (10599, 2), + (10602, 1), + (10603, 1), + (10604, 2), + (10625, 2), + (10626, 2), + (10627, 3), + (10629, 6), + (10630, 2), + (10631, 1), + (10636, 1), + (10638, 1), + (10639, 1), + (10640, 1), + (10662, 6), + (10664, 2), + (10667, 1), + (10672, 1), + (10673, 2), + (10674, 1), + (10675, 1), + (10679, 1), + (10698, 77), + (10703, 2), + (10704, 1), + (10705, 1), + (10707, 5), + (10708, 1), + (10711, 1), + (10712, 1), + (10714, 1), + (10716, 3), + (10717, 1), + (10718, 1), + (10720, 1), + (10742, 2), + (10744, 1), + (10746, 1), + (10747, 1), + (10752, 1), + (10753, 1), + (10754, 3), + (10755, 1), + (10757, 1), + (10788, 1), + (10789, 1), + (10790, 1), + (10791, 6), + (10793, 2), + (10794, 2), + (10795, 2), + (10798, 1), + (10818, 1), + (10821, 1), + (10826, 1), + (10830, 1), + (10832, 1), + (10834, 1), + (10835, 1), + (10837, 1), + (10857, 1), + (10861, 2), + (10862, 1), + (10864, 1), + (10865, 1), + (10868, 4), + (10869, 1), + (10870, 2), + (10871, 4), + (10872, 1), + (10875, 1), + (10898, 3), + (10899, 1), + (10903, 1), + (10904, 1), + (10905, 1), + (10907, 4), + (10908, 1), + (10909, 2), + (10911, 2), + (10912, 1), + (10913, 1), + (10916, 1), + (10931, 5), + (10933, 1), + (10937, 1), + (10938, 1), + (10939, 1), + (10943, 1), + (10945, 1), + (10946, 3), + (10947, 1), + (10948, 1), + (10949, 3), + (10952, 1), + (10977, 1), + (10978, 1), + (10979, 1), + (10980, 1), + (10981, 1), + (10982, 1), + (10984, 1), + (10985, 2), + (10986, 1), + (10987, 1), + (10988, 1), + (10991, 2), + (10992, 1), + (11014, 1), + (11016, 1), + (11018, 2), + (11019, 1), + (11020, 4), + (11022, 1), + (11023, 1), + (11025, 1), + (11026, 1), + (11028, 4), + (11029, 2), + (11052, 1), + (11056, 1), + (11057, 1), + (11062, 3), + (11063, 2), + (11064, 2), + (11065, 1), + (11067, 1), + (11069, 1), + (11070, 1), + (11084, 1), + (11093, 1), + (11103, 1), + (11104, 2), + (11105, 3), + (11106, 2), + (11107, 1), + (11132, 1), + (11133, 1), + (11134, 1), + (11135, 3), + (11136, 1), + (11139, 1), + (11141, 1), + (11144, 2), + (11146, 1), + (11147, 1), + (11148, 1), + (11171, 1), + (11173, 1), + (11174, 1), + (11176, 1), + (11180, 1), + (11183, 1), + (11186, 1), + (11210, 1), + (11212, 1), + (11219, 1), + (11220, 2), + (11222, 3), + (11223, 2), + (11224, 1), + (11225, 1), + (11226, 1), + (11231, 1), + (11249, 1), + (11250, 1), + (11253, 1), + (11254, 5), + (11257, 1), + (11258, 3), + (11259, 3), + (11261, 1), + (11264, 2), + (11287, 1), + (11289, 1), + (11290, 2), + (11291, 1), + (11293, 1), + (11296, 1), + (11300, 1), + (11301, 1), + (11302, 1), + (11326, 1), + (11328, 5), + (11329, 1), + (11335, 1), + (11336, 2), + (11337, 1), + (11338, 1), + (11339, 1), + (11340, 1), + (11366, 3), + (11368, 1), + (11369, 2), + (11370, 1), + (11374, 2), + (11375, 1), + (11378, 2), + (11379, 1), + (11404, 2), + (11407, 1), + (11409, 2), + (11410, 2), + (11411, 1), + (11414, 1), + (11415, 3), + (11417, 1), + (11422, 1), + (11443, 1), + (11446, 1), + (11450, 1), + (11454, 1), + (11455, 2), + (11481, 6), + (11485, 1), + (11487, 1), + (11488, 1), + (11492, 1), + (11493, 1), + (11494, 1), + (11495, 1), + (11498, 3), + (11499, 1), + (11521, 1), + (11522, 1), + (11524, 2), + (11525, 2), + (11526, 1), + (11528, 1), + (11532, 1), + (11564, 1), + (11565, 2), + (11572, 1), + (11576, 1), + (11577, 1), + (11599, 1), + (11601, 1), + (11602, 2), + (11603, 1), + (11607, 1), + (11609, 1), + (11614, 1), + (11616, 1), + (11631, 1), + (11640, 2), + (11641, 1), + (11642, 1), + (11643, 4), + (11651, 3), + (11653, 2), + (11654, 1), + (11655, 1), + (11679, 2), + (11682, 5), + (11686, 1), + (11687, 1), + (11689, 1), + (11690, 3), + (11691, 1), + (11693, 1), + (11717, 2), + (11719, 3), + (11720, 4), + (11721, 6), + (11726, 1), + (11727, 1), + (11728, 1), + (11750, 6), + (11755, 3), + (11756, 2), + (11757, 2), + (11759, 1), + (11762, 1), + (11763, 1), + (11764, 1), + (11765, 3), + (11766, 1), + (11768, 1), + (11769, 1), + (11770, 2), + (11796, 2), + (11797, 2), + (11798, 1), + (11801, 1), + (11804, 1), + (11806, 1), + (11807, 3), + (11808, 1), + (11810, 1), + (11811, 1), + (11813, 1), + (11837, 2), + (11841, 2), + (11843, 2), + (11844, 1), + (11845, 1), + (11846, 1), + (11871, 1), + (11876, 2), + (11877, 1), + (11878, 1), + (11880, 1), + (11881, 2), + (11882, 4), + (11883, 5), + (11884, 3), + (11885, 1), + (11888, 1), + (11912, 2), + (11913, 1), + (11923, 1), + (11926, 1), + (11927, 1), + (11928, 1), + (11951, 1), + (11953, 2), + (11955, 1), + (11956, 2), + (11959, 2), + (11961, 1), + (11962, 1), + (11964, 1), + (11966, 2), + (11990, 1), + (11992, 3), + (12003, 2), + (12028, 1), + (12031, 1), + (12033, 1), + (12035, 1), + (12037, 1), + (12038, 1), + (12039, 2), + (12040, 1), + (12041, 1), + (12043, 2), + (12072, 4), + (12077, 2), + (12078, 3), + (12079, 2), + (12080, 1), + (12108, 2), + (12109, 2), + (12112, 1), + (12114, 1), + (12115, 2), + (12116, 1), + (12117, 2), + (12118, 1), + (12123, 2), + (12145, 1), + (12146, 1), + (12147, 3), + (12148, 1), + (12151, 1), + (12156, 1), + (12158, 2), + (12183, 1), + (12190, 1), + (12192, 1), + (12194, 2), + (12195, 1), + (12196, 2), + (12197, 3), + (12198, 3), + (12201, 1), + (12224, 1), + (12225, 1), + (12226, 1), + (12230, 1), + (12231, 1), + (12234, 1), + (12236, 1), + (12237, 3), + (12263, 1), + (12265, 1), + (12266, 1), + (12267, 1), + (12269, 1), + (12272, 1), + (12273, 2), + (12274, 2), + (12276, 2), + (12277, 1), + (12279, 1), + (12280, 1), + (12300, 1), + (12303, 1), + (12305, 1), + (12307, 2), + (12309, 1), + (12310, 2), + (12311, 1), + (12315, 2), + (12321, 1), + (12341, 1), + (12344, 2), + (12350, 2), + (12351, 1), + (12352, 1), + (12353, 1), + (12383, 1), + (12389, 2), + (12390, 1), + (12391, 1), + (12392, 4), + (12395, 1), + (12421, 3), + (12423, 1), + (12428, 1), + (12429, 1), + (12430, 1), + (12457, 1), + (12461, 1), + (12463, 1), + (12468, 1), + (12471, 1), + (12473, 1), + (12498, 5), + (12499, 2), + (12502, 1), + (12503, 1), + (12505, 1), + (12506, 1), + (12508, 2), + (12509, 1), + (12510, 1), + (12511, 1), + (12513, 1), + (12535, 1), + (12536, 1), + (12537, 1), + (12538, 1), + (12539, 1), + (12540, 1), + (12542, 1), + (12545, 1), + (12547, 2), + (12548, 1), + (12550, 1), + (12577, 1), + (12581, 1), + (12583, 1), + (12585, 1), + (12586, 3), + (12618, 1), + (12624, 1), + (12626, 1), + (12655, 1), + (12657, 3), + (12658, 1), + (12663, 1), + (12664, 3), + (12665, 2), + (12667, 1), + (12682, 1), + (12693, 1), + (12697, 1), + (12699, 1), + (12701, 1), + (12702, 1), + (12705, 2), + (12706, 1), + (12730, 1), + (12732, 2), + (12733, 2), + (12737, 1), + (12739, 1), + (12740, 1), + (12742, 3), + (12771, 1), + (12773, 1), + (12780, 1), + (12781, 3), + (12782, 1), + (12809, 1), + (12811, 1), + (12812, 1), + (12819, 1), + (12821, 1), + (12822, 1), + (12824, 1), + (12826, 1), + (12848, 1), + (12851, 2), + (12853, 1), + (12860, 3), + (12861, 1), + (12862, 1), + (12863, 1), + (12889, 1), + (12890, 1), + (12896, 1), + (12899, 1), + (12928, 1), + (12929, 2), + (12930, 1), + (12936, 1), + (12937, 3), + (12938, 1), + (12941, 1), + (12964, 1), + (12969, 1), + (12971, 1), + (12973, 1), + (12976, 1), + (12977, 2), + (13005, 1), + (13006, 1), + (13008, 1), + (13010, 1), + (13013, 2), + (13015, 2), + (13018, 1), + (13046, 1), + (13047, 1), + (13053, 2), + (13055, 2), + (13081, 1), + (13083, 1), + (13085, 4), + (13086, 1), + (13091, 2), + (13092, 2), + (13094, 2), + (13095, 1), + (13096, 1), + (13097, 1), + (13123, 2), + (13127, 1), + (13130, 1), + (13131, 1), + (13132, 1), + (13134, 1), + (13136, 1), + (13159, 1), + (13161, 2), + (13162, 1), + (13167, 2), + (13168, 1), + (13172, 1), + (13174, 1), + (13175, 1), + (13176, 1), + (13206, 1), + (13207, 1), + (13209, 2), + (13212, 1), + (13213, 2), + (13239, 2), + (13242, 1), + (13247, 1), + (13249, 2), + (13252, 1), + (13279, 1), + (13280, 2), + (13282, 5), + (13284, 1), + (13286, 1), + (13288, 1), + (13289, 1), + (13290, 1), + (13291, 1), + (13317, 1), + (13318, 1), + (13319, 1), + (13320, 1), + (13325, 1), + (13326, 1), + (13328, 2), + (13330, 2), + (13354, 2), + (13356, 6), + (13360, 2), + (13362, 1), + (13363, 2), + (13364, 3), + (13367, 2), + (13368, 3), + (13370, 1), + (13393, 1), + (13397, 2), + (13406, 1), + (13408, 1), + (13435, 1), + (13436, 1), + (13438, 1), + (13440, 2), + (13442, 1), + (13443, 1), + (13444, 1), + (13445, 1), + (13449, 1), + (13473, 2), + (13474, 1), + (13475, 1), + (13479, 2), + (13481, 2), + (13482, 1), + (13484, 1), + (13485, 1), + (13491, 1), + (13511, 1), + (13520, 1), + (13521, 2), + (13522, 1), + (13527, 1), + (13550, 1), + (13551, 1), + (13552, 3), + (13555, 1), + (13557, 1), + (13559, 2), + (13562, 2), + (13564, 1), + (13590, 1), + (13592, 1), + (13596, 1), + (13600, 2), + (13602, 1), + (13603, 1), + (13630, 1), + (13633, 1), + (13634, 1), + (13637, 1), + (13640, 1), + (13643, 1), + (13668, 1), + (13669, 2), + (13670, 2), + (13674, 1), + (13676, 1), + (13677, 1), + (13678, 4), + (13679, 1), + (13680, 1), + (13713, 1), + (13714, 1), + (13716, 6), + (13717, 2), + (13745, 1), + (13752, 2), + (13753, 1), + (13754, 1), + (13755, 1), + (13757, 1), + (13758, 1), + (13791, 1), + (13795, 1), + (13796, 2), + (13823, 2), + (13831, 1), + (13834, 1), + (13836, 1), + (13837, 1), + (13862, 1), + (13863, 1), + (13864, 1), + (13867, 1), + (13875, 1), + (13876, 1), + (13877, 1), + (13878, 1), + (13906, 1), + (13910, 2), + (13911, 1), + (13912, 2), + (13914, 2), + (13942, 1), + (13947, 2), + (13948, 2), + (13950, 3), + (13951, 1), + (13952, 1), + (13953, 1), + (13954, 1), + (13980, 1), + (13985, 1), + (13987, 1), + (13988, 1), + (13989, 1), + (14016, 1), + (14018, 7), + (14020, 2), + (14021, 1), + (14022, 1), + (14023, 1), + (14024, 1), + (14026, 1), + (14027, 1), + (14030, 1), + (14061, 1), + (14063, 6), + (14064, 1), + (14068, 1), + (14074, 1), + (14098, 1), + (14099, 2), + (14102, 5), + (14104, 2), + (14108, 1), + (14136, 1), + (14140, 1), + (14143, 1), + (14145, 1), + (14146, 1), + (14148, 1), + (14174, 2), + (14176, 1), + (14177, 1), + (14186, 1), + (14188, 1), + (14189, 1), + (14190, 1), + (14213, 1), + (14216, 1), + (14225, 1), + (14226, 1), + (14253, 1), + (14257, 1), + (14258, 1), + (14261, 2), + (14264, 1), + (14265, 1), + (14266, 1), + (14292, 1), + (14293, 1), + (14294, 1), + (14303, 1), + (14328, 1), + (14336, 1), + (14337, 1), + (14340, 1), + (14341, 1), + (14342, 1), + (14370, 1), + (14371, 1), + (14373, 5), + (14375, 1), + (14378, 1), + (14382, 2), + (14409, 1), + (14410, 1), + (14412, 1), + (14417, 1), + (14420, 4), + (14421, 1), + (14424, 1), + (14448, 5), + (14449, 2), + (14455, 1), + (14459, 1), + (14460, 1), + (14491, 1), + (14492, 1), + (14494, 1), + (14495, 1), + (14500, 1), + (14522, 1), + (14530, 2), + (14532, 3), + (14534, 1), + (14537, 2), + (14563, 1), + (14565, 1), + (14567, 1), + (14575, 1), + (14576, 1), + (14578, 2), + (14606, 2), + (14607, 2), + (14608, 1), + (14610, 1), + (14611, 1), + (14614, 1), + (14618, 2), + (14645, 2), + (14648, 1), + (14651, 1), + (14652, 1), + (14653, 1), + (14655, 1), + (14685, 1), + (14687, 1), + (14688, 1), + (14689, 1), + (14691, 4), + (14692, 1), + (14694, 1), + (14695, 1), + (14720, 1), + (14722, 1), + (14723, 1), + (14724, 1), + (14725, 1), + (14727, 1), + (14728, 1), + (14730, 2), + (14731, 1), + (14732, 2), + (14735, 2), + (14757, 1), + (14763, 1), + (14765, 1), + (14767, 1), + (14769, 2), + (14797, 1), + (14798, 1), + (14801, 1), + (14806, 2), + (14810, 2), + (14811, 1), + (14813, 2), + (14842, 1), + (14847, 2), + (14849, 2), + (14875, 1), + (14881, 1), + (14884, 1), + (14885, 2), + (14886, 2), + (14889, 2), + (14917, 1), + (14919, 1), + (14921, 2), + (14923, 1), + (14924, 1), + (14926, 1), + (14927, 1), + (14928, 1), + (14956, 2), + (14957, 1), + (14958, 1), + (14961, 1), + (14963, 3), + (14968, 1), + (15003, 2), + (15007, 1), + (15034, 1), + (15041, 2), + (15043, 1), + (15044, 1), + (15045, 1), + (15076, 1), + (15080, 1), + (15081, 1), + (15082, 1), + (15083, 1), + (15085, 1), + (15112, 1), + (15114, 1), + (15117, 1), + (15118, 1), + (15120, 2), + (15123, 1), + (15124, 1), + (15155, 1), + (15156, 1), + (15165, 1), + (15186, 1), + (15196, 1), + (15197, 1), + (15199, 1), + (15200, 1), + (15231, 1), + (15232, 2), + (15233, 1), + (15235, 3), + (15237, 2), + (15238, 1), + (15266, 1), + (15270, 1), + (15275, 2), + (15276, 1), + (15280, 1), + (15309, 1), + (15314, 1), + (15345, 1), + (15352, 1), + (15353, 2), + (15355, 2), + (15356, 1), + (15384, 1), + (15385, 1), + (15386, 1), + (15388, 1), + (15396, 1), + (15421, 1), + (15422, 1), + (15425, 1), + (15434, 1), + (15435, 1), + (15436, 1), + (15461, 1), + (15462, 1), + (15463, 1), + (15469, 1), + (15474, 1), + (15475, 1), + (15500, 1), + (15504, 1), + (15505, 1), + (15507, 1), + (15508, 1), + (15509, 1), + (15512, 1), + (15513, 1), + (15539, 1), + (15542, 1), + (15544, 1), + (15548, 2), + (15550, 1), + (15551, 1), + (15580, 1), + (15586, 1), + (15587, 1), + (15589, 1), + (15590, 1), + (15618, 1), + (15620, 1), + (15624, 1), + (15626, 1), + (15659, 2), + (15662, 1), + (15665, 1), + (15667, 1), + (15668, 1), + (15695, 1), + (15697, 1), + (15698, 1), + (15701, 1), + (15702, 1), + (15704, 1), + (15709, 2), + (15740, 1), + (15741, 1), + (15742, 1), + (15743, 1), + (15746, 1), + (15778, 1), + (15779, 1), + (15782, 1), + (15784, 1), + (15786, 1), + (15825, 1), + (15849, 1), + (15853, 1), + (15857, 1), + (15860, 1), + (15864, 1), + (15891, 1), + (15893, 2), + (15895, 1), + (15896, 1), + (15898, 1), + (15900, 1), + (15932, 1), + (15937, 1), + (15938, 1), + (15967, 1), + (15973, 1), + (15977, 1), + (15980, 1), + (16007, 1), + (16010, 1), + (16012, 1), + (16014, 1), + (16016, 1), + (16018, 1), + (16019, 1), + (16053, 1), + (16058, 1), + (16086, 1), + (16091, 1), + (16093, 1), + (16098, 1), + (16137, 1), + (16162, 1), + (16163, 1), + (16167, 1), + (16168, 2), + (16171, 1), + (16172, 2), + (16202, 1), + (16206, 1), + (16210, 2), + (16212, 1), + (16213, 1), + (16215, 1), + (16245, 1), + (16249, 1), + (16280, 1), + (16283, 1), + (16284, 1), + (16288, 1), + (16319, 1), + (16322, 2), + (16326, 1), + (16327, 3), + (16329, 1), + (16331, 1), + (16370, 1), + (16403, 1), + (16404, 1), + (16406, 1), + (16409, 1), + (16410, 1), + (16411, 1), + (16434, 1), + (16440, 1), + (16441, 1), + (16443, 2), + (16444, 1), + (16445, 1), + (16460, 1), + (16475, 1), + (16479, 1), + (16482, 1), + (16483, 2), + (16488, 1), + (16521, 2), + (16523, 2), + (16524, 1), + (16525, 2), + (16551, 1), + (16552, 1), + (16553, 2), + (16558, 1), + (16563, 1), + (16565, 1), + (16567, 1), + (16593, 1), + (16595, 1), + (16596, 1), + (16600, 1), + (16639, 2), + (16644, 1), + (16673, 2), + (16674, 1), + (16678, 1), + (16712, 1), + (16714, 1), + (16717, 1), + (16718, 1), + (16750, 1), + (16751, 1), + (16753, 1), + (16756, 1), + (16792, 1), + (16796, 1), + (16798, 2), + (16827, 1), + (16875, 1), + (16906, 1), + (16909, 1), + (16910, 1), + (16911, 2), + (16941, 1), + (16943, 1), + (16948, 1), + (16949, 1), + (16954, 1), + (16957, 1), + (16985, 1), + (16993, 1), + (17022, 2), + (17024, 1), + (17028, 1), + (17032, 1), + (17066, 2), + (17103, 1), + (17104, 2), + (17106, 1), + (17109, 1), + (17139, 1), + (17143, 1), + (17179, 1), + (17183, 2), + (17187, 1), + (17189, 1), + (17217, 1), + (17223, 2), + (17255, 1), + (17262, 1), + (17265, 1), + (17278, 1), + (17298, 1), + (17302, 2), + (17334, 1), + (17338, 1), + (17371, 2), + (17378, 1), + (17381, 1), + (17415, 1), + (17416, 1), + (17457, 1), + (17458, 1), + (17490, 1), + (17499, 1), + (17536, 1), + (17539, 1), + (17568, 1), + (17571, 1), + (17572, 1), + (17616, 1), + (17617, 1), + (17619, 1), + (17682, 5), + (17687, 1), + (17729, 1), + (17731, 1), + (17763, 1), + (17769, 1), + (17803, 1), + (17806, 1), + (17812, 1), + (17841, 1), + (17887, 1), + (17889, 1), + (17920, 1), + (17922, 1), + (17925, 1), + (17961, 1), + (17965, 1), + (17967, 1), + (18004, 1), + (18030, 1), + (18040, 2), + (18042, 1), + (18043, 1), + (18044, 1), + (18045, 1), + (18078, 1), + (18157, 1), + (18167, 1), + (18236, 1), + (18239, 1), + (18270, 1), + (18314, 1), + (18355, 1), + (18394, 1), + (18396, 1), + (18436, 1), + (18465, 1), + (18469, 1), + (18505, 1), + (18542, 2), + (18547, 1), + (18550, 1), + (18584, 1), + (18587, 1), + (18588, 1), + (18667, 1), + (18668, 1), + (18702, 1), + (18741, 1), + (18742, 1), + (18783, 1), + (18784, 1), + (18818, 1), + (18855, 1), + (18900, 1), + (18904, 1), + (18939, 1), + (18943, 1), + (18977, 1), + (19013, 1), + (19019, 1), + (19021, 1), + (19048, 1), + (19053, 1), + (19056, 1), + (19133, 2), + (19172, 1), + (19176, 2), + (19201, 5), + (19211, 1), + (19248, 1), + (19249, 1), + (19280, 1), + (19288, 1), + (19295, 1), + (19325, 1), + (19327, 1), + (19328, 2), + (19330, 2), + (19337, 6), + (19365, 1), + (19406, 1), + (19407, 1), + (19450, 1), + (19487, 1), + (19526, 1), + (19561, 2), + (19564, 1), + (19600, 1), + (19605, 1), + (19640, 1), + (19680, 1), + (19720, 1), + (19758, 1), + (19800, 1), + (19952, 2), + (19954, 1), + (19955, 1), + (19956, 1), + (19988, 1), + (19989, 26), + (19990, 21), + (19991, 30), + (19992, 21), + (19993, 13), + (19994, 12), + (19995, 9), + (19996, 6), + (20000, 1), + (20010, 1), + (20030, 1), + (20031, 1), + (20066, 1), + (20069, 1), + (20070, 1), + (20073, 1), + (20109, 1), + (20111, 1), + (20132, 1), + (20150, 1), + (20186, 1), + (20266, 1), + (20267, 1), + (20268, 1), + (20302, 1), + (20303, 1), + (20423, 1), + (20424, 1), + (20540, 1), + (20577, 1), + (20616, 1), + (20654, 1), + (20655, 2), + (20693, 1), + (20696, 1), + (20732, 2), + (20773, 2), + (20883, 1), + (20888, 1), + (20892, 1), + (20925, 1), + (20928, 1), + (21045, 1), + (21047, 1), + (21083, 2), + (21126, 1), + (21165, 1), + (21201, 1), + (21202, 1), + (21276, 1), + (21315, 1), + (21357, 1), + (21399, 2), + (21439, 1), + (21476, 1), + (21510, 1), + (21513, 1), + (21550, 1), + (21551, 1), + (21593, 1), + (21633, 1), + (21665, 1), + (21666, 1), + (21669, 1), + (21751, 1), + (21826, 1), + (21921, 1), + (21939, 1), + (21943, 1), + (21977, 1), + (21980, 2), + (21981, 1), + (22017, 1), + (22018, 1), + (22133, 1), + (22134, 1), + (22135, 2), + (22172, 1), + (22211, 1), + (22212, 1), + (22213, 1), + (22251, 1), + (22254, 1), + (22256, 1), + (22290, 1), + (22371, 1), + (22406, 1), + (22408, 1), + (22410, 1), + (22451, 1), + (22485, 1), + (22486, 2), + (22525, 1), + (22526, 1), + (22562, 1), + (22563, 3), + (22564, 1), + (22607, 1), + (22644, 1), + (22680, 1), + (22758, 1), + (22759, 1), + (22798, 2), + (22837, 2), + (22838, 1), + (22875, 1), + (22877, 1), + (22914, 1), + (22916, 1), + (22918, 1), + (22993, 1), + (23031, 1), + (23033, 2), + (23070, 1), + (23109, 1), + (23111, 1), + (23148, 1), + (23151, 1), + (23188, 1), + (23189, 1), + (23226, 1), + (23227, 1), + (23304, 1), + (23305, 1), + (23381, 5), + (23384, 2), + (23388, 1), + (23424, 1), + (23462, 1), + (23498, 1), + (23542, 1), + (23579, 1), + (23580, 1), + (23654, 1), + (23657, 1), + (23820, 1), + (24019, 7), + (24047, 1), + (24204, 1), + (24390, 1), + (27166, 6), + (31645, 5), + (37476, 6), + (50442, 1), + (66530, 1), + (236741, 1), + (266960, 1), + (410116, 1), + (452279, 1), + (521150, 1), + (531415, 1), + (531469, 1), + (533889, 1), + (534391, 1), + (537072, 1), + (537491, 1), + (546820, 1), + (554056, 1), + (562513, 1), + (570304, 1), + (571882, 1), + (580008, 1), + (582755, 1), + (586561, 1), + (589436, 1), + (593061, 2), + (618859, 1), + (619082, 1), + (625907, 1), + (633533, 1), + (644603, 1), + (646180, 1), + (655481, 1), + (693987, 1), + (701633, 1), + (728784, 1), + (745886, 1), + (752140, 1), + (771376, 1), + (848764, 1), + (902834, 1), + (952321, 1), + (964030, 1), + (974008, 1), + (977740, 1), + (992978, 1), + (1019553, 1), + (1057259, 1), + (1094674, 1), + (1105518, 1), + (1116659, 1), + (1121314, 1), + (1135487, 1), + (1151345, 1), + (1173415, 1), + (1189567, 1), + (1238079, 1), + (1282021, 1), + (1290980, 1), + (1293007, 1), + (1318405, 1), + (1328926, 1), + (1338999, 1), + (1373382, 1), + (1402596, 1), + (1422519, 1), + (1446480, 1), + (1460046, 1), + (1475924, 1), + (1478227, 1), + (1482046, 1), + (1597051, 1), +]; From 5353e8383fdc8943dfc5eef16b9a2303c9a51999 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 24 May 2023 13:47:07 +0100 Subject: [PATCH 03/53] Implement get_root and get_node --- src/column.rs | 41 ++++++++++++++++++++++++++++++++++++++++- src/db.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/column.rs b/src/column.rs index e112c8cd..97c44f77 100644 --- a/src/column.rs +++ b/src/column.rs @@ -9,7 +9,7 @@ use crate::{ error::{try_io, Error, Result}, index::{Address, IndexTable, PlanOutcome, TableId as IndexTableId}, log::{Log, LogAction, LogOverlays, LogQuery, LogReader, LogWriter}, - multitree::{NewNode, NodeAddress, NodeRef}, + multitree::{Children, NewNode, NodeAddress, NodeRef}, options::{ColumnOptions, Metadata, Options, DEFAULT_COMPRESSION_THRESHOLD}, parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, stats::{ColumnStatSummary, ColumnStats}, @@ -227,6 +227,23 @@ impl HashColumn { self.get(key, log).map(|v| v.map(|v| v.len() as u32)) } + pub fn get_value(&self, address: Address, log: &impl LogQuery) -> Result> { + let tables = self.tables.read(); + let values = self.as_ref(&tables.value); + if let Some((tier, value)) = + Column::get_value(TableKeyQuery::Check(&TableKey::NoHash), address, values, log)? + { + if self.collect_stats { + self.stats.query_hit(tier); + } + return Ok(Some(value)) + } + if self.collect_stats { + self.stats.query_miss(); + } + Ok(None) + } + fn get_in_index( &self, key: &Key, @@ -710,6 +727,28 @@ impl HashColumn { [vec![num_children], data, child_data].concat() } + pub fn unpack_node_data(&self, data: Vec) -> Result<(Vec, Children)> { + if data.len() == 0 { + return Err(Error::InvalidValueData) + } + let num_children = data[0] as usize; + let (_, data) = data.split_at(1); + let child_buf_len = num_children * 8; + if data.len() < child_buf_len { + return Err(Error::InvalidValueData) + } + let (data, child_buf) = data.split_at(data.len() - child_buf_len); + + let mut children = Children::new(); + for i in 0..num_children { + let node_address = + u64::from_le_bytes(child_buf[i * 8..(i + 1) * 8].try_into().unwrap()); + children.push(node_address); + } + + Ok((data.to_vec(), children)) + } + pub fn write_insert_tree_plan_immediate( &self, change: Operation, diff --git a/src/db.rs b/src/db.rs index 38208a48..fa11ea33 100644 --- a/src/db.rs +++ b/src/db.rs @@ -23,9 +23,9 @@ use crate::{ column::{hash_key, ColId, Column, IterState, ReindexBatch, ValueIterState}, error::{try_io, Error, Result}, hash::IdentityBuildHasher, - index::PlanOutcome, + index::{Address, PlanOutcome}, log::{Log, LogAction}, - multitree::NewNode, + multitree::{Children, NewNode, NodeAddress}, options::{Options, CURRENT_VERSION}, parking_lot::{Condvar, Mutex, RwLock}, stats::StatSummary, @@ -290,6 +290,37 @@ impl DbInner { } } + fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { + match &self.columns[col as usize] { + Column::Hash(column) => { + let value = self.get(col, key)?; + if let Some(data) = value { + return Ok(Some(column.unpack_node_data(data)?)) + } + Ok(None) + }, + Column::Tree(_) => Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), + } + } + + fn get_node( + &self, + col: ColId, + node_address: NodeAddress, + ) -> Result, Children)>> { + match &self.columns[col as usize] { + Column::Hash(column) => { + let log = self.log.overlays(); + let value = column.get_value(Address::from_u64(node_address), log)?; + if let Some(data) = value { + return Ok(Some(column.unpack_node_data(data)?)) + } + Ok(None) + }, + Column::Tree(_) => Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), + } + } + fn btree_iter(&self, col: ColId) -> Result { match &self.columns[col as usize] { Column::Hash(_column) => @@ -1019,6 +1050,18 @@ impl Db { self.inner.btree_iter(col) } + pub fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { + self.inner.get_root(col, key) + } + + pub fn get_node( + &self, + col: ColId, + node_address: NodeAddress, + ) -> Result, Children)>> { + self.inner.get_node(col, node_address) + } + /// Commit a set of changes to the database. pub fn commit(&self, tx: I) -> Result<()> where From 05367c25fd75faabbfdef3574d47d007d61fa3f0 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 24 May 2023 14:37:28 +0100 Subject: [PATCH 04/53] Initial work on readers --- admin/src/multitree_bench/mod.rs | 35 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index f85b1b59..4f697a19 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -258,16 +258,35 @@ fn writer( } fn reader( - _db: Arc, - _args: Arc, - _chain_generator: Arc, - _index: u64, + db: Arc, + args: Arc, + chain_generator: Arc, + index: u64, shutdown: Arc, ) { - // Query random keys while writing - /* let seed = args.seed.unwrap_or(0); - let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + index); */ - while !shutdown.load(Ordering::Relaxed) {} + // Query random values while writing + let offset = args.seed.unwrap_or(0); + let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); + + while !shutdown.load(Ordering::Relaxed) { + let commits = COMMITS.load(Ordering::Relaxed) as u64; + if commits == 0 { + continue + } + + let root_seed = rng.next_u64() % commits + offset; + + let (generated_node_data, generated_children) = chain_generator.generate_node(root_seed, 0); + + let key = chain_generator.key(root_seed); + match db.get_root(0, &key).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(generated_node_data, db_node_data); + }, + None => { + }, + } + } } fn iter(_db: Arc, shutdown: Arc) { From ccb01550ac72744c57ffbd6d6442ffc755750a9c Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Sat, 27 May 2023 00:41:02 +0100 Subject: [PATCH 05/53] Working readers --- admin/src/multitree_bench/mod.rs | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 4f697a19..f2c730a3 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -20,6 +20,8 @@ use std::{ static COMMITS: AtomicUsize = AtomicUsize::new(0); static NEXT_COMMIT: AtomicUsize = AtomicUsize::new(0); +static QUERIES: AtomicUsize = AtomicUsize::new(0); +static ITERATIONS: AtomicUsize = AtomicUsize::new(0); /// Stress tests (warning erase db first). #[derive(Debug, clap::Parser)] @@ -275,15 +277,45 @@ fn reader( } let root_seed = rng.next_u64() % commits + offset; + let mut depth = 0; - let (generated_node_data, generated_children) = chain_generator.generate_node(root_seed, 0); + let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); let key = chain_generator.key(root_seed); match db.get_root(0, &key).unwrap() { Some((db_node_data, db_children)) => { - assert_eq!(generated_node_data, db_node_data); + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + let mut generated_children = gen_children; + let mut database_children = db_children; + + while generated_children.len() > 0 { + let child_index = rng.next_u64() % generated_children.len() as u64; + let child_seed = generated_children[child_index as usize]; + let child_address = database_children[child_index as usize]; + depth += 1; + + let (gen_node_data, gen_children) = + chain_generator.generate_node(child_seed, depth); + match db.get_node(0, child_address).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + generated_children = gen_children; + database_children = db_children; + }, + None => { + assert!(false); + }, + } + } + + QUERIES.fetch_add(1, Ordering::SeqCst); }, None => { + assert!(false); }, } } @@ -373,5 +405,15 @@ pub fn run_internal(args: Args, db: Db) { let commits = commits - start_commit; let elapsed_time = start_time.elapsed().as_secs_f64(); - println!("Completed {} commits in {} seconds.", commits, elapsed_time); + let queries = QUERIES.load(Ordering::SeqCst); + let iterations = ITERATIONS.load(Ordering::SeqCst); + + println!( + "Completed {} commits in {} seconds. {} cps. {} queries, {} iterations", + commits, + elapsed_time, + commits as f64 / elapsed_time, + queries, + iterations + ); } From 27c3d06d59666f8962c04c8a19d34f2498de8e3d Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Mon, 29 May 2023 13:31:16 +0100 Subject: [PATCH 06/53] Working iterator --- admin/src/multitree_bench/mod.rs | 86 ++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index f2c730a3..70e64d97 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -266,7 +266,7 @@ fn reader( index: u64, shutdown: Arc, ) { - // Query random values while writing + // Query random values from random trees while writing let offset = args.seed.unwrap_or(0); let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); @@ -321,8 +321,81 @@ fn reader( } } -fn iter(_db: Arc, shutdown: Arc) { - while !shutdown.load(Ordering::Relaxed) {} +fn iter_children( + depth: u32, + generated_children: &mut Vec, + database_children: &mut Vec, + db: &Db, + chain_generator: &ChainGenerator, +) { + for i in 0..generated_children.len() { + let child_index = i; + let child_seed = generated_children[child_index as usize]; + let child_address = database_children[child_index as usize]; + + let (gen_node_data, mut gen_children) = + chain_generator.generate_node(child_seed, depth + 1); + match db.get_node(0, child_address).unwrap() { + Some((db_node_data, mut db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + iter_children(depth + 1, &mut gen_children, &mut db_children, db, chain_generator); + }, + None => { + assert!(false); + }, + } + } +} + +fn iter( + db: Arc, + args: Arc, + chain_generator: Arc, + index: u64, + shutdown: Arc, +) { + // Iterate over nodes in random trees while writing + let offset = args.seed.unwrap_or(0); + let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); + + while !shutdown.load(Ordering::Relaxed) { + let commits = COMMITS.load(Ordering::Relaxed) as u64; + if commits == 0 { + continue + } + + let root_seed = rng.next_u64() % commits + offset; + let depth = 0; + + let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); + + let key = chain_generator.key(root_seed); + match db.get_root(0, &key).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + // Iterate over all children recursively in depth first order. + let mut generated_children = gen_children; + let mut database_children = db_children; + + iter_children( + depth, + &mut generated_children, + &mut database_children, + &db, + &chain_generator, + ); + + ITERATIONS.fetch_add(1, Ordering::SeqCst); + }, + None => { + assert!(false); + }, + } + } } pub fn run_internal(args: Args, db: Db) { @@ -366,14 +439,19 @@ pub fn run_internal(args: Args, db: Db) { ); } + let iter_start_index = args.readers; for i in 0..args.iter { let db = db.clone(); let shutdown = shutdown.clone(); + let args = args.clone(); + let chain_generator = chain_generator.clone(); threads.push( thread::Builder::new() .name(format!("iter {i}")) - .spawn(move || iter(db, shutdown)) + .spawn(move || { + iter(db, args, chain_generator, (iter_start_index + i) as u64, shutdown) + }) .unwrap(), ); } From a479ce1fe5001c5e5305c9df56d64492eb6f9ade Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Sun, 18 Jun 2023 11:48:01 +0100 Subject: [PATCH 07/53] Added TreeReader for accessing tree root and nodes --- admin/src/multitree_bench/mod.rs | 120 ++++++++++++++++++------------- src/column.rs | 55 +++++++------- src/db.rs | 118 +++++++++++++++++++++++++----- src/lib.rs | 2 +- 4 files changed, 198 insertions(+), 97 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 70e64d97..254aa3d5 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -5,7 +5,7 @@ use super::*; mod data; -pub use parity_db::{CompressionType, Db, Key, Value}; +pub use parity_db::{CompressionType, Db, Key, TreeReader, Value}; use parity_db::{NewNode, NodeRef, Operation}; use rand::{RngCore, SeedableRng}; @@ -282,37 +282,42 @@ fn reader( let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); let key = chain_generator.key(root_seed); - match db.get_root(0, &key).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - let mut generated_children = gen_children; - let mut database_children = db_children; - - while generated_children.len() > 0 { - let child_index = rng.next_u64() % generated_children.len() as u64; - let child_seed = generated_children[child_index as usize]; - let child_address = database_children[child_index as usize]; - depth += 1; - - let (gen_node_data, gen_children) = - chain_generator.generate_node(child_seed, depth); - match db.get_node(0, child_address).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - generated_children = gen_children; - database_children = db_children; - }, - None => { - assert!(false); - }, + match db.get_tree(0, &key).unwrap() { + Some(reader) => match reader.get_root().unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + let mut generated_children = gen_children; + let mut database_children = db_children; + + while generated_children.len() > 0 { + let child_index = rng.next_u64() % generated_children.len() as u64; + let child_seed = generated_children[child_index as usize]; + let child_address = database_children[child_index as usize]; + depth += 1; + + let (gen_node_data, gen_children) = + chain_generator.generate_node(child_seed, depth); + match reader.get_node(child_address).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + generated_children = gen_children; + database_children = db_children; + }, + None => { + assert!(false); + }, + } } - } - QUERIES.fetch_add(1, Ordering::SeqCst); + QUERIES.fetch_add(1, Ordering::SeqCst); + }, + None => { + assert!(false); + }, }, None => { assert!(false); @@ -325,7 +330,7 @@ fn iter_children( depth: u32, generated_children: &mut Vec, database_children: &mut Vec, - db: &Db, + reader: &Arc, chain_generator: &ChainGenerator, ) { for i in 0..generated_children.len() { @@ -335,12 +340,18 @@ fn iter_children( let (gen_node_data, mut gen_children) = chain_generator.generate_node(child_seed, depth + 1); - match db.get_node(0, child_address).unwrap() { + match reader.get_node(child_address).unwrap() { Some((db_node_data, mut db_children)) => { assert_eq!(gen_node_data, db_node_data); assert_eq!(gen_children.len(), db_children.len()); - iter_children(depth + 1, &mut gen_children, &mut db_children, db, chain_generator); + iter_children( + depth + 1, + &mut gen_children, + &mut db_children, + reader, + chain_generator, + ); }, None => { assert!(false); @@ -372,24 +383,31 @@ fn iter( let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); let key = chain_generator.key(root_seed); - match db.get_root(0, &key).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - // Iterate over all children recursively in depth first order. - let mut generated_children = gen_children; - let mut database_children = db_children; - - iter_children( - depth, - &mut generated_children, - &mut database_children, - &db, - &chain_generator, - ); - - ITERATIONS.fetch_add(1, Ordering::SeqCst); + match db.get_tree(0, &key).unwrap() { + Some(reader) => { + match reader.get_root().unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + // Iterate over all children recursively in depth first order. + let mut generated_children = gen_children; + let mut database_children = db_children; + + iter_children( + depth, + &mut generated_children, + &mut database_children, + &reader, + &chain_generator, + ); + + ITERATIONS.fetch_add(1, Ordering::SeqCst); + }, + None => { + assert!(false); + }, + } }, None => { assert!(false); diff --git a/src/column.rs b/src/column.rs index 97c44f77..3eb71836 100644 --- a/src/column.rs +++ b/src/column.rs @@ -379,6 +379,31 @@ impl Column { } } +pub fn pack_node_data(data: Vec, child_data: Vec, num_children: u8) -> Vec { + [vec![num_children], data, child_data].concat() +} + +pub fn unpack_node_data(data: Vec) -> Result<(Vec, Children)> { + if data.len() == 0 { + return Err(Error::InvalidValueData) + } + let num_children = data[0] as usize; + let (_, data) = data.split_at(1); + let child_buf_len = num_children * 8; + if data.len() < child_buf_len { + return Err(Error::InvalidValueData) + } + let (data, child_buf) = data.split_at(data.len() - child_buf_len); + + let mut children = Children::new(); + for i in 0..num_children { + let node_address = u64::from_le_bytes(child_buf[i * 8..(i + 1) * 8].try_into().unwrap()); + children.push(node_address); + } + + Ok((data.to_vec(), children)) +} + impl HashColumn { fn open( col: ColId, @@ -709,7 +734,7 @@ impl HashColumn { writer: &mut LogWriter, ) -> Result { let num_children = node.children.len(); - let data = self.pack_node_data( + let data = pack_node_data( node.data, self.write_children(node.children, tables, writer)?, num_children as u8, @@ -723,32 +748,6 @@ impl HashColumn { Ok(address.as_u64()) } - fn pack_node_data(&self, data: Vec, child_data: Vec, num_children: u8) -> Vec { - [vec![num_children], data, child_data].concat() - } - - pub fn unpack_node_data(&self, data: Vec) -> Result<(Vec, Children)> { - if data.len() == 0 { - return Err(Error::InvalidValueData) - } - let num_children = data[0] as usize; - let (_, data) = data.split_at(1); - let child_buf_len = num_children * 8; - if data.len() < child_buf_len { - return Err(Error::InvalidValueData) - } - let (data, child_buf) = data.split_at(data.len() - child_buf_len); - - let mut children = Children::new(); - for i in 0..num_children { - let node_address = - u64::from_le_bytes(child_buf[i * 8..(i + 1) * 8].try_into().unwrap()); - children.push(node_address); - } - - Ok((data.to_vec(), children)) - } - pub fn write_insert_tree_plan_immediate( &self, change: Operation, @@ -761,7 +760,7 @@ impl HashColumn { let tables = self.tables.upgradable_read(); let num_children = node.children.len(); - let data = self.pack_node_data( + let data = pack_node_data( node.data, self.write_children(node.children, self.as_ref(&tables.value), &mut writer)?, num_children as u8, diff --git a/src/db.rs b/src/db.rs index fa11ea33..88823166 100644 --- a/src/db.rs +++ b/src/db.rs @@ -20,14 +20,14 @@ use crate::{ btree::{commit_overlay::BTreeChangeSet, BTreeIterator, BTreeTable}, - column::{hash_key, ColId, Column, IterState, ReindexBatch, ValueIterState}, + column::{hash_key, unpack_node_data, ColId, Column, IterState, ReindexBatch, ValueIterState}, error::{try_io, Error, Result}, hash::IdentityBuildHasher, index::{Address, PlanOutcome}, log::{Log, LogAction}, multitree::{Children, NewNode, NodeAddress}, options::{Options, CURRENT_VERSION}, - parking_lot::{Condvar, Mutex, RwLock}, + parking_lot::{Condvar, Mutex, RwLock, RwLockUpgradableReadGuard}, stats::StatSummary, ColumnOptions, Key, }; @@ -38,7 +38,7 @@ use std::{ ops::Bound, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, - Arc, + Arc, Weak, }, thread, }; @@ -131,6 +131,11 @@ struct CommitQueue { commits: VecDeque, } +#[derive(Debug)] +struct Trees { + readers: HashMap, IdentityBuildHasher>, +} + #[derive(Debug)] struct DbInner { columns: Vec, @@ -144,6 +149,7 @@ struct DbInner { commit_worker_wait: Arc>, // Overlay of most recent values in the commit queue. commit_overlay: RwLock>, + trees: RwLock>, // This may underflow occasionally, but is bound for 0 eventually. log_queue_wait: WaitCondvar, flush_worker_wait: Arc>, @@ -228,6 +234,7 @@ impl DbInner { log_worker_wait: WaitCondvar::new(), commit_worker_wait: Arc::new(WaitCondvar::new()), commit_overlay: RwLock::new(commit_overlay), + trees: RwLock::new(Default::default()), log_queue_wait: WaitCondvar::new(), flush_worker_wait: Arc::new(WaitCondvar::new()), cleanup_worker_wait: WaitCondvar::new(), @@ -290,18 +297,18 @@ impl DbInner { } } - fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { + /* fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { match &self.columns[col as usize] { Column::Hash(column) => { let value = self.get(col, key)?; if let Some(data) = value { - return Ok(Some(column.unpack_node_data(data)?)) + return Ok(Some(unpack_node_data(data)?)) } Ok(None) }, Column::Tree(_) => Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), } - } + } */ fn get_node( &self, @@ -313,7 +320,7 @@ impl DbInner { let log = self.log.overlays(); let value = column.get_value(Address::from_u64(node_address), log)?; if let Some(data) = value { - return Ok(Some(column.unpack_node_data(data)?)) + return Ok(Some(unpack_node_data(data)?)) } Ok(None) }, @@ -321,6 +328,49 @@ impl DbInner { } } + fn get_tree( + &self, + db: &Arc, + col: ColId, + key: &[u8], + ) -> Result>> { + match &self.columns[col as usize] { + Column::Hash(column) => { + let key = column.hash_key(key); + + let trees = self.trees.upgradable_read(); + + if let Some(column_trees) = trees.get(&col) { + if let Some(reader) = column_trees.readers.get(&key) { + if let Some(reader) = reader.upgrade() { + return Ok(Some(reader)) + } + } + } + + // Does the tree actually exist? + /* let value = self.get(col, key)?; + if let Some(data) = value { + return Ok(Some(unpack_node_data(data)?)) + } */ + + // Didn't manage to use an existing TreeReader so will need to change trees, hence + // upgrade lock. + let mut trees = RwLockUpgradableReadGuard::upgrade(trees); + + let column_trees = + trees.entry(col).or_insert_with(|| Trees { readers: Default::default() }); + let reader = Arc::new(TreeReader { db: db.clone(), col, key }); + column_trees.readers.insert(key, Arc::downgrade(&reader)); + + //RwLockWriteGuard::downgrade_to_upgradable(trees); + + Ok(Some(reader)) + }, + Column::Tree(_) => Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), + } + } + fn btree_iter(&self, col: ColId) -> Result { match &self.columns[col as usize] { Column::Hash(_column) => @@ -1050,16 +1100,8 @@ impl Db { self.inner.btree_iter(col) } - pub fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { - self.inner.get_root(col, key) - } - - pub fn get_node( - &self, - col: ColId, - node_address: NodeAddress, - ) -> Result, Children)>> { - self.inner.get_node(col, node_address) + pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>> { + self.inner.get_tree(&self.inner, col, key) } /// Commit a set of changes to the database. @@ -1325,6 +1367,48 @@ impl Db { } } +pub struct TreeReader { + db: Arc, + col: ColId, + key: Key, +} + +impl TreeReader { + pub fn get_root(&self) -> Result, Children)>> { + /* let value = self.db.get(self.col, &self.key)?; + if let Some(data) = value { + return unpack_node_data(data).map(|x| Some(x)) + } + Err(Error::InvalidValueData) */ + + match &self.db.columns[self.col as usize] { + Column::Hash(column) => { + let overlay = self.db.commit_overlay.read(); + // Check commit overlay first + let value = if let Some(v) = + overlay.get(self.col as usize).and_then(|o| o.get(&self.key)) + { + Ok(v.map(|i| i.value().clone())) + } else { + // Go into tables and log overlay. + let log = self.db.log.overlays(); + column.get(&self.key, log) + }?; + + if let Some(data) = value { + return unpack_node_data(data).map(|x| Some(x)) + } + }, + Column::Tree(..) => {}, + }; + Err(Error::InvalidValueData) + } + + pub fn get_node(&self, node_address: NodeAddress) -> Result, Children)>> { + self.db.get_node(self.col, node_address) + } +} + pub type IndexedCommitOverlay = HashMap), IdentityBuildHasher>; pub type BTreeCommitOverlay = BTreeMap)>; diff --git a/src/lib.rs b/src/lib.rs index cfcc475d..cb9f06a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ mod table; pub use btree::BTreeIterator; pub use column::{ColId, ValueIterState}; pub use compress::CompressionType; -pub use db::{check::CheckOptions, Db, Operation, Value}; +pub use db::{check::CheckOptions, Db, Operation, TreeReader, Value}; #[cfg(feature = "instrumentation")] pub use error::set_number_of_allowed_io_operations; pub use error::{Error, Result}; From d4afd3e55700867cd320105c2fbed8fbe0c9e91d Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 20 Jun 2023 18:11:56 +0100 Subject: [PATCH 08/53] get_tree returns RwLock reader --- admin/Cargo.toml | 1 + admin/src/multitree_bench/mod.rs | 76 +++++++++++++++++--------------- src/db.rs | 28 +++++------- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/admin/Cargo.toml b/admin/Cargo.toml index cae2c8b8..9acc18ed 100644 --- a/admin/Cargo.toml +++ b/admin/Cargo.toml @@ -11,6 +11,7 @@ env_logger = "0.10.0" fdlimit = "0.2.1" log = "0.4.8" parity-db = { path = ".." } +parking_lot = "0.12.0" rand = { version = "0.8.5", features = ["small_rng"] } blake2 = "0.10.4" diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 254aa3d5..708cf900 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -8,6 +8,8 @@ mod data; pub use parity_db::{CompressionType, Db, Key, TreeReader, Value}; use parity_db::{NewNode, NodeRef, Operation}; +use parking_lot::RwLockReadGuard; + use rand::{RngCore, SeedableRng}; use std::{ collections::BTreeMap, @@ -283,41 +285,44 @@ fn reader( let key = chain_generator.key(root_seed); match db.get_tree(0, &key).unwrap() { - Some(reader) => match reader.get_root().unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - let mut generated_children = gen_children; - let mut database_children = db_children; - - while generated_children.len() > 0 { - let child_index = rng.next_u64() % generated_children.len() as u64; - let child_seed = generated_children[child_index as usize]; - let child_address = database_children[child_index as usize]; - depth += 1; - - let (gen_node_data, gen_children) = - chain_generator.generate_node(child_seed, depth); - match reader.get_node(child_address).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - generated_children = gen_children; - database_children = db_children; - }, - None => { - assert!(false); - }, + Some(reader) => { + let reader = reader.read(); + match reader.get_root().unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + let mut generated_children = gen_children; + let mut database_children = db_children; + + while generated_children.len() > 0 { + let child_index = rng.next_u64() % generated_children.len() as u64; + let child_seed = generated_children[child_index as usize]; + let child_address = database_children[child_index as usize]; + depth += 1; + + let (gen_node_data, gen_children) = + chain_generator.generate_node(child_seed, depth); + match reader.get_node(child_address).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + generated_children = gen_children; + database_children = db_children; + }, + None => { + assert!(false); + }, + } } - } - QUERIES.fetch_add(1, Ordering::SeqCst); - }, - None => { - assert!(false); - }, + QUERIES.fetch_add(1, Ordering::SeqCst); + }, + None => { + assert!(false); + }, + } }, None => { assert!(false); @@ -326,11 +331,11 @@ fn reader( } } -fn iter_children( +fn iter_children<'a>( depth: u32, generated_children: &mut Vec, database_children: &mut Vec, - reader: &Arc, + reader: &RwLockReadGuard<'a, TreeReader>, chain_generator: &ChainGenerator, ) { for i in 0..generated_children.len() { @@ -385,6 +390,7 @@ fn iter( let key = chain_generator.key(root_seed); match db.get_tree(0, &key).unwrap() { Some(reader) => { + let reader = reader.read(); match reader.get_root().unwrap() { Some((db_node_data, db_children)) => { assert_eq!(gen_node_data, db_node_data); diff --git a/src/db.rs b/src/db.rs index 88823166..cf68d6cd 100644 --- a/src/db.rs +++ b/src/db.rs @@ -38,7 +38,7 @@ use std::{ ops::Bound, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, - Arc, Weak, + Arc, }, thread, }; @@ -133,7 +133,7 @@ struct CommitQueue { #[derive(Debug)] struct Trees { - readers: HashMap, IdentityBuildHasher>, + readers: HashMap>, IdentityBuildHasher>, } #[derive(Debug)] @@ -333,7 +333,7 @@ impl DbInner { db: &Arc, col: ColId, key: &[u8], - ) -> Result>> { + ) -> Result>>> { match &self.columns[col as usize] { Column::Hash(column) => { let key = column.hash_key(key); @@ -342,28 +342,21 @@ impl DbInner { if let Some(column_trees) = trees.get(&col) { if let Some(reader) = column_trees.readers.get(&key) { - if let Some(reader) = reader.upgrade() { - return Ok(Some(reader)) - } + let reader = reader.clone(); + return Ok(Some(reader)) } } - // Does the tree actually exist? - /* let value = self.get(col, key)?; - if let Some(data) = value { - return Ok(Some(unpack_node_data(data)?)) - } */ + // TODO: Check if the tree actually exists - // Didn't manage to use an existing TreeReader so will need to change trees, hence - // upgrade lock. let mut trees = RwLockUpgradableReadGuard::upgrade(trees); let column_trees = trees.entry(col).or_insert_with(|| Trees { readers: Default::default() }); - let reader = Arc::new(TreeReader { db: db.clone(), col, key }); - column_trees.readers.insert(key, Arc::downgrade(&reader)); - //RwLockWriteGuard::downgrade_to_upgradable(trees); + let reader = Arc::new(RwLock::new(TreeReader { db: db.clone(), col, key })); + + column_trees.readers.insert(key, reader.clone()); Ok(Some(reader)) }, @@ -1100,7 +1093,7 @@ impl Db { self.inner.btree_iter(col) } - pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>> { + pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>>> { self.inner.get_tree(&self.inner, col, key) } @@ -1367,6 +1360,7 @@ impl Db { } } +#[derive(Debug)] pub struct TreeReader { db: Arc, col: ColId, From f8d825c6f6faabb1c13470f8b56b107054e549b8 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 21 Jun 2023 11:26:16 +0100 Subject: [PATCH 09/53] Track ValueTable free entries in memory --- src/table.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/table.rs b/src/table.rs index f81113cc..fc2340fe 100644 --- a/src/table.rs +++ b/src/table.rs @@ -54,6 +54,7 @@ use crate::{ table::key::{TableKey, TableKeyQuery, PARTIAL_SIZE}, }; use std::{ + collections::BTreeSet, convert::TryInto, io::Read, mem::MaybeUninit, @@ -125,6 +126,12 @@ impl std::fmt::Display for TableId { } } +#[derive(Debug)] +struct FreeEntries { + stack: Vec, + ordered: BTreeSet, +} + #[derive(Debug)] pub struct ValueTable { pub id: TableId, @@ -133,6 +140,7 @@ pub struct ValueTable { filled: AtomicU64, last_removed: AtomicU64, dirty_header: AtomicBool, + free_entries: Option>, multipart: bool, ref_counted: bool, db_version: u32, @@ -403,6 +411,33 @@ impl ValueTable { log::debug!(target: "parity-db", "Opened value table {} with {} entries, entry_size={}, removed={}", id, filled, entry_size, last_removed); } + let free_entries = if options.multitree { + let mut stack: Vec = Default::default(); + let mut ordered: BTreeSet = Default::default(); + + let mut next = last_removed; + while next != 0 { + if next >= filled { + return Err(crate::error::Error::Corruption(format!( + "Bad removed ref {} out of {}", + next, filled + ))) + } + + stack.insert(0, next); + ordered.insert(next); + + let mut buf = PartialEntry::new_uninit(); + file.read_at(buf.as_mut(), next * entry_size as u64)?; + buf.skip_size(); + next = buf.read_next(); + } + + Some(RwLock::new(FreeEntries { stack, ordered })) + } else { + None + }; + Ok(ValueTable { id, entry_size, @@ -410,6 +445,7 @@ impl ValueTable { filled: AtomicU64::new(filled), last_removed: AtomicU64::new(last_removed), dirty_header: AtomicBool::new(false), + free_entries, multipart, ref_counted: options.ref_counted, db_version, @@ -675,6 +711,12 @@ impl ValueTable { last_removed, ); self.last_removed.store(next_removed, Ordering::Relaxed); + if let Some(free_entries) = &self.free_entries { + let mut free_entries = free_entries.write(); + let last = free_entries.stack.pop().unwrap(); + assert_eq!(last, last_removed); + free_entries.ordered.remove(&last_removed); + } last_removed } else { log::trace!( @@ -690,6 +732,40 @@ impl ValueTable { Ok(index) } + pub fn claim_next_free(&self) -> Result { + match &self.free_entries { + Some(free_entries) => { + let filled = self.filled.load(Ordering::Relaxed); + let last_removed = self.last_removed.load(Ordering::Relaxed); + let index = if last_removed != 0 { + let mut free_entries = free_entries.write(); + + let last = free_entries.stack.pop().unwrap(); + assert_eq!(last, last_removed); + free_entries.ordered.remove(&last_removed); + + let next_removed = *free_entries.stack.last().unwrap_or(&0u64); + + self.last_removed.store(next_removed, Ordering::Relaxed); + last_removed + } else { + self.filled.store(filled + 1, Ordering::Relaxed); + filled + }; + self.dirty_header.store(true, Ordering::Relaxed); + Ok(index) + }, + None => + return Err(crate::error::Error::InvalidConfiguration(format!( + "claim_next_free called without free_entries" + ))), + } + } + + pub fn claim_contiguous_entries(&self, num: u64, min_span_length: u64) -> Vec { + Vec::new() + } + fn overwrite_chain( &self, key: &TableKey, @@ -807,6 +883,13 @@ impl ValueTable { log.insert_value(self.id, index, buf[0..buf.offset()].to_vec()); self.last_removed.store(index, Ordering::Relaxed); self.dirty_header.store(true, Ordering::Relaxed); + + if let Some(free_entries) = &self.free_entries { + let mut free_entries = free_entries.write(); + free_entries.stack.push(index); + free_entries.ordered.insert(index); + } + Ok(()) } From 5a50c1deebdae7ad838d8febcf3901b8cc0893a5 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 23 Jun 2023 17:02:03 +0100 Subject: [PATCH 10/53] Added ability to claim free entries from ValueTable. Used this to make tree insertion work with commit queue. --- admin/src/multitree_bench/mod.rs | 115 ++++++++++++++++++------------- src/column.rs | 96 +++++++++++++++++++------- src/db.rs | 77 ++++++++++++++++----- src/multitree.rs | 4 +- src/table.rs | 25 +++++-- 5 files changed, 218 insertions(+), 99 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 708cf900..f4c22be2 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -187,9 +187,14 @@ impl ChainGenerator { ) as usize; } let mut v = Vec::new(); + v.resize(size, 0); let fill = size; rng.fill_bytes(&mut v[..fill]); + /* // Purely random values as above result in compression never creating smaller values. Do the following to test compression. + // TODO: Better value generation that has random parts and also runs to allow compression to work. Then we can just use that for both cases. + let val = (rng.next_u64() & 256) as u8; + v.resize(size, val); */ (v, children_seeds) } @@ -229,6 +234,63 @@ fn num_new_child_nodes(node: &NodeRef) -> u32 { } } +fn read_value( + root_seed: u64, + rng: &mut rand::rngs::SmallRng, + db: &Db, + chain_generator: &ChainGenerator, +) { + let mut depth = 0; + + let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); + + let key = chain_generator.key(root_seed); + match db.get_tree(0, &key).unwrap() { + Some(reader) => { + let reader = reader.read(); + match reader.get_root().unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + let mut generated_children = gen_children; + let mut database_children = db_children; + + while generated_children.len() > 0 { + let child_index = rng.next_u64() % generated_children.len() as u64; + let child_seed = generated_children[child_index as usize]; + let child_address = database_children[child_index as usize]; + depth += 1; + + let (gen_node_data, gen_children) = + chain_generator.generate_node(child_seed, depth); + match reader.get_node(child_address).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + generated_children = gen_children; + database_children = db_children; + }, + None => { + assert!(false); + }, + } + } + + QUERIES.fetch_add(1, Ordering::SeqCst); + }, + None => { + assert!(false); + }, + } + }, + None => { + assert!(false); + }, + } +} + fn writer( db: Arc, args: Arc, @@ -257,6 +319,10 @@ fn writer( db.commit_changes(commit.drain(..)).unwrap(); COMMITS.fetch_add(1, Ordering::Relaxed); commit.clear(); + + // Immediately read and check a random value from the tree + let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + n as u64); + read_value(root_seed, &mut rng, &db, &chain_generator); } } } @@ -279,55 +345,8 @@ fn reader( } let root_seed = rng.next_u64() % commits + offset; - let mut depth = 0; - - let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); - - let key = chain_generator.key(root_seed); - match db.get_tree(0, &key).unwrap() { - Some(reader) => { - let reader = reader.read(); - match reader.get_root().unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - let mut generated_children = gen_children; - let mut database_children = db_children; - while generated_children.len() > 0 { - let child_index = rng.next_u64() % generated_children.len() as u64; - let child_seed = generated_children[child_index as usize]; - let child_address = database_children[child_index as usize]; - depth += 1; - - let (gen_node_data, gen_children) = - chain_generator.generate_node(child_seed, depth); - match reader.get_node(child_address).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); - assert_eq!(gen_children.len(), db_children.len()); - - generated_children = gen_children; - database_children = db_children; - }, - None => { - assert!(false); - }, - } - } - - QUERIES.fetch_add(1, Ordering::SeqCst); - }, - None => { - assert!(false); - }, - } - }, - None => { - assert!(false); - }, - } + read_value(root_seed, &mut rng, &db, &chain_generator); } } diff --git a/src/column.rs b/src/column.rs index 3eb71836..3951d2fa 100644 --- a/src/column.rs +++ b/src/column.rs @@ -4,7 +4,7 @@ use crate::{ btree::BTreeTable, compress::Compress, - db::{check::CheckDisplay, Operation, RcValue}, + db::{check::CheckDisplay, NodeChange, Operation, RcValue}, display::hex, error::{try_io, Error, Result}, index::{Address, IndexTable, PlanOutcome, TableId as IndexTableId}, @@ -708,16 +708,16 @@ impl HashColumn { Ok((outcome, tables, reindex)) } - fn write_children( + fn claim_children( &self, children: Vec, tables: TablesRef, - writer: &mut LogWriter, + node_values: &mut Vec, ) -> Result> { let mut data = Vec::new(); for child in children { let address = match child { - NodeRef::New(node) => self.write_node(node, tables, writer)?, + NodeRef::New(node) => self.claim_node(node, tables, node_values)?, NodeRef::Existing(address) => address, }; let mut data_buf = [0u8; 8]; @@ -727,51 +727,68 @@ impl HashColumn { Ok(data) } - fn write_node( + fn claim_node( &self, node: NewNode, tables: TablesRef, - writer: &mut LogWriter, + node_values: &mut Vec, ) -> Result { let num_children = node.children.len(); let data = pack_node_data( node.data, - self.write_children(node.children, tables, writer)?, + self.claim_children(node.children, tables, node_values)?, num_children as u8, ); - let stats = self.collect_stats.then_some(&self.stats); let table_key = TableKey::NoHash; - let address = - Column::write_new_value_plan(&table_key, tables, data.as_ref(), writer, stats)?; + + let (cval, target_tier) = + Column::compress(tables.compression, &table_key, data.as_ref(), tables.tables); + let (cval, compressed) = cval + .as_ref() + .map(|cval| (cval.as_slice(), true)) + .unwrap_or((data.as_ref(), false)); + + let cval: RcValue = cval.to_vec().into(); + let val = if compressed { data.into() } else { cval.clone() }; + + assert!( + (target_tier >= (SIZE_TIERS - 1)) || + cval.value().len() <= + tables.tables[target_tier].value_size(&table_key).unwrap() as usize + ); + + let offset = tables.tables[target_tier].claim_next_free()?; + let address = Address::new(offset, target_tier as u8); + + node_values.push(NodeChange { address: address.as_u64(), val, cval, compressed }); Ok(address.as_u64()) } - pub fn write_insert_tree_plan_immediate( + /// returns value for the root node and vector of NodeChange for nodes. + pub fn claim_tree_values( &self, - change: Operation, - log: &Log, - bytes: &mut u64, - ) -> Result, Vec>>> { + change: &Operation, + ) -> Result<(Vec, Vec)> { match change { - Operation::InsertTree(key, node) => { - let mut writer = log.begin_record(); + Operation::InsertTree(_key, node) => { let tables = self.tables.upgradable_read(); + let mut node_values: Vec = Default::default(); + let num_children = node.children.len(); let data = pack_node_data( - node.data, - self.write_children(node.children, self.as_ref(&tables.value), &mut writer)?, + node.data.clone(), + self.claim_children( + node.children.clone(), + self.as_ref(&tables.value), + &mut node_values, + )?, num_children as u8, ); - self.complete_plan(&mut writer)?; - - let l = writer.drain(); - *bytes += log.end_record(l)?; - - return Ok(Some(Operation::Set(key, data))) + return Ok((data, node_values)) }, Operation::RemoveTree(_key) => return Err(Error::InvalidInput(format!("RemoveTree not implemented yet"))), @@ -783,6 +800,35 @@ impl HashColumn { } } + pub fn write_address_value_plan( + &self, + address: u64, + cval: RcValue, + compressed: bool, + val_len: u32, + log: &mut LogWriter, + ) -> Result { + let tables = self.tables.upgradable_read(); + let tables = self.as_ref(&tables.value); + let address = Address::from_u64(address); + let target_tier = address.size_tier(); + let offset = address.offset(); + tables.tables[target_tier as usize].write_claimed_plan( + offset, + &TableKey::NoHash, + cval.as_ref(), + log, + compressed, + )?; + + let stats = self.collect_stats.then_some(&self.stats); + if let Some(stats) = stats { + stats.insert_val(val_len, cval.value().len() as u32); + } + + Ok(PlanOutcome::Written) + } + pub fn enact_plan(&self, action: LogAction, log: &mut LogReader) -> Result<()> { let tables = self.tables.read(); let reindex = self.reindex.read(); diff --git a/src/db.rs b/src/db.rs index cf68d6cd..eb9f727e 100644 --- a/src/db.rs +++ b/src/db.rs @@ -144,7 +144,6 @@ struct DbInner { log: Log, commit_queue: Mutex, commit_queue_full_cv: Condvar, - log_writer_mutex: Mutex, log_worker_wait: WaitCondvar, commit_worker_wait: Arc>, // Overlay of most recent values in the commit queue. @@ -230,7 +229,6 @@ impl DbInner { log, commit_queue: Mutex::new(Default::default()), commit_queue_full_cv: Condvar::new(), - log_writer_mutex: Mutex::new(false), log_worker_wait: WaitCondvar::new(), commit_worker_wait: Arc::new(WaitCondvar::new()), commit_overlay: RwLock::new(commit_overlay), @@ -317,6 +315,12 @@ impl DbInner { ) -> Result, Children)>> { match &self.columns[col as usize] { Column::Hash(column) => { + let overlay = self.commit_overlay.read(); + // Check commit overlay first + if let Some(v) = overlay.get(col as usize).and_then(|o| o.get_address(node_address)) + { + return Ok(Some(unpack_node_data(v.value().clone())?)) + } let log = self.log.overlays(); let value = column.get_value(Address::from_u64(node_address), log)?; if let Some(data) = value { @@ -406,30 +410,29 @@ impl DbInner { .or_insert_with(|| BTreeChangeSet::new(col)) .push(change)? } else if self.options.columns[col as usize].multitree { - let _log_writer = self.log_writer_mutex.lock(); - let mut bytes = 0; - + // TODO: Allow normal Operations as well? match &self.columns[col as usize] { Column::Hash(column) => { - if let Some(operation) = column - .write_insert_tree_plan_immediate(change, &self.log, &mut bytes)? - { + let (root_data, node_values) = column.claim_tree_values(&change)?; + + let root_operation = Operation::Set(change.key(), root_data); + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(root_operation, &self.options, self.db_version)?; + + for node_change in node_values { commit .indexed .entry(col) .or_insert_with(|| IndexedChangeSet::new(col)) - .push(operation, &self.options, self.db_version)? + .push_node_change(node_change); } }, Column::Tree(_) => return Err(Error::InvalidConfiguration("Not a HashColumn".to_string())), } - - if bytes > 0 { - let mut logged_bytes = self.log_queue_wait.work.lock(); - *logged_bytes += bytes as i64; - self.flush_worker_wait.signal(); - } } else { commit.indexed.entry(col).or_insert_with(|| IndexedChangeSet::new(col)).push( change, @@ -1404,22 +1407,28 @@ impl TreeReader { } pub type IndexedCommitOverlay = HashMap), IdentityBuildHasher>; +pub type AddressCommitOverlay = HashMap; pub type BTreeCommitOverlay = BTreeMap)>; #[derive(Debug)] pub struct CommitOverlay { indexed: IndexedCommitOverlay, + address: AddressCommitOverlay, btree_indexed: BTreeCommitOverlay, } impl CommitOverlay { fn new() -> Self { - CommitOverlay { indexed: Default::default(), btree_indexed: Default::default() } + CommitOverlay { + indexed: Default::default(), + address: Default::default(), + btree_indexed: Default::default(), + } } #[cfg(test)] fn is_empty(&self) -> bool { - self.indexed.is_empty() && self.btree_indexed.is_empty() + self.indexed.is_empty() && self.address.is_empty() && self.btree_indexed.is_empty() } } @@ -1436,6 +1445,10 @@ impl CommitOverlay { self.get_ref(key).map(|res| res.as_ref().map(|b| b.value().len() as u32)) } + fn get_address(&self, address: u64) -> Option { + self.address.get(&address).map(|(_, v)| v.clone()) + } + fn btree_get(&self, key: &[u8]) -> Option> { self.btree_indexed.get(key).map(|(_, v)| v.as_ref()) } @@ -1563,6 +1576,14 @@ impl, Value> Operation { } } +#[derive(Debug)] +pub struct NodeChange { + pub address: u64, + pub val: RcValue, + pub cval: RcValue, + pub compressed: bool, +} + #[derive(Debug, Default)] pub struct CommitChangeSet { pub indexed: HashMap, @@ -1573,11 +1594,12 @@ pub struct CommitChangeSet { pub struct IndexedChangeSet { pub col: ColId, pub changes: Vec>, + pub node_changes: Vec, } impl IndexedChangeSet { pub fn new(col: ColId) -> Self { - IndexedChangeSet { col, changes: Default::default() } + IndexedChangeSet { col, changes: Default::default(), node_changes: Default::default() } } fn push>( @@ -1609,6 +1631,10 @@ impl IndexedChangeSet { self.changes.push(change); } + fn push_node_change(&mut self, change: NodeChange) { + self.node_changes.push(change); + } + fn copy_to_overlay( &self, overlay: &mut CommitOverlay, @@ -1644,6 +1670,9 @@ impl IndexedChangeSet { ))), } } + for change in self.node_changes.iter() { + overlay.address.insert(change.address, (record_id, change.val.clone())); + } Ok(()) } @@ -1668,6 +1697,15 @@ impl IndexedChangeSet { } *ops += 1; } + for change in self.node_changes.iter() { + column.write_address_value_plan( + change.address, + change.cval.clone(), + change.compressed, + change.val.value().len() as u32, + writer, + )?; + } Ok(()) } @@ -1687,6 +1725,9 @@ impl IndexedChangeSet { Operation::RemoveTree(..) => (), } } + for change in self.node_changes.iter() { + overlay.address.remove(&change.address); + } } } diff --git a/src/multitree.rs b/src/multitree.rs index 79e6eb65..3d956e03 100644 --- a/src/multitree.rs +++ b/src/multitree.rs @@ -4,13 +4,13 @@ pub type NodeAddress = u64; pub type Children = Vec; -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum NodeRef { New(NewNode), Existing(NodeAddress), } -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct NewNode { pub data: Vec, pub children: Vec, diff --git a/src/table.rs b/src/table.rs index fc2340fe..a34dc2d1 100644 --- a/src/table.rs +++ b/src/table.rs @@ -762,9 +762,9 @@ impl ValueTable { } } - pub fn claim_contiguous_entries(&self, num: u64, min_span_length: u64) -> Vec { + /* pub fn claim_contiguous_entries(&self, num: u64, min_span_length: u64) -> Vec { Vec::new() - } + } */ fn overwrite_chain( &self, @@ -772,6 +772,7 @@ impl ValueTable { value: &[u8], log: &mut LogWriter, at: Option, + claimed: bool, compressed: bool, ) -> Result { let mut remainder = value.len() + self.ref_size() + key.encoded_size(); @@ -779,7 +780,7 @@ impl ValueTable { let mut start = 0; assert!(self.multipart || value.len() <= self.value_size(key).unwrap() as usize); let (mut index, mut follow) = match at { - Some(index) => (index, true), + Some(index) => (index, !claimed), None => (self.next_free(log)?, false), }; loop { @@ -900,7 +901,7 @@ impl ValueTable { log: &mut LogWriter, compressed: bool, ) -> Result { - self.overwrite_chain(key, value, log, None, compressed) + self.overwrite_chain(key, value, log, None, false, compressed) } pub fn write_replace_plan( @@ -911,7 +912,19 @@ impl ValueTable { log: &mut LogWriter, compressed: bool, ) -> Result<()> { - self.overwrite_chain(key, value, log, Some(index), compressed)?; + self.overwrite_chain(key, value, log, Some(index), false, compressed)?; + Ok(()) + } + + pub fn write_claimed_plan( + &self, + index: u64, + key: &TableKey, + value: &[u8], + log: &mut LogWriter, + compressed: bool, + ) -> Result<()> { + self.overwrite_chain(key, value, log, Some(index), true, compressed)?; Ok(()) } @@ -1133,7 +1146,7 @@ impl ValueTable { let empty_overlays = RwLock::new(Default::default()); let mut log = LogWriter::new(&empty_overlays, 0); - let at = self.overwrite_chain(&TableKey::NoHash, entry, &mut log, None, false)?; + let at = self.overwrite_chain(&TableKey::NoHash, entry, &mut log, None, false, false)?; self.complete_plan(&mut log)?; assert_eq!(at, 1); let log = log.drain(); From 902fa024878d7167dfd20c7a0e0ea1dd8d1e10fe Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 13 Jul 2023 17:48:03 +0100 Subject: [PATCH 11/53] Make ChainGenerator generate trees that share nodes from previous trees --- admin/Cargo.toml | 1 + admin/src/multitree_bench/data.rs | 20 ++ admin/src/multitree_bench/mod.rs | 362 +++++++++++++++++++++++------- 3 files changed, 298 insertions(+), 85 deletions(-) diff --git a/admin/Cargo.toml b/admin/Cargo.toml index 9acc18ed..3da7f3b3 100644 --- a/admin/Cargo.toml +++ b/admin/Cargo.toml @@ -14,6 +14,7 @@ parity-db = { path = ".." } parking_lot = "0.12.0" rand = { version = "0.8.5", features = ["small_rng"] } blake2 = "0.10.4" +siphasher = "0.3.10" [target.'cfg(not(target_env = "msvc"))'.dependencies] jemallocator = "0.5.0" diff --git a/admin/src/multitree_bench/data.rs b/admin/src/multitree_bench/data.rs index a45e4b82..2a7ba0d1 100644 --- a/admin/src/multitree_bench/data.rs +++ b/admin/src/multitree_bench/data.rs @@ -30,6 +30,26 @@ pub const DEPTH_CHILD_COUNT_HISTOGRAMS: &[(u32, [u32; 17])] = &[ (13, [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), ]; +// Test data (not collected from Polkadot). +pub const AGE_HISTOGRAM: &[(u32, u32)] = &[ + (0, 100), + (1, 10), + (2, 5), + (3, 4), + (4, 4), + (5, 3), + (6, 3), + (7, 3), + (8, 2), + (9, 2), + (10, 2), + (11, 2), + (12, 1), + (13, 1), + (14, 1), + (15, 1), +]; + pub const _KEY_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ (5, 1), (20, 1), diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index f4c22be2..d727818e 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -97,62 +97,93 @@ impl MultiTreeStress { } } -fn sample_histogram(rnd: u64, histogram: &BTreeMap, total: u32) -> u32 { - let sr = (rnd % total as u64) as u32; - let mut range = histogram.range((std::ops::Bound::Included(sr), std::ops::Bound::Unbounded)); - let size = *range.next().unwrap().1; - size +struct Histogram { + distribution: BTreeMap, + total: u32, +} + +impl Histogram { + fn new(histogram_data: &[(u32, u32)]) -> Histogram { + let mut distribution = BTreeMap::default(); + let mut total = 0; + for (size, count) in histogram_data { + total += count; + if *count > 0 { + distribution.insert(total, *size); + } + } + Histogram { distribution, total } + } + + fn sample(&self, rnd: u64) -> u32 { + let sr = (rnd % self.total as u64) as u32; + let mut range = self + .distribution + .range((std::ops::Bound::Included(sr), std::ops::Bound::Unbounded)); + let size = *range.next().unwrap().1; + size + } +} + +pub enum NodeSpec { + /// Direct specification of a node. (Tree index, depth, seed). + Direct(u64, u32, u64), + /// Node will be a path node but haven't done the work to generate the path yet. + UnresolvedPath(), + /// Path to another node. (Tree index, Path) where Path is a sequence of child indices starting + /// from the root of the tree. + Path(u64, Vec), } struct ChainGenerator { - depth_child_count_distribution: Vec>, - depth_child_count_total: Vec, - value_length_distribution: BTreeMap, - value_length_total: u32, + depth_child_count_histograms: Vec, + age_histogram: Histogram, + value_length_histogram: Histogram, + seed: u64, + compressable: bool, } impl ChainGenerator { fn new( depth_child_count_histogram: &[(u32, [u32; 17])], + age_histogram: &[(u32, u32)], value_length_histogram: &[(u32, u32)], + seed: u64, + compressable: bool, ) -> ChainGenerator { - let mut depth_child_count_distribution = Vec::default(); - let mut depth_child_count_total = Vec::default(); - for (depth, histogram) in depth_child_count_histogram { - assert_eq!(*depth, depth_child_count_distribution.len() as u32); - - let mut distribution = BTreeMap::default(); - let mut total = 0; - for i in 0..histogram.len() { - let size = i as u32; - let count = histogram[i]; - total += count; - if count > 0 { - distribution.insert(total, size); - } - } + let mut depth_child_count_histograms = Vec::default(); + for (depth, histogram_data) in depth_child_count_histogram { + assert_eq!(*depth, depth_child_count_histograms.len() as u32); - depth_child_count_distribution.push(distribution); - depth_child_count_total.push(total); - } + let data: Vec<(u32, u32)> = + histogram_data.iter().enumerate().map(|(a, b)| (a as u32, *b)).collect(); + let histogram = Histogram::new(data.as_slice()); - let mut value_length_distribution = BTreeMap::default(); - let mut value_length_total = 0; - for (size, count) in value_length_histogram { - value_length_total += count; - if *count > 0 { - value_length_distribution.insert(value_length_total, *size); - } + depth_child_count_histograms.push(histogram); } + let age_histogram = Histogram::new(age_histogram); + + let value_length_histogram = Histogram::new(value_length_histogram); + ChainGenerator { - depth_child_count_distribution, - depth_child_count_total, - value_length_distribution, - value_length_total, + depth_child_count_histograms, + age_histogram, + value_length_histogram, + seed, + compressable, } } + fn root_seed(&self, tree_index: u64) -> u64 { + use std::hash::Hasher; + let mut hasher = siphasher::sip::SipHasher24::new(); + hasher.write_u64(self.seed); + hasher.write_u64(tree_index); + let seed = hasher.finish(); + seed + } + fn key(&self, seed: u64) -> Key { let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); let mut key = Key::default(); @@ -160,43 +191,141 @@ impl ChainGenerator { key } - /// Returns tuple of node data and child seeds - fn generate_node(&self, seed: u64, depth: u32) -> (Vec, Vec) { + /// Returns tuple of node data and child specs. When only_direct_children is true node data will + /// be empty and non direct children will be NodeSpec::UnresolvedPath. + fn generate_node( + &self, + tree_index: u64, + depth: u32, + seed: u64, + only_direct_children: bool, + ) -> (Vec, Vec) { let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); - let num_children = if depth < self.depth_child_count_distribution.len() as u32 { - sample_histogram( - rng.next_u64(), - &self.depth_child_count_distribution[depth as usize], - self.depth_child_count_total[depth as usize], - ) + let num_children = if depth < self.depth_child_count_histograms.len() as u32 { + self.depth_child_count_histograms[depth as usize].sample(rng.next_u64()) } else { 0 }; - let mut children_seeds = Vec::default(); + let mut children = Vec::default(); + for _i in 0..num_children { - children_seeds.push(rng.next_u64()); + let age = self.age_histogram.sample(rng.next_u64()) as u64; + + let child_tree_index = if age > tree_index { tree_index } else { tree_index - age }; + + if child_tree_index == tree_index { + children.push(NodeSpec::Direct(tree_index, depth + 1, rng.next_u64())); + } else { + let path_seed = rng.next_u64(); + if only_direct_children { + children.push(NodeSpec::UnresolvedPath()); + } else { + // Generate path to node in child_tree_index + let mut path_rng = rand::rngs::SmallRng::seed_from_u64(path_seed); + let mut path = Vec::default(); + let mut path_node: Option = None; + + let target_depth = depth + 1; + + let mut other_tree_index = child_tree_index; + let mut other_depth = 0; + let mut other_seed = self.root_seed(child_tree_index); + while other_depth < target_depth { + let (_other_node_data, other_children) = + self.generate_node(other_tree_index, other_depth, other_seed, true); + + let mut direct_children = + other_children.iter().enumerate().filter(|(_, x)| { + if let NodeSpec::Direct(..) = x { + true + } else { + false + } + }); + let num_direct_children = direct_children.clone().count(); + + if num_direct_children == 0 { + break + } + + let child_index = path_rng.next_u64() % num_direct_children as u64; + + let child = direct_children.nth(child_index as usize).unwrap(); + if let NodeSpec::Direct(new_index, new_depth, new_seed) = child.1 { + path.push(child.0 as u32); + + // Chose a direct node so should be same tree, one depth down. + assert_eq!(*new_index, other_tree_index); + assert_eq!(*new_depth, other_depth + 1); + + other_tree_index = *new_index; + other_depth = *new_depth; + other_seed = *new_seed; + + if other_depth == target_depth { + path_node = Some(NodeSpec::Path(child_tree_index, path.clone())); + } + } else { + break + } + } + + match path_node { + Some(node) => { + children.push(node); + }, + None => { + // Unable to generate a path so just create a direct node. Use path_rng + // to ensure deterministic generation when using only_direct_children. + // TODO: This is not returned when only_direct_children is true even + // though it is a direct node. Is this ok? only_direct_children is only + // used when generating a path so it is ok if it doesn't see these + // nodes. + children.push(NodeSpec::Direct( + tree_index, + depth + 1, + path_rng.next_u64(), + )); + }, + } + } + } + } + + if only_direct_children { + return (Vec::new(), children) } let mut size = 4; if num_children == 0 { - size = sample_histogram( - rng.next_u64(), - &self.value_length_distribution, - self.value_length_total, - ) as usize; + size = self.value_length_histogram.sample(rng.next_u64()) as usize; } let mut v = Vec::new(); v.resize(size, 0); - let fill = size; + let fill = if !self.compressable { size } else { size / 2 }; rng.fill_bytes(&mut v[..fill]); - /* // Purely random values as above result in compression never creating smaller values. Do the following to test compression. - // TODO: Better value generation that has random parts and also runs to allow compression to work. Then we can just use that for both cases. - let val = (rng.next_u64() & 256) as u8; - v.resize(size, val); */ - (v, children_seeds) + (v, children) + } + + fn execute_path(&self, tree_index: u64, path: Vec) -> (u64, u32, u64) { + let mut depth = 0; + let mut seed = self.root_seed(tree_index); + for child_index in path { + let (_node_data, children) = self.generate_node(tree_index, depth, seed, true); + let child = &children[child_index as usize]; + if let NodeSpec::Direct(child_tree_index, child_depth, child_seed) = child { + assert_eq!(*child_tree_index, tree_index); + assert_eq!(*child_depth, depth + 1); + depth = *child_depth; + seed = *child_seed; + } else { + assert!(false); + } + } + (tree_index, depth, seed) } } @@ -207,15 +336,32 @@ fn informant(shutdown: Arc) { } fn build_commit_tree( - node_data: (Vec, Vec), - depth: u32, + node_data: (Vec, Vec), chain_generator: &ChainGenerator, ) -> NodeRef { let mut children = Vec::default(); - for seed in node_data.1 { - let child_data = chain_generator.generate_node(seed, depth + 1); - let child_node = build_commit_tree(child_data, depth + 1, chain_generator); - children.push(child_node); + for spec in node_data.1 { + match spec { + NodeSpec::Direct(child_tree_index, child_depth, child_seed) => { + let child_data = + chain_generator.generate_node(child_tree_index, child_depth, child_seed, false); + let child_node = build_commit_tree(child_data, chain_generator); + children.push(child_node); + }, + NodeSpec::UnresolvedPath() => { + assert!(false); + }, + NodeSpec::Path(tree_index, path) => { + // Note, this duplicates the nodes from previous trees. + // TODO: Make it share the nodes when possible. + let (child_tree_index, child_depth, child_seed) = + chain_generator.execute_path(tree_index, path); + let child_data = + chain_generator.generate_node(child_tree_index, child_depth, child_seed, false); + let child_node = build_commit_tree(child_data, chain_generator); + children.push(child_node); + }, + } } let new_node = NewNode { data: node_data.0, children }; NodeRef::New(new_node) @@ -235,14 +381,16 @@ fn num_new_child_nodes(node: &NodeRef) -> u32 { } fn read_value( - root_seed: u64, + tree_index: u64, rng: &mut rand::rngs::SmallRng, db: &Db, chain_generator: &ChainGenerator, ) { let mut depth = 0; + let root_seed = chain_generator.root_seed(tree_index); - let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); + let (gen_node_data, gen_children) = + chain_generator.generate_node(tree_index, depth, root_seed, false); let key = chain_generator.key(root_seed); match db.get_tree(0, &key).unwrap() { @@ -258,12 +406,32 @@ fn read_value( while generated_children.len() > 0 { let child_index = rng.next_u64() % generated_children.len() as u64; - let child_seed = generated_children[child_index as usize]; + + let (child_tree_index, child_seed) = + match &generated_children[child_index as usize] { + NodeSpec::Direct(child_tree_index, _child_depth, child_seed) => + (*child_tree_index, *child_seed), + NodeSpec::UnresolvedPath() => { + assert!(false); + (0, 0) + }, + NodeSpec::Path(tree_index, path) => { + let (child_tree_index, child_depth, child_seed) = + chain_generator.execute_path(*tree_index, path.clone()); + assert_eq!(child_depth, depth + 1); + (child_tree_index, child_seed) + }, + }; + let child_address = database_children[child_index as usize]; depth += 1; - let (gen_node_data, gen_children) = - chain_generator.generate_node(child_seed, depth); + let (gen_node_data, gen_children) = chain_generator.generate_node( + child_tree_index, + depth, + child_seed, + false, + ); match reader.get_node(child_address).unwrap() { Some((db_node_data, db_children)) => { assert_eq!(gen_node_data, db_node_data); @@ -298,7 +466,7 @@ fn writer( shutdown: Arc, start_commit: usize, ) { - let offset = args.seed.unwrap_or(0); + let seed = args.seed.unwrap_or(0); let mut commit = Vec::new(); loop { @@ -307,9 +475,11 @@ fn writer( break } - let root_seed = n as u64 + offset; - let node_data = chain_generator.generate_node(root_seed, 0); - let root_node_ref = build_commit_tree(node_data, 0, &chain_generator); + let tree_index = n as u64; + let root_seed = chain_generator.root_seed(tree_index); + + let node_data = chain_generator.generate_node(tree_index, 0, root_seed, false); + let root_node_ref = build_commit_tree(node_data, &chain_generator); let num_new_nodes = num_new_child_nodes(&root_node_ref) + 1; println!("Tree commit num new nodes: {}", num_new_nodes); if let NodeRef::New(node) = root_node_ref { @@ -321,8 +491,8 @@ fn writer( commit.clear(); // Immediately read and check a random value from the tree - let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + n as u64); - read_value(root_seed, &mut rng, &db, &chain_generator); + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); + read_value(tree_index, &mut rng, &db, &chain_generator); } } } @@ -344,26 +514,41 @@ fn reader( continue } - let root_seed = rng.next_u64() % commits + offset; + let tree_index = rng.next_u64() % commits; - read_value(root_seed, &mut rng, &db, &chain_generator); + read_value(tree_index, &mut rng, &db, &chain_generator); } } fn iter_children<'a>( depth: u32, - generated_children: &mut Vec, + generated_children: &mut Vec, database_children: &mut Vec, reader: &RwLockReadGuard<'a, TreeReader>, chain_generator: &ChainGenerator, ) { for i in 0..generated_children.len() { let child_index = i; - let child_seed = generated_children[child_index as usize]; + + let (child_tree_index, child_seed) = match &generated_children[child_index as usize] { + NodeSpec::Direct(child_tree_index, _child_depth, child_seed) => + (*child_tree_index, *child_seed), + NodeSpec::UnresolvedPath() => { + assert!(false); + (0, 0) + }, + NodeSpec::Path(tree_index, path) => { + let (child_tree_index, child_depth, child_seed) = + chain_generator.execute_path(*tree_index, path.clone()); + assert_eq!(child_depth, depth + 1); + (child_tree_index, child_seed) + }, + }; + let child_address = database_children[child_index as usize]; let (gen_node_data, mut gen_children) = - chain_generator.generate_node(child_seed, depth + 1); + chain_generator.generate_node(child_tree_index, depth + 1, child_seed, false); match reader.get_node(child_address).unwrap() { Some((db_node_data, mut db_children)) => { assert_eq!(gen_node_data, db_node_data); @@ -401,10 +586,12 @@ fn iter( continue } - let root_seed = rng.next_u64() % commits + offset; + let tree_index = rng.next_u64() % commits; + let root_seed = chain_generator.root_seed(tree_index); let depth = 0; - let (gen_node_data, gen_children) = chain_generator.generate_node(root_seed, depth); + let (gen_node_data, gen_children) = + chain_generator.generate_node(tree_index, depth, root_seed, false); let key = chain_generator.key(root_seed); match db.get_tree(0, &key).unwrap() { @@ -454,8 +641,13 @@ pub fn run_internal(args: Args, db: Db) { data::DEPTH_CHILD_COUNT_HISTOGRAMS.iter().map(|x| x.1.iter().sum::()).sum(); println!("Total num expected tree nodes: {}", total_num_expected_tree_nodes); - let chain_generator = - ChainGenerator::new(data::DEPTH_CHILD_COUNT_HISTOGRAMS, data::VALUE_LENGTH_HISTOGRAM); + let chain_generator = ChainGenerator::new( + data::DEPTH_CHILD_COUNT_HISTOGRAMS, + data::AGE_HISTOGRAM, + data::VALUE_LENGTH_HISTOGRAM, + args.seed.unwrap_or(0), + args.compress, + ); let chain_generator = Arc::new(chain_generator); let start_time = std::time::Instant::now(); From a057eedafa437cfcef330dfd6daef94851cde157 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 18 Jul 2023 19:16:25 +0100 Subject: [PATCH 12/53] Tree commits share existing nodes --- admin/src/lib.rs | 2 +- admin/src/multitree_bench/mod.rs | 299 ++++++++++++++++++++++++------- src/db.rs | 23 ++- 3 files changed, 247 insertions(+), 77 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index 9914c246..ec152e16 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -150,7 +150,7 @@ pub fn run() -> Result<(), String> { } let db = parity_db::Db::open_or_create(&db_options).unwrap(); - multitree_bench::run_internal(args, db); + multitree_bench::run_internal(args, db)?; }, } Ok(()) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index d727818e..927d28c0 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -8,11 +8,12 @@ mod data; pub use parity_db::{CompressionType, Db, Key, TreeReader, Value}; use parity_db::{NewNode, NodeRef, Operation}; -use parking_lot::RwLockReadGuard; +use parking_lot::{RwLock, RwLockReadGuard}; use rand::{RngCore, SeedableRng}; use std::{ - collections::BTreeMap, + collections::{BTreeMap, HashMap, HashSet}, + ops::Deref, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, Arc, @@ -217,6 +218,8 @@ impl ChainGenerator { if child_tree_index == tree_index { children.push(NodeSpec::Direct(tree_index, depth + 1, rng.next_u64())); } else { + // Always generate path seed even if only_direct_children is true to ensure + // determinism. let path_seed = rng.next_u64(); if only_direct_children { children.push(NodeSpec::UnresolvedPath()); @@ -310,7 +313,7 @@ impl ChainGenerator { (v, children) } - fn execute_path(&self, tree_index: u64, path: Vec) -> (u64, u32, u64) { + fn execute_path(&self, tree_index: u64, path: Vec) -> Result<(u64, u32, u64), String> { let mut depth = 0; let mut seed = self.root_seed(tree_index); for child_index in path { @@ -322,61 +325,173 @@ impl ChainGenerator { depth = *child_depth; seed = *child_seed; } else { - assert!(false); + return Err("Non-direct node in path".to_string()) } } - (tree_index, depth, seed) + Ok((tree_index, depth, seed)) } } -fn informant(shutdown: Arc) { +fn informant(shutdown: Arc) -> Result<(), String> { while !shutdown.load(Ordering::Relaxed) { thread::sleep(std::time::Duration::from_secs(1)); } + Ok(()) } -fn build_commit_tree( +fn find_dependent_trees( + node_data: &(Vec, Vec), + chain_generator: &ChainGenerator, + trees: &mut HashSet, +) -> Result<(), String> { + for spec in &node_data.1 { + match spec { + NodeSpec::Direct(child_tree_index, child_depth, child_seed) => { + let child_data = chain_generator.generate_node( + *child_tree_index, + *child_depth, + *child_seed, + false, + ); + find_dependent_trees(&child_data, chain_generator, trees)?; + }, + NodeSpec::UnresolvedPath() => return Err("UnresolvedPath found".to_string()), + NodeSpec::Path(tree_index, _path) => { + trees.insert(*tree_index); + }, + } + } + Ok(()) +} + +fn build_commit_tree<'s, 'd: 's>( node_data: (Vec, Vec), + db: &Db, chain_generator: &ChainGenerator, -) -> NodeRef { + tree_refs: &'s HashMap>, + tree_guards: &mut HashMap>, +) -> Result { let mut children = Vec::default(); for spec in node_data.1 { match spec { NodeSpec::Direct(child_tree_index, child_depth, child_seed) => { let child_data = chain_generator.generate_node(child_tree_index, child_depth, child_seed, false); - let child_node = build_commit_tree(child_data, chain_generator); + let child_node = + build_commit_tree(child_data, db, chain_generator, tree_refs, tree_guards)?; children.push(child_node); }, - NodeSpec::UnresolvedPath() => { - assert!(false); - }, + NodeSpec::UnresolvedPath() => return Err("UnresolvedPath found".to_string()), NodeSpec::Path(tree_index, path) => { - // Note, this duplicates the nodes from previous trees. - // TODO: Make it share the nodes when possible. - let (child_tree_index, child_depth, child_seed) = - chain_generator.execute_path(tree_index, path); - let child_data = - chain_generator.generate_node(child_tree_index, child_depth, child_seed, false); - let child_node = build_commit_tree(child_data, chain_generator); - children.push(child_node); + let root_seed = chain_generator.root_seed(tree_index); + let key = chain_generator.key(root_seed); + + if let None = tree_guards.get(&key) { + if let Some(tree_ref) = tree_refs.get(&key) { + tree_guards.insert(key.clone(), tree_ref.read()); + } + } + + let mut final_child_address: Option = None; + if let Some(tree_guard) = tree_guards.get(&key) { + if let Some((db_node_data, db_children)) = tree_guard.get_root().unwrap() { + // Note: We don't actually have to generate any nodes here; we could just + // traverse down the database nodes. Only generating them to verify data. + let (gen_node_data, gen_children) = + chain_generator.generate_node(tree_index, 0, root_seed, false); + + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + let mut generated_children = gen_children; + let mut database_children = db_children; + + for index in 0..path.len() { + let child_index = path[index]; + + let child_address = database_children[child_index as usize]; + + if index == path.len() - 1 { + final_child_address = Some(child_address); + break + } + + let (child_tree_index, child_depth, child_seed) = + match &generated_children[child_index as usize] { + NodeSpec::Direct(child_tree_index, child_depth, child_seed) => + (*child_tree_index, *child_depth, *child_seed), + NodeSpec::UnresolvedPath() => + return Err("UnresolvedPath found".to_string()), + NodeSpec::Path(_tree_index, _path) => + return Err("NodeSpec::Path found within path".to_string()), + }; + + let (gen_node_data, gen_children) = chain_generator.generate_node( + child_tree_index, + child_depth, + child_seed, + false, + ); + + match tree_guard.get_node(child_address).unwrap() { + Some((db_node_data, db_children)) => { + assert_eq!(gen_node_data, db_node_data); + assert_eq!(gen_children.len(), db_children.len()); + + generated_children = gen_children; + database_children = db_children; + }, + None => return Err("Child address not in database".to_string()), + } + } + } + } + + match final_child_address { + Some(address) => { + let child_node = NodeRef::Existing(address); + children.push(child_node); + }, + None => { + // Not able to get the existing child address so duplicate sub-tree + let (child_tree_index, child_depth, child_seed) = + chain_generator.execute_path(tree_index, path)?; + let child_data = chain_generator.generate_node( + child_tree_index, + child_depth, + child_seed, + false, + ); + let child_node = build_commit_tree( + child_data, + db, + chain_generator, + tree_refs, + tree_guards, + )?; + children.push(child_node); + }, + } }, } } let new_node = NewNode { data: node_data.0, children }; - NodeRef::New(new_node) + Ok(NodeRef::New(new_node)) } -fn num_new_child_nodes(node: &NodeRef) -> u32 { +fn num_new_nodes(node: &NodeRef, num_existing: &mut u32) -> u32 { match node { NodeRef::New(node) => { - let mut num = 0; + let mut num = 1; for child in &node.children { - num += num_new_child_nodes(child) + 1; + num += num_new_nodes(child, num_existing); } num }, - NodeRef::Existing(_) => 0, + NodeRef::Existing(_) => { + *num_existing += 1; + 0 + }, } } @@ -385,7 +500,7 @@ fn read_value( rng: &mut rand::rngs::SmallRng, db: &Db, chain_generator: &ChainGenerator, -) { +) -> Result<(), String> { let mut depth = 0; let root_seed = chain_generator.root_seed(tree_index); @@ -411,13 +526,11 @@ fn read_value( match &generated_children[child_index as usize] { NodeSpec::Direct(child_tree_index, _child_depth, child_seed) => (*child_tree_index, *child_seed), - NodeSpec::UnresolvedPath() => { - assert!(false); - (0, 0) - }, + NodeSpec::UnresolvedPath() => + return Err("UnresolvedPath found".to_string()), NodeSpec::Path(tree_index, path) => { let (child_tree_index, child_depth, child_seed) = - chain_generator.execute_path(*tree_index, path.clone()); + chain_generator.execute_path(*tree_index, path.clone())?; assert_eq!(child_depth, depth + 1); (child_tree_index, child_seed) }, @@ -440,22 +553,40 @@ fn read_value( generated_children = gen_children; database_children = db_children; }, - None => { - assert!(false); - }, + None => return Err("Child address not in database".to_string()), } } QUERIES.fetch_add(1, Ordering::SeqCst); }, - None => { - assert!(false); - }, + None => return Err("Tree root not in database".to_string()), } }, - None => { - assert!(false); - }, + None => return Err("Tree not in database".to_string()), + } + + Ok(()) +} + +struct TreeReaderRef<'d> { + reader_ref: Arc>, +} + +impl<'d> TreeReaderRef<'d> { + pub fn read<'s>(&'s self) -> TreeReaderGuard<'s, 'd> { + TreeReaderGuard { lock_guard: self.reader_ref.read() } + } +} + +struct TreeReaderGuard<'s, 'd: 's> { + lock_guard: RwLockReadGuard<'s, dyn TreeReader + 'd>, +} + +impl<'s, 'd: 's> Deref for TreeReaderGuard<'s, 'd> { + type Target = dyn TreeReader + 'd; + + fn deref(&self) -> &Self::Target { + self.lock_guard.deref() } } @@ -465,7 +596,7 @@ fn writer( chain_generator: Arc, shutdown: Arc, start_commit: usize, -) { +) -> Result<(), String> { let seed = args.seed.unwrap_or(0); let mut commit = Vec::new(); @@ -479,9 +610,40 @@ fn writer( let root_seed = chain_generator.root_seed(tree_index); let node_data = chain_generator.generate_node(tree_index, 0, root_seed, false); - let root_node_ref = build_commit_tree(node_data, &chain_generator); - let num_new_nodes = num_new_child_nodes(&root_node_ref) + 1; - println!("Tree commit num new nodes: {}", num_new_nodes); + + // First phase. Find all trees that this commit is dependent on. + let mut trees: HashSet = Default::default(); + find_dependent_trees(&node_data, &chain_generator, &mut trees)?; + + let mut tree_refs: HashMap = Default::default(); + let mut tree_guards: HashMap = Default::default(); + for index in trees { + let seed = chain_generator.root_seed(index); + let key = chain_generator.key(seed); + match db.get_tree(0, &key).unwrap() { + Some(reader) => { + let reader_ref = TreeReaderRef { reader_ref: reader }; + tree_refs.insert(key, reader_ref); + }, + None => { + // It's fine for the tree to not be in the database. The commit will regenerate + // the required nodes. + }, + } + } + + /* for (key, tree_ref) in tree_refs.iter() { + tree_guards.insert(key.clone(), tree_ref.read()); + } */ + + let root_node_ref = + build_commit_tree(node_data, &db, &chain_generator, &tree_refs, &mut tree_guards)?; + let mut num_existing_nodes = 0; + let num_new_nodes = num_new_nodes(&root_node_ref, &mut num_existing_nodes); + println!( + "Tree commit num new nodes: {}, num existing: {}", + num_new_nodes, num_existing_nodes + ); if let NodeRef::New(node) = root_node_ref { let key = chain_generator.key(root_seed); commit.push((0, Operation::InsertTree(key.to_vec(), node))); @@ -492,9 +654,11 @@ fn writer( // Immediately read and check a random value from the tree let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); - read_value(tree_index, &mut rng, &db, &chain_generator); + read_value(tree_index, &mut rng, &db, &chain_generator)?; } } + + Ok(()) } fn reader( @@ -503,7 +667,7 @@ fn reader( chain_generator: Arc, index: u64, shutdown: Arc, -) { +) -> Result<(), String> { // Query random values from random trees while writing let offset = args.seed.unwrap_or(0); let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); @@ -516,30 +680,29 @@ fn reader( let tree_index = rng.next_u64() % commits; - read_value(tree_index, &mut rng, &db, &chain_generator); + read_value(tree_index, &mut rng, &db, &chain_generator)?; } + + Ok(()) } fn iter_children<'a>( depth: u32, generated_children: &mut Vec, database_children: &mut Vec, - reader: &RwLockReadGuard<'a, TreeReader>, + reader: &RwLockReadGuard<'a, dyn TreeReader>, chain_generator: &ChainGenerator, -) { +) -> Result<(), String> { for i in 0..generated_children.len() { let child_index = i; let (child_tree_index, child_seed) = match &generated_children[child_index as usize] { NodeSpec::Direct(child_tree_index, _child_depth, child_seed) => (*child_tree_index, *child_seed), - NodeSpec::UnresolvedPath() => { - assert!(false); - (0, 0) - }, + NodeSpec::UnresolvedPath() => return Err("UnresolvedPath found".to_string()), NodeSpec::Path(tree_index, path) => { let (child_tree_index, child_depth, child_seed) = - chain_generator.execute_path(*tree_index, path.clone()); + chain_generator.execute_path(*tree_index, path.clone())?; assert_eq!(child_depth, depth + 1); (child_tree_index, child_seed) }, @@ -560,13 +723,13 @@ fn iter_children<'a>( &mut db_children, reader, chain_generator, - ); - }, - None => { - assert!(false); + )?; }, + None => return Err("Child address not in database".to_string()), } } + + Ok(()) } fn iter( @@ -575,7 +738,7 @@ fn iter( chain_generator: Arc, index: u64, shutdown: Arc, -) { +) -> Result<(), String> { // Iterate over nodes in random trees while writing let offset = args.seed.unwrap_or(0); let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); @@ -612,23 +775,21 @@ fn iter( &mut database_children, &reader, &chain_generator, - ); + )?; ITERATIONS.fetch_add(1, Ordering::SeqCst); }, - None => { - assert!(false); - }, + None => return Err("Tree root not in database".to_string()), } }, - None => { - assert!(false); - }, + None => return Err("Tree not in database".to_string()), } } + + Ok(()) } -pub fn run_internal(args: Args, db: Db) { +pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let args = Arc::new(args); let shutdown = Arc::new(AtomicBool::new(false)); let db = Arc::new(db); @@ -711,7 +872,7 @@ pub fn run_internal(args: Args, db: Db) { shutdown.store(true, Ordering::SeqCst); for t in threads.into_iter() { - t.join().unwrap(); + t.join().unwrap()?; } let commits = COMMITS.load(Ordering::SeqCst); @@ -729,4 +890,6 @@ pub fn run_internal(args: Args, db: Db) { queries, iterations ); + + Ok(()) } diff --git a/src/db.rs b/src/db.rs index eb9f727e..2f12e21c 100644 --- a/src/db.rs +++ b/src/db.rs @@ -133,7 +133,7 @@ struct CommitQueue { #[derive(Debug)] struct Trees { - readers: HashMap>, IdentityBuildHasher>, + readers: HashMap>, IdentityBuildHasher>, } #[derive(Debug)] @@ -337,7 +337,7 @@ impl DbInner { db: &Arc, col: ColId, key: &[u8], - ) -> Result>>> { + ) -> Result>>> { match &self.columns[col as usize] { Column::Hash(column) => { let key = column.hash_key(key); @@ -358,7 +358,7 @@ impl DbInner { let column_trees = trees.entry(col).or_insert_with(|| Trees { readers: Default::default() }); - let reader = Arc::new(RwLock::new(TreeReader { db: db.clone(), col, key })); + let reader = Arc::new(RwLock::new(DbTreeReader { db: db.clone(), col, key })); column_trees.readers.insert(key, reader.clone()); @@ -1096,7 +1096,7 @@ impl Db { self.inner.btree_iter(col) } - pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>>> { + pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>>> { self.inner.get_tree(&self.inner, col, key) } @@ -1363,15 +1363,22 @@ impl Db { } } +// Use a trait here to allow client code to have better control over lock guard lifetime without +// lifetime proliferation within Db (which would be required if not using a dynamic object). +pub trait TreeReader { + fn get_root(&self) -> Result, Children)>>; + fn get_node(&self, node_address: NodeAddress) -> Result, Children)>>; +} + #[derive(Debug)] -pub struct TreeReader { +pub struct DbTreeReader { db: Arc, col: ColId, key: Key, } -impl TreeReader { - pub fn get_root(&self) -> Result, Children)>> { +impl TreeReader for DbTreeReader { + fn get_root(&self) -> Result, Children)>> { /* let value = self.db.get(self.col, &self.key)?; if let Some(data) = value { return unpack_node_data(data).map(|x| Some(x)) @@ -1401,7 +1408,7 @@ impl TreeReader { Err(Error::InvalidValueData) } - pub fn get_node(&self, node_address: NodeAddress) -> Result, Children)>> { + fn get_node(&self, node_address: NodeAddress) -> Result, Children)>> { self.db.get_node(self.col, node_address) } } From 366cb7bd230a2fc2c7cc0a350b8c4b8cc0504f72 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 19 Jul 2023 19:40:01 +0100 Subject: [PATCH 13/53] Stress test tree pruning. Tree removal (Currently just removes root). --- admin/src/lib.rs | 12 ++- admin/src/multitree_bench/mod.rs | 127 +++++++++++++++++++++++++++---- src/db.rs | 49 ++++++++---- 3 files changed, 157 insertions(+), 31 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index ec152e16..d511b197 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -134,7 +134,7 @@ pub fn run() -> Result<(), String> { options.path.push("test_db_multitree_stress"); if options.path.exists() && !args.append { std::fs::remove_dir_all(options.path.as_path()) - .map_err(|e| format!("Error clearing stress db: {e:?}"))?; + .map_err(|e| format!("Error clearing multitree stress db: {e:?}"))?; } let mut db_options = options.clone(); @@ -149,6 +149,16 @@ pub fn run() -> Result<(), String> { } } + if db_options.columns.len() < 2 { + let info_column: parity_db::ColumnOptions = Default::default(); + db_options.columns.push(info_column); + } + + let info_column = &mut db_options.columns[1]; + info_column.uniform = false; + info_column.ref_counted = false; + info_column.multitree = false; + let db = parity_db::Db::open_or_create(&db_options).unwrap(); multitree_bench::run_internal(args, db)?; }, diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 927d28c0..8aea207f 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -23,9 +23,16 @@ use std::{ static COMMITS: AtomicUsize = AtomicUsize::new(0); static NEXT_COMMIT: AtomicUsize = AtomicUsize::new(0); +static NUM_REMOVED: AtomicUsize = AtomicUsize::new(0); static QUERIES: AtomicUsize = AtomicUsize::new(0); static ITERATIONS: AtomicUsize = AtomicUsize::new(0); +const TREE_COLUMN: u8 = 0; +const INFO_COLUMN: u8 = 1; + +const KEY_LAST_COMMIT: Key = [1u8; 32]; +const KEY_NUM_REMOVED: Key = [2u8; 32]; + /// Stress tests (warning erase db first). #[derive(Debug, clap::Parser)] pub struct MultiTreeStress { @@ -56,9 +63,9 @@ pub struct MultiTreeStress { #[clap(long)] pub append: bool, - /// Do not apply pruning. + /// Number of trees to keep (Older are removed). 0 means never remove. [default: 8] #[clap(long)] - pub archive: bool, + pub pruning: Option, /// Enable compression. #[clap(long)] @@ -77,7 +84,7 @@ pub struct Args { pub commits: usize, pub seed: Option, pub append: bool, - pub archive: bool, + pub pruning: u64, pub compress: bool, pub commit_time: u64, } @@ -91,7 +98,7 @@ impl MultiTreeStress { commits: self.commits.unwrap_or(100_000), seed: self.seed, append: self.append, - archive: self.archive, + pruning: self.pruning.unwrap_or(8), compress: self.compress, commit_time: self.commit_time.unwrap_or(0), } @@ -508,7 +515,7 @@ fn read_value( chain_generator.generate_node(tree_index, depth, root_seed, false); let key = chain_generator.key(root_seed); - match db.get_tree(0, &key).unwrap() { + match db.get_tree(TREE_COLUMN, &key).unwrap() { Some(reader) => { let reader = reader.read(); match reader.get_root().unwrap() { @@ -559,7 +566,13 @@ fn read_value( QUERIES.fetch_add(1, Ordering::SeqCst); }, - None => return Err("Tree root not in database".to_string()), + None => { + // Is this expected? + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + return Err("Tree root not in database".to_string()) + } + }, } }, None => return Err("Tree not in database".to_string()), @@ -641,12 +654,17 @@ fn writer( let mut num_existing_nodes = 0; let num_new_nodes = num_new_nodes(&root_node_ref, &mut num_existing_nodes); println!( - "Tree commit num new nodes: {}, num existing: {}", - num_new_nodes, num_existing_nodes + "Commit tree {}, num new nodes: {}, num existing: {}", + tree_index, num_new_nodes, num_existing_nodes ); if let NodeRef::New(node) = root_node_ref { let key = chain_generator.key(root_seed); - commit.push((0, Operation::InsertTree(key.to_vec(), node))); + commit.push((TREE_COLUMN, Operation::InsertTree(key.to_vec(), node))); + + commit.push(( + INFO_COLUMN, + Operation::Set(KEY_LAST_COMMIT.to_vec(), (n as u64).to_be_bytes().to_vec()), + )); db.commit_changes(commit.drain(..)).unwrap(); COMMITS.fetch_add(1, Ordering::Relaxed); @@ -661,6 +679,47 @@ fn writer( Ok(()) } +fn pruner( + db: Arc, + args: Arc, + chain_generator: Arc, + shutdown: Arc, +) -> Result<(), String> { + let mut commit = Vec::new(); + + while !shutdown.load(Ordering::Relaxed) { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + let commits = COMMITS.load(Ordering::Relaxed); + + let target_num_removed = + if commits as u64 > args.pruning { commits as u64 - args.pruning } else { 0 }; + + if target_num_removed > num_removed as u64 { + // Need to remove a tree + let tree_index = num_removed as u64; + let root_seed = chain_generator.root_seed(tree_index); + let key = chain_generator.key(root_seed); + + println!("Remove tree {}", tree_index); + + commit.push((TREE_COLUMN, Operation::RemoveTree(key.to_vec()))); + commit.push(( + INFO_COLUMN, + Operation::Set( + KEY_NUM_REMOVED.to_vec(), + ((num_removed + 1) as u64).to_be_bytes().to_vec(), + ), + )); + + db.commit_changes(commit.drain(..)).unwrap(); + NUM_REMOVED.fetch_add(1, Ordering::Relaxed); + commit.clear(); + } + } + + Ok(()) +} + fn reader( db: Arc, args: Arc, @@ -673,12 +732,14 @@ fn reader( let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); while !shutdown.load(Ordering::Relaxed) { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed) as u64; let commits = COMMITS.load(Ordering::Relaxed) as u64; if commits == 0 { continue } - let tree_index = rng.next_u64() % commits; + //let tree_index = rng.next_u64() % commits; + let tree_index = (rng.next_u64() % (commits - num_removed)) + num_removed; read_value(tree_index, &mut rng, &db, &chain_generator)?; } @@ -744,12 +805,15 @@ fn iter( let mut rng = rand::rngs::SmallRng::seed_from_u64(offset + index); while !shutdown.load(Ordering::Relaxed) { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed) as u64; let commits = COMMITS.load(Ordering::Relaxed) as u64; if commits == 0 { continue } - let tree_index = rng.next_u64() % commits; + //let tree_index = rng.next_u64() % commits; + let tree_index = (rng.next_u64() % (commits - num_removed)) + num_removed; + let root_seed = chain_generator.root_seed(tree_index); let depth = 0; @@ -757,7 +821,7 @@ fn iter( chain_generator.generate_node(tree_index, depth, root_seed, false); let key = chain_generator.key(root_seed); - match db.get_tree(0, &key).unwrap() { + match db.get_tree(TREE_COLUMN, &key).unwrap() { Some(reader) => { let reader = reader.read(); match reader.get_root().unwrap() { @@ -779,7 +843,13 @@ fn iter( ITERATIONS.fetch_add(1, Ordering::SeqCst); }, - None => return Err("Tree root not in database".to_string()), + None => { + // Is this expected? + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + return Err("Tree root not in database".to_string()) + } + }, } }, None => return Err("Tree not in database".to_string()), @@ -796,7 +866,21 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let mut threads = Vec::new(); - let start_commit = 0; + let start_commit = if let Some(start) = db.get(INFO_COLUMN, &KEY_LAST_COMMIT).unwrap() { + let mut buf = [0u8; 8]; + buf.copy_from_slice(&start[0..8]); + u64::from_be_bytes(buf) as usize + 1 + } else { + 0 + }; + + let num_removed = if let Some(start) = db.get(INFO_COLUMN, &KEY_NUM_REMOVED).unwrap() { + let mut buf = [0u8; 8]; + buf.copy_from_slice(&start[0..8]); + u64::from_be_bytes(buf) as usize + } else { + 0 + }; let total_num_expected_tree_nodes: u32 = data::DEPTH_CHILD_COUNT_HISTOGRAMS.iter().map(|x| x.1.iter().sum::()).sum(); @@ -815,6 +899,7 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { COMMITS.store(start_commit, Ordering::SeqCst); NEXT_COMMIT.store(start_commit, Ordering::SeqCst); + NUM_REMOVED.store(num_removed, Ordering::SeqCst); { let shutdown = shutdown.clone(); @@ -866,6 +951,20 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { ); } + if args.pruning > 0 { + let db = db.clone(); + let shutdown = shutdown.clone(); + let args = args.clone(); + let chain_generator = chain_generator.clone(); + + threads.push( + thread::Builder::new() + .name(format!("pruner")) + .spawn(move || pruner(db, args, chain_generator, shutdown)) + .unwrap(), + ); + } + while COMMITS.load(Ordering::Relaxed) < start_commit + args.commits { thread::sleep(std::time::Duration::from_millis(50)); } diff --git a/src/db.rs b/src/db.rs index 2f12e21c..96a1a231 100644 --- a/src/db.rs +++ b/src/db.rs @@ -410,25 +410,40 @@ impl DbInner { .or_insert_with(|| BTreeChangeSet::new(col)) .push(change)? } else if self.options.columns[col as usize].multitree { - // TODO: Allow normal Operations as well? match &self.columns[col as usize] { - Column::Hash(column) => { - let (root_data, node_values) = column.claim_tree_values(&change)?; - - let root_operation = Operation::Set(change.key(), root_data); - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push(root_operation, &self.options, self.db_version)?; - - for node_change in node_values { + Column::Hash(column) => match change { + Operation::Set(..) | + Operation::Dereference(..) | + Operation::Reference(..) => + return Err(Error::InvalidConfiguration( + "Invalid operation for multitree column".to_string(), + )), + Operation::InsertTree(..) => { + let (root_data, node_values) = column.claim_tree_values(&change)?; + + let root_operation = Operation::Set(change.key(), root_data); commit .indexed .entry(col) .or_insert_with(|| IndexedChangeSet::new(col)) - .push_node_change(node_change); - } + .push(root_operation, &self.options, self.db_version)?; + + for node_change in node_values { + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push_node_change(node_change); + } + }, + Operation::RemoveTree(..) => { + let root_operation = Operation::Dereference(change.key()); + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(root_operation, &self.options, self.db_version)?; + }, }, Column::Tree(_) => return Err(Error::InvalidConfiguration("Not a HashColumn".to_string())), @@ -1402,10 +1417,12 @@ impl TreeReader for DbTreeReader { if let Some(data) = value { return unpack_node_data(data).map(|x| Some(x)) } + + return Ok(None) }, - Column::Tree(..) => {}, + Column::Tree(..) => + return Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), }; - Err(Error::InvalidValueData) } fn get_node(&self, node_address: NodeAddress) -> Result, Children)>> { From 4461eb4002b974625b9213a0640d7583ceda2778 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Mon, 24 Jul 2023 13:15:52 +0100 Subject: [PATCH 14/53] Implemented tree removal with reference counting for shared nodes --- admin/src/lib.rs | 3 +- admin/src/multitree_bench/mod.rs | 254 +++++++++++++++++++++++++------ src/column.rs | 54 ++++++- src/db.rs | 180 +++++++++++++++++----- src/table.rs | 21 ++- 5 files changed, 422 insertions(+), 90 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index d511b197..0a5b94f4 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -156,8 +156,9 @@ pub fn run() -> Result<(), String> { let info_column = &mut db_options.columns[1]; info_column.uniform = false; - info_column.ref_counted = false; info_column.multitree = false; + info_column.ref_counted = false; + info_column.preimage = false; let db = parity_db::Db::open_or_create(&db_options).unwrap(); multitree_bench::run_internal(args, db)?; diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 8aea207f..6cff8f9f 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -13,6 +13,7 @@ use parking_lot::{RwLock, RwLockReadGuard}; use rand::{RngCore, SeedableRng}; use std::{ collections::{BTreeMap, HashMap, HashSet}, + io::Write, ops::Deref, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -24,8 +25,10 @@ use std::{ static COMMITS: AtomicUsize = AtomicUsize::new(0); static NEXT_COMMIT: AtomicUsize = AtomicUsize::new(0); static NUM_REMOVED: AtomicUsize = AtomicUsize::new(0); +static TARGET_NUM_REMOVED: AtomicUsize = AtomicUsize::new(0); static QUERIES: AtomicUsize = AtomicUsize::new(0); static ITERATIONS: AtomicUsize = AtomicUsize::new(0); +static EXPECTED_NUM_ENTRIES: AtomicUsize = AtomicUsize::new(0); const TREE_COLUMN: u8 = 0; const INFO_COLUMN: u8 = 1; @@ -33,6 +36,10 @@ const INFO_COLUMN: u8 = 1; const KEY_LAST_COMMIT: Key = [1u8; 32]; const KEY_NUM_REMOVED: Key = [2u8; 32]; +const THREAD_PRUNING: bool = true; +const FORCE_NO_MULTIPART_VALUES: bool = true; +const FIXED_TEXT_POSITION: bool = true; + /// Stress tests (warning erase db first). #[derive(Debug, clap::Parser)] pub struct MultiTreeStress { @@ -105,6 +112,50 @@ impl MultiTreeStress { } } +struct OutputHelper { + last_fixed: String, + stdout: std::io::Stdout, +} + +impl OutputHelper { + fn new() -> OutputHelper { + println!(""); + OutputHelper { last_fixed: "".to_string(), stdout: std::io::stdout() } + } + + fn println(&mut self, text: String) { + if FIXED_TEXT_POSITION { + let overwrite = format!("{:<1$}", text, self.last_fixed.len()); + println!("\r{}", overwrite); + print!("{}", self.last_fixed); + self.stdout.flush().unwrap(); + } else { + println!("{}", text); + } + } + + fn print_fixed(&mut self, text: String) { + if FIXED_TEXT_POSITION { + let overwrite = format!("{:<1$}", text, self.last_fixed.len()); + print!("\r{}", overwrite); + self.last_fixed = text; + self.stdout.flush().unwrap(); + } else { + println!(" {}", text); + } + } + + fn println_final(&mut self, text: String) { + if FIXED_TEXT_POSITION { + println!(""); + println!("{}", text); + self.stdout.flush().unwrap(); + } else { + println!("{}", text); + } + } +} + struct Histogram { distribution: BTreeMap, total: u32, @@ -310,6 +361,9 @@ impl ChainGenerator { let mut size = 4; if num_children == 0 { size = self.value_length_histogram.sample(rng.next_u64()) as usize; + if FORCE_NO_MULTIPART_VALUES { + size = std::cmp::min(size, 32760 - 64); + } } let mut v = Vec::new(); @@ -339,9 +393,39 @@ impl ChainGenerator { } } -fn informant(shutdown: Arc) -> Result<(), String> { - while !shutdown.load(Ordering::Relaxed) { - thread::sleep(std::time::Duration::from_secs(1)); +fn informant( + db: Arc, + shutdown: Arc, + shutdown_final: Arc, + output_helper: Arc>, +) -> Result<(), String> { + let mut num_expected_entries = 0; + let mut num_entries = 0; + while !shutdown_final.load(Ordering::Relaxed) { + if FIXED_TEXT_POSITION { + thread::sleep(std::time::Duration::from_millis(100)); + } else { + thread::sleep(std::time::Duration::from_secs(1)); + } + + let new_num_expected_entries = EXPECTED_NUM_ENTRIES.load(Ordering::Relaxed); + let new_num_entries = db.get_num_column_value_entries(TREE_COLUMN).unwrap(); + + if new_num_expected_entries != num_expected_entries || new_num_entries != num_entries { + num_expected_entries = new_num_expected_entries; + num_entries = new_num_entries; + + output_helper.write().print_fixed(format!( + "Entries, Created: {}, ValueTables: {}", + num_expected_entries, num_entries + )); + + if num_entries == 0 { + if shutdown.load(Ordering::Relaxed) { + shutdown_final.store(true, Ordering::SeqCst); + } + } + } } Ok(()) } @@ -575,7 +659,13 @@ fn read_value( }, } }, - None => return Err("Tree not in database".to_string()), + None => { + // Is this expected? + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + return Err("Tree not in database".to_string()) + } + }, } Ok(()) @@ -609,6 +699,7 @@ fn writer( chain_generator: Arc, shutdown: Arc, start_commit: usize, + output_helper: Arc>, ) -> Result<(), String> { let seed = args.seed.unwrap_or(0); let mut commit = Vec::new(); @@ -633,7 +724,7 @@ fn writer( for index in trees { let seed = chain_generator.root_seed(index); let key = chain_generator.key(seed); - match db.get_tree(0, &key).unwrap() { + match db.get_tree(TREE_COLUMN, &key).unwrap() { Some(reader) => { let reader_ref = TreeReaderRef { reader_ref: reader }; tree_refs.insert(key, reader_ref); @@ -653,12 +744,14 @@ fn writer( build_commit_tree(node_data, &db, &chain_generator, &tree_refs, &mut tree_guards)?; let mut num_existing_nodes = 0; let num_new_nodes = num_new_nodes(&root_node_ref, &mut num_existing_nodes); - println!( - "Commit tree {}, num new nodes: {}, num existing: {}", - tree_index, num_new_nodes, num_existing_nodes - ); if let NodeRef::New(node) = root_node_ref { - let key = chain_generator.key(root_seed); + let key: [u8; 32] = chain_generator.key(root_seed); + + output_helper.write().println(format!( + "Commit tree {}, new: {}, existing: {}", + tree_index, num_new_nodes, num_existing_nodes + )); + commit.push((TREE_COLUMN, Operation::InsertTree(key.to_vec(), node))); commit.push(( @@ -668,53 +761,83 @@ fn writer( db.commit_changes(commit.drain(..)).unwrap(); COMMITS.fetch_add(1, Ordering::Relaxed); + EXPECTED_NUM_ENTRIES.fetch_add(num_new_nodes as usize, Ordering::Relaxed); commit.clear(); // Immediately read and check a random value from the tree let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); read_value(tree_index, &mut rng, &db, &chain_generator)?; + + if args.pruning > 0 && !THREAD_PRUNING { + try_prune(&db, &args, &chain_generator, &mut commit, &output_helper)?; + } + + if args.commit_time > 0 { + thread::sleep(std::time::Duration::from_millis(args.commit_time)); + } } } Ok(()) } +fn try_prune( + db: &Db, + args: &Args, + chain_generator: &ChainGenerator, + commit: &mut Vec<(u8, Operation, Vec>)>, + output_helper: &RwLock, +) -> Result<(), String> { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + let target_override = TARGET_NUM_REMOVED.load(Ordering::Relaxed); + let commits = COMMITS.load(Ordering::Relaxed); + + let target_num_removed = if target_override > 0 { + target_override as u64 + } else { + if commits as u64 > args.pruning { + commits as u64 - args.pruning + } else { + 0 + } + }; + + if target_num_removed > num_removed as u64 { + // Need to remove a tree + let tree_index = num_removed as u64; + let root_seed = chain_generator.root_seed(tree_index); + let key = chain_generator.key(root_seed); + + output_helper.write().println(format!("Remove tree {}", tree_index)); + + commit.push((TREE_COLUMN, Operation::RemoveTree(key.to_vec()))); + commit.push(( + INFO_COLUMN, + Operation::Set( + KEY_NUM_REMOVED.to_vec(), + ((num_removed + 1) as u64).to_be_bytes().to_vec(), + ), + )); + + NUM_REMOVED.fetch_add(1, Ordering::Relaxed); + db.commit_changes(commit.drain(..)).unwrap(); + commit.clear(); + } + + Ok(()) +} + fn pruner( db: Arc, args: Arc, chain_generator: Arc, shutdown: Arc, + output_helper: Arc>, ) -> Result<(), String> { let mut commit = Vec::new(); while !shutdown.load(Ordering::Relaxed) { - let num_removed = NUM_REMOVED.load(Ordering::Relaxed); - let commits = COMMITS.load(Ordering::Relaxed); - - let target_num_removed = - if commits as u64 > args.pruning { commits as u64 - args.pruning } else { 0 }; - - if target_num_removed > num_removed as u64 { - // Need to remove a tree - let tree_index = num_removed as u64; - let root_seed = chain_generator.root_seed(tree_index); - let key = chain_generator.key(root_seed); - - println!("Remove tree {}", tree_index); - - commit.push((TREE_COLUMN, Operation::RemoveTree(key.to_vec()))); - commit.push(( - INFO_COLUMN, - Operation::Set( - KEY_NUM_REMOVED.to_vec(), - ((num_removed + 1) as u64).to_be_bytes().to_vec(), - ), - )); - - db.commit_changes(commit.drain(..)).unwrap(); - NUM_REMOVED.fetch_add(1, Ordering::Relaxed); - commit.clear(); - } + try_prune(&db, &args, &chain_generator, &mut commit, &output_helper)?; } Ok(()) @@ -852,7 +975,13 @@ fn iter( }, } }, - None => return Err("Tree not in database".to_string()), + None => { + // Is this expected? + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + return Err("Tree not in database".to_string()) + } + }, } } @@ -862,7 +991,9 @@ fn iter( pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let args = Arc::new(args); let shutdown = Arc::new(AtomicBool::new(false)); + let shutdown_final = Arc::new(AtomicBool::new(false)); let db = Arc::new(db); + let output_helper = Arc::new(RwLock::new(OutputHelper::new())); let mut threads = Vec::new(); @@ -884,7 +1015,9 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let total_num_expected_tree_nodes: u32 = data::DEPTH_CHILD_COUNT_HISTOGRAMS.iter().map(|x| x.1.iter().sum::()).sum(); - println!("Total num expected tree nodes: {}", total_num_expected_tree_nodes); + output_helper + .write() + .println(format!("Expected average num tree nodes: {}", total_num_expected_tree_nodes)); let chain_generator = ChainGenerator::new( data::DEPTH_CHILD_COUNT_HISTOGRAMS, @@ -902,8 +1035,12 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { NUM_REMOVED.store(num_removed, Ordering::SeqCst); { + let db = db.clone(); let shutdown = shutdown.clone(); - threads.push(thread::spawn(move || informant(shutdown))); + let shutdown_final = shutdown_final.clone(); + let output_helper = output_helper.clone(); + + threads.push(thread::spawn(move || informant(db, shutdown, shutdown_final, output_helper))); } for i in 0..args.readers { @@ -942,25 +1079,29 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let shutdown = shutdown.clone(); let args = args.clone(); let chain_generator = chain_generator.clone(); + let output_helper = output_helper.clone(); threads.push( thread::Builder::new() .name(format!("writer {i}")) - .spawn(move || writer(db, args, chain_generator, shutdown, start_commit)) + .spawn(move || { + writer(db, args, chain_generator, shutdown, start_commit, output_helper) + }) .unwrap(), ); } - if args.pruning > 0 { + if args.pruning > 0 && THREAD_PRUNING { let db = db.clone(); - let shutdown = shutdown.clone(); + let shutdown = shutdown_final.clone(); let args = args.clone(); let chain_generator = chain_generator.clone(); + let output_helper = output_helper.clone(); threads.push( thread::Builder::new() .name(format!("pruner")) - .spawn(move || pruner(db, args, chain_generator, shutdown)) + .spawn(move || pruner(db, args, chain_generator, shutdown, output_helper)) .unwrap(), ); } @@ -970,10 +1111,6 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { } shutdown.store(true, Ordering::SeqCst); - for t in threads.into_iter() { - t.join().unwrap()?; - } - let commits = COMMITS.load(Ordering::SeqCst); let commits = commits - start_commit; let elapsed_time = start_time.elapsed().as_secs_f64(); @@ -981,14 +1118,31 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { let queries = QUERIES.load(Ordering::SeqCst); let iterations = ITERATIONS.load(Ordering::SeqCst); - println!( + output_helper.write().println(format!( "Completed {} commits in {} seconds. {} cps. {} queries, {} iterations", commits, elapsed_time, commits as f64 / elapsed_time, queries, iterations - ); + )); + + // Continue removing trees until they are all gone. + TARGET_NUM_REMOVED.store(args.commits, Ordering::SeqCst); + while NUM_REMOVED.load(Ordering::Relaxed) < args.commits { + thread::sleep(std::time::Duration::from_millis(50)); + } + + // Wait for all entries to actually be removed from Db. + while !shutdown_final.load(Ordering::Relaxed) { + thread::sleep(std::time::Duration::from_millis(50)); + } + + for t in threads.into_iter() { + t.join().unwrap()?; + } + + output_helper.write().println_final(format!("Removed all entries")); Ok(()) } diff --git a/src/column.rs b/src/column.rs index 3951d2fa..8997f5f5 100644 --- a/src/column.rs +++ b/src/column.rs @@ -718,7 +718,10 @@ impl HashColumn { for child in children { let address = match child { NodeRef::New(node) => self.claim_node(node, tables, node_values)?, - NodeRef::Existing(address) => address, + NodeRef::Existing(address) => { + node_values.push(NodeChange::IncrementReference(address)); + address + }, }; let mut data_buf = [0u8; 8]; data_buf.copy_from_slice(&address.to_le_bytes()); @@ -758,10 +761,13 @@ impl HashColumn { tables.tables[target_tier].value_size(&table_key).unwrap() as usize ); + // Check it isn't multipart + //assert!(target_tier < (SIZE_TIERS - 1)); + let offset = tables.tables[target_tier].claim_next_free()?; let address = Address::new(offset, target_tier as u8); - node_values.push(NodeChange { address: address.as_u64(), val, cval, compressed }); + node_values.push(NodeChange::NewValue(address.as_u64(), val, cval, compressed)); Ok(address.as_u64()) } @@ -829,6 +835,41 @@ impl HashColumn { Ok(PlanOutcome::Written) } + pub fn write_address_inc_ref_plan( + &self, + address: u64, + log: &mut LogWriter, + ) -> Result { + let tables = self.tables.upgradable_read(); + let tables = self.as_ref(&tables.value); + let address = Address::from_u64(address); + let target_tier = address.size_tier(); + let offset = address.offset(); + tables.tables[target_tier as usize].write_inc_ref(offset, log)?; + + let stats = self.collect_stats.then_some(&self.stats); + if let Some(stats) = stats { + stats.reference_increase(); + } + + Ok(PlanOutcome::Written) + } + + pub fn write_address_dec_ref_plan( + &self, + address: u64, + log: &mut LogWriter, + ) -> Result<(bool, PlanOutcome)> { + let tables = self.tables.upgradable_read(); + let tables = self.as_ref(&tables.value); + let address = Address::from_u64(address); + let target_tier = address.size_tier(); + let offset = address.offset(); + let remains = tables.tables[target_tier as usize].write_dec_ref(offset, log)?; + + Ok((remains, PlanOutcome::Written)) + } + pub fn enact_plan(&self, action: LogAction, log: &mut LogReader) -> Result<()> { let tables = self.tables.read(); let reindex = self.reindex.read(); @@ -1259,6 +1300,15 @@ impl HashColumn { log::debug!(target: "parity-db", "Dropped {}", id); Ok(()) } + + pub fn get_num_value_entries(&self) -> Result { + let tables = self.tables.read(); + let mut num_entries = 0; + for value_table in &tables.value { + num_entries += value_table.get_num_entries()?; + } + Ok(num_entries) + } } impl Column { diff --git a/src/db.rs b/src/db.rs index 96a1a231..698a1d36 100644 --- a/src/db.rs +++ b/src/db.rs @@ -20,14 +20,17 @@ use crate::{ btree::{commit_overlay::BTreeChangeSet, BTreeIterator, BTreeTable}, - column::{hash_key, unpack_node_data, ColId, Column, IterState, ReindexBatch, ValueIterState}, + column::{ + hash_key, unpack_node_data, ColId, Column, HashColumn, IterState, ReindexBatch, + ValueIterState, + }, error::{try_io, Error, Result}, hash::IdentityBuildHasher, index::{Address, PlanOutcome}, log::{Log, LogAction}, multitree::{Children, NewNode, NodeAddress}, options::{Options, CURRENT_VERSION}, - parking_lot::{Condvar, Mutex, RwLock, RwLockUpgradableReadGuard}, + parking_lot::{Condvar, Mutex, RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, stats::StatSummary, ColumnOptions, Key, }; @@ -38,7 +41,7 @@ use std::{ ops::Bound, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, - Arc, + Arc, Weak, }, thread, }; @@ -133,7 +136,7 @@ struct CommitQueue { #[derive(Debug)] struct Trees { - readers: HashMap>, IdentityBuildHasher>, + readers: HashMap>, IdentityBuildHasher>, } #[derive(Debug)] @@ -337,30 +340,41 @@ impl DbInner { db: &Arc, col: ColId, key: &[u8], + check_existence: bool, ) -> Result>>> { match &self.columns[col as usize] { Column::Hash(column) => { - let key = column.hash_key(key); + // Check if the tree actually exists. We can't return the data from this function as + // TreeReader is not locked. That is done by the client. + if check_existence { + let root = self.get(col, key).unwrap(); + if root.is_none() { + return Ok(None) + } + } + + let hash_key = column.hash_key(key); let trees = self.trees.upgradable_read(); if let Some(column_trees) = trees.get(&col) { - if let Some(reader) = column_trees.readers.get(&key) { - let reader = reader.clone(); - return Ok(Some(reader)) + if let Some(reader) = column_trees.readers.get(&hash_key) { + let reader = reader.upgrade(); + if let Some(reader) = reader { + return Ok(Some(reader)) + } } } - // TODO: Check if the tree actually exists - let mut trees = RwLockUpgradableReadGuard::upgrade(trees); let column_trees = trees.entry(col).or_insert_with(|| Trees { readers: Default::default() }); - let reader = Arc::new(RwLock::new(DbTreeReader { db: db.clone(), col, key })); + let reader = + Arc::new(RwLock::new(DbTreeReader { db: db.clone(), col, key: hash_key })); - column_trees.readers.insert(key, reader.clone()); + column_trees.readers.insert(hash_key, Arc::downgrade(&reader)); Ok(Some(reader)) }, @@ -436,13 +450,31 @@ impl DbInner { .push_node_change(node_change); } }, - Operation::RemoveTree(..) => { - let root_operation = Operation::Dereference(change.key()); + Operation::RemoveTree(key) => { + let root_operation = Operation::Dereference(&key); commit .indexed .entry(col) .or_insert_with(|| IndexedChangeSet::new(col)) .push(root_operation, &self.options, self.db_version)?; + + let value = self.get(col, &key)?; + if let Some(data) = value { + let root_data = unpack_node_data(data)?; + let children = root_data.1; + + let node_change = NodeChange::DereferenceChildren(key, children); + + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push_node_change(node_change); + } else { + return Err(Error::InvalidConfiguration( + "No entry for tree root".to_string(), + )) + } }, }, Column::Tree(_) => @@ -517,7 +549,7 @@ impl DbInner { Ok(()) } - fn process_commits(&self) -> Result { + fn process_commits(&self, db: &Arc) -> Result { #[cfg(any(test, feature = "instrumentation"))] let might_wait_because_the_queue_is_full = self.options.with_background_thread; #[cfg(not(any(test, feature = "instrumentation")))] @@ -569,6 +601,8 @@ impl DbInner { let mut ops: u64 = 0; for (c, key_values) in commit.changeset.indexed.iter() { key_values.write_plan( + db, + *c, &self.columns[*c as usize], &mut writer, &mut ops, @@ -916,7 +950,7 @@ impl DbInner { self.cleanup_worker_wait.signal(); } - fn kill_logs(&self) -> Result<()> { + fn kill_logs(&self, db: &Arc) -> Result<()> { { if let Some(err) = self.bg_err.lock().as_ref() { // On error the log reader may be left in inconsistent state. So it is important @@ -930,7 +964,7 @@ impl DbInner { // Finish logged records and proceed to log and enact queued commits. while self.enact_logs(false)? {} self.flush_logs(0)?; - while self.process_commits()? {} + while self.process_commits(db)? {} while self.enact_logs(false)? {} self.flush_logs(0)?; while self.enact_logs(false)? {} @@ -1112,7 +1146,7 @@ impl Db { } pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>>> { - self.inner.get_tree(&self.inner, col, key) + self.inner.get_tree(&self.inner, col, key, true) } /// Commit a set of changes to the database. @@ -1186,7 +1220,7 @@ impl Db { db.log_worker_wait.wait(); } - more_commits = db.process_commits()?; + more_commits = db.process_commits(&db)?; more_reindex = db.process_reindex()?; } log::debug!(target: "parity-db", "Log worker shutdown"); @@ -1248,6 +1282,17 @@ impl Db { self.inner.stats() } + pub fn get_num_column_value_entries(&self, col: ColId) -> Result { + let column = &self.inner.columns[col as usize]; + match column { + Column::Hash(column) => return column.get_num_value_entries(), + Column::Tree(..) => + return Err(Error::InvalidConfiguration( + "get_num_column_value_entries not implemented for tree columns.".to_string(), + )), + } + } + // We open the DB before to check metadata validity and make sure there are no pending WAL // logs. fn precheck_column_operation(options: &mut Options) -> Result<[u8; 32]> { @@ -1372,7 +1417,7 @@ impl Db { log::warn!(target: "parity-db", "Cleanup thread shutdown error: {:?}", e); } } - if let Err(e) = self.inner.kill_logs() { + if let Err(e) = self.inner.kill_logs(&self.inner) { log::warn!(target: "parity-db", "Shutdown error: {:?}", e); } } @@ -1600,12 +1645,14 @@ impl, Value> Operation { } } -#[derive(Debug)] -pub struct NodeChange { - pub address: u64, - pub val: RcValue, - pub cval: RcValue, - pub compressed: bool, +#[derive(Debug, PartialEq, Eq)] +pub enum NodeChange { + /// (address, value, compressed value, compressed) + NewValue(u64, RcValue, RcValue, bool), + /// (address) + IncrementReference(u64), + /// Dereference and remove any of the children in the tree + DereferenceChildren(Vec, Children), } #[derive(Debug, Default)] @@ -1695,13 +1742,17 @@ impl IndexedChangeSet { } } for change in self.node_changes.iter() { - overlay.address.insert(change.address, (record_id, change.val.clone())); + if let NodeChange::NewValue(address, val, _cval, _compressed) = change { + overlay.address.insert(*address, (record_id, val.clone())); + } } Ok(()) } fn write_plan( &self, + db: &Arc, + col: ColId, column: &Column, writer: &mut crate::log::LogWriter, ops: &mut u64, @@ -1722,13 +1773,68 @@ impl IndexedChangeSet { *ops += 1; } for change in self.node_changes.iter() { - column.write_address_value_plan( - change.address, - change.cval.clone(), - change.compressed, - change.val.value().len() as u32, - writer, - )?; + match change { + NodeChange::NewValue(address, val, cval, compressed) => { + column.write_address_value_plan( + *address, + cval.clone(), + *compressed, + val.value().len() as u32, + writer, + )?; + }, + NodeChange::IncrementReference(address) => { + column.write_address_inc_ref_plan(*address, writer)?; + }, + NodeChange::DereferenceChildren(key, children) => { + let tree = db.get_tree(db, col, key, false).unwrap(); + if let Some(tree) = tree { + //println!("Locking tree {:?}", &key[0..3]); + let guard = tree.write(); + let mut num_removed = 0; + //println!("Dereferencing tree {:?}", &key[0..3]); + self.write_dereference_children_plan( + column, + &guard, + children, + &mut num_removed, + writer, + )?; + //println!("Dereferenced tree {:?}, removed {}", &key[0..3], num_removed); + } + // TODO: Remove TreeReader from Db. + }, + } + } + Ok(()) + } + + fn write_dereference_children_plan( + &self, + column: &HashColumn, + guard: &RwLockWriteGuard<'_, dyn TreeReader>, + children: &Vec, + num_removed: &mut u64, + writer: &mut crate::log::LogWriter, + ) -> Result<()> { + for address in children { + let node = guard.get_node(*address)?; + let (remains, _outcome) = column.write_address_dec_ref_plan(*address, writer)?; + if !remains { + // Was removed + *num_removed += 1; + if let Some((_node_data, children)) = node { + self.write_dereference_children_plan( + column, + guard, + &children, + num_removed, + writer, + )?; + } else { + return Err(Error::InvalidConfiguration("Missing node data".to_string())) + } + } } Ok(()) } @@ -1750,7 +1856,9 @@ impl IndexedChangeSet { } } for change in self.node_changes.iter() { - overlay.address.remove(&change.address); + if let NodeChange::NewValue(address, _val, _cval, _compressed) = change { + overlay.address.remove(address); + } } } } @@ -1865,7 +1973,7 @@ mod tests { if *self == EnableCommitPipelineStages::DbFile || *self == EnableCommitPipelineStages::LogOverlay { - while db.process_commits().unwrap() {} + while db.process_commits(db).unwrap() {} while db.process_reindex().unwrap() {} } if *self == EnableCommitPipelineStages::DbFile { diff --git a/src/table.rs b/src/table.rs index a34dc2d1..acc59ad3 100644 --- a/src/table.rs +++ b/src/table.rs @@ -447,7 +447,7 @@ impl ValueTable { dirty_header: AtomicBool::new(false), free_entries, multipart, - ref_counted: options.ref_counted, + ref_counted: options.ref_counted || options.multitree, db_version, }) } @@ -1177,6 +1177,25 @@ impl ValueTable { } Ok(len) } + + pub fn get_num_entries(&self) -> Result { + if let Some(free_entries) = &self.free_entries { + let filled = self.filled.load(Ordering::Relaxed); + let free_entries = free_entries.read(); + let num_free = free_entries.stack.len(); + let num = (filled - 1) - num_free as u64; + if num > 0 && self.multipart { + // TODO: Need to implement this. + return Err(crate::error::Error::InvalidConfiguration(format!( + "Unable to determine number of multipart entries" + ))) + } + return Ok(num) + } + Err(crate::error::Error::InvalidConfiguration(format!( + "Unable to determine number of entries" + ))) + } } pub mod key { From 73cf3ec9fd01a274ff75b3e9d522823f691a810e Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Mon, 24 Jul 2023 13:46:46 +0100 Subject: [PATCH 15/53] Empty on shutdown option. This removes all trees and waits for value tables to empty. --- admin/src/multitree_bench/mod.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 6cff8f9f..df3e94f3 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -70,6 +70,10 @@ pub struct MultiTreeStress { #[clap(long)] pub append: bool, + /// Remove all trees on shutdown and wait for the database to be empty. + #[clap(long)] + pub empty_on_shutdown: bool, + /// Number of trees to keep (Older are removed). 0 means never remove. [default: 8] #[clap(long)] pub pruning: Option, @@ -91,6 +95,7 @@ pub struct Args { pub commits: usize, pub seed: Option, pub append: bool, + pub empty_on_shutdown: bool, pub pruning: u64, pub compress: bool, pub commit_time: u64, @@ -105,6 +110,7 @@ impl MultiTreeStress { commits: self.commits.unwrap_or(100_000), seed: self.seed, append: self.append, + empty_on_shutdown: self.empty_on_shutdown, pruning: self.pruning.unwrap_or(8), compress: self.compress, commit_time: self.commit_time.unwrap_or(0), @@ -1127,22 +1133,28 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { iterations )); - // Continue removing trees until they are all gone. - TARGET_NUM_REMOVED.store(args.commits, Ordering::SeqCst); - while NUM_REMOVED.load(Ordering::Relaxed) < args.commits { - thread::sleep(std::time::Duration::from_millis(50)); - } + if args.empty_on_shutdown { + // Continue removing trees until they are all gone. + TARGET_NUM_REMOVED.store(args.commits, Ordering::SeqCst); + while NUM_REMOVED.load(Ordering::Relaxed) < args.commits { + thread::sleep(std::time::Duration::from_millis(50)); + } - // Wait for all entries to actually be removed from Db. - while !shutdown_final.load(Ordering::Relaxed) { - thread::sleep(std::time::Duration::from_millis(50)); + // Wait for all entries to actually be removed from Db. + while !shutdown_final.load(Ordering::Relaxed) { + thread::sleep(std::time::Duration::from_millis(50)); + } + } else { + shutdown_final.store(true, Ordering::SeqCst); } for t in threads.into_iter() { t.join().unwrap()?; } - output_helper.write().println_final(format!("Removed all entries")); + if args.empty_on_shutdown { + output_helper.write().println_final(format!("Removed all entries")); + } Ok(()) } From ba5a913034f6444bc8fe6e9266e3bfc63d7cab10 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 1 Aug 2023 15:24:04 +0100 Subject: [PATCH 16/53] Depth based age histograms for more accurate chain generation. Increased node sharing. --- admin/src/multitree_bench/data.rs | 10663 ++++++++++++++++------------ admin/src/multitree_bench/mod.rs | 210 +- 2 files changed, 6335 insertions(+), 4538 deletions(-) diff --git a/admin/src/multitree_bench/data.rs b/admin/src/multitree_bench/data.rs index 2a7ba0d1..6b5e2488 100644 --- a/admin/src/multitree_bench/data.rs +++ b/admin/src/multitree_bench/data.rs @@ -1,5677 +1,7379 @@ // Copyright 2021-2022 Parity Technologies (UK) Ltd. // This file is dual-licensed as Apache-2.0 or MIT. +pub const NUM_NODES: u32 = 2493773; +pub const AVERAGE_NUM_NEW_NODES: f64 = 614.359375; + pub const DEPTH_CHILD_COUNT_HISTOGRAMS: &[(u32, [u32; 17])] = &[ (0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), - (1, [0, 0, 9, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - (2, [9, 0, 11, 13, 4, 2, 3, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1]), - (3, [78, 0, 43, 15, 5, 2, 5, 0, 1, 0, 1, 0, 3, 2, 2, 7, 16]), - (4, [215, 0, 86, 56, 32, 40, 14, 22, 17, 26, 16, 13, 7, 12, 9, 11, 84]), - (5, [1355, 0, 578, 255, 168, 122, 55, 35, 23, 16, 9, 8, 9, 8, 16, 6, 778]), - (6, [3936, 0, 734, 287, 243, 234, 228, 354, 529, 752, 956, 965, 784, 537, 303, 293, 6120]), + (1, [0, 0, 7, 3, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (2, [9, 0, 10, 16, 4, 4, 2, 1, 1, 0, 1, 2, 1, 0, 0, 0, 1]), + (3, [79, 0, 42, 14, 11, 4, 2, 1, 3, 4, 0, 1, 0, 0, 2, 7, 21]), + (4, [230, 0, 79, 52, 41, 54, 35, 22, 26, 20, 22, 12, 8, 12, 9, 18, 109]), + (5, [1636, 0, 688, 380, 279, 190, 112, 50, 33, 20, 24, 14, 11, 9, 16, 8, 761]), + (6, [5337, 0, 1075, 317, 229, 215, 202, 314, 538, 827, 1114, 948, 845, 550, 329, 323, 6020]), ( 7, [ - 36666, 0, 20515, 8277, 4180, 3330, 4509, 7107, 10629, 14209, 15995, 15107, 11277, 6318, - 2522, 561, 1236, + 38815, 0, 21492, 8449, 3864, 3017, 4081, 6491, 9796, 13328, 15775, 15326, 12054, 7061, + 2971, 757, 1253, ], ), ( 8, [ - 610349, 0, 272521, 75786, 16430, 3401, 1955, 2547, 2898, 2788, 2450, 1912, 1400, 641, - 257, 96, 359, + 605659, 0, 277669, 80106, 17947, 3814, 2167, 2561, 2968, 2808, 2433, 1824, 1146, 679, + 239, 55, 355, ], ), - (9, [921168, 0, 65235, 9919, 1750, 334, 107, 203, 470, 656, 839, 963, 801, 470, 172, 57, 25]), - (10, [188318, 0, 17655, 4333, 924, 203, 20, 2, 0, 0, 5, 11, 17, 7, 0, 0, 0]), - (11, [50231, 0, 1485, 35, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - (12, [2917, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - (13, [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (9, [950869, 0, 66216, 9742, 1686, 346, 117, 213, 441, 735, 914, 934, 711, 447, 188, 36, 24]), + (10, [190606, 0, 17715, 4316, 895, 191, 24, 2, 1, 12, 5, 0, 1, 0, 2, 0, 0]), + (11, [50531, 0, 1471, 29, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (12, [2945, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (13, [12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), ]; -// Test data (not collected from Polkadot). -pub const AGE_HISTOGRAM: &[(u32, u32)] = &[ - (0, 100), - (1, 10), - (2, 5), - (3, 4), - (4, 4), - (5, 3), - (6, 3), - (7, 3), - (8, 2), - (9, 2), - (10, 2), - (11, 2), - (12, 1), - (13, 1), - (14, 1), - (15, 1), -]; - -pub const _KEY_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ - (5, 1), - (20, 1), - (32, 183), - (36, 14), - (44, 6247), - (48, 1727), - (52, 4381), - (53, 1), - (55, 32), - (56, 80), - (64, 549), - (65, 1), - (66, 67), - (68, 30), - (69, 667), - (72, 249742), - (73, 16), - (76, 304), - (77, 12321), - (80, 1238143), - (81, 503), - (84, 19113), - (92, 281057), - (120, 70), +pub const DEPTH_AGE_HISTOGRAMS: &[(u32, &[(u32, u32)])] = &[ + ( + 0, + &[ + (0, 520), + (1, 20), + (2, 22), + (3, 10), + (4, 14), + (5, 6), + (6, 9), + (7, 5), + (8, 5), + (9, 4), + (10, 4), + (11, 4), + (12, 4), + (13, 3), + (14, 4), + (15, 3), + (16, 2), + (17, 2), + (18, 2), + (19, 2), + (20, 2), + (21, 1), + (22, 1), + (23, 1), + (24, 1), + (25, 1), + (26, 1), + (27, 1), + (28, 1), + (29, 1), + (30, 1), + (31, 1), + (32, 1), + (33, 1), + (34, 1), + (35, 1), + (36, 1), + (37, 1), + (38, 1), + (39, 1), + (40, 1), + (41, 1), + (42, 1), + (43, 1), + (44, 1), + (45, 1), + (46, 1), + (47, 1), + (48, 1), + (49, 1), + (50, 1), + (51, 1), + (52, 1), + (53, 1), + (54, 1), + (55, 1), + (56, 1), + (57, 1), + (58, 1), + (59, 1), + (60, 1), + (61, 1), + (62, 1), + (63, 1), + (64, 2), + (65, 2), + (66, 2), + (67, 2), + (68, 2), + (69, 2), + (70, 2), + (71, 2), + (72, 2), + (73, 2), + (74, 2), + (75, 2), + (76, 2), + (77, 2), + (78, 1), + (79, 1), + (80, 1), + (81, 1), + (82, 1), + (83, 1), + (84, 1), + (85, 1), + (86, 1), + (87, 1), + (88, 1), + (89, 1), + (90, 1), + (91, 1), + (92, 1), + (93, 1), + (94, 1), + (95, 1), + (96, 2), + (97, 2), + (98, 2), + (99, 2), + (100, 2), + (101, 2), + (102, 2), + (103, 2), + (104, 2), + (105, 2), + (106, 2), + (107, 2), + (108, 2), + (109, 2), + (110, 2), + (111, 2), + (112, 2), + (113, 2), + (114, 2), + (115, 2), + (116, 3), + (117, 3), + (118, 3), + (119, 3), + (120, 3), + (121, 3), + (122, 3), + (123, 3), + (124, 3), + (125, 3), + (126, 3), + (127, 3), + (128, 2), + (129, 2), + (130, 2), + (131, 2), + (132, 2), + (133, 2), + (134, 2), + (135, 2), + (136, 2), + (137, 2), + (138, 2), + (139, 2), + (140, 2), + (141, 2), + (142, 2), + (143, 2), + (144, 2), + (145, 2), + (146, 2), + (147, 2), + (148, 2), + (149, 2), + (150, 2), + (151, 2), + (152, 2), + (153, 2), + (154, 2), + (155, 2), + (156, 2), + (157, 2), + (158, 2), + (159, 2), + (160, 1), + (161, 1), + (162, 1), + (163, 1), + (164, 1), + (165, 1), + (166, 1), + (167, 1), + (168, 1), + (169, 1), + (170, 1), + (171, 1), + (172, 1), + (173, 1), + (174, 1), + (175, 1), + (176, 1), + (177, 1), + (178, 1), + (179, 1), + (192, 2), + (193, 2), + (194, 2), + (195, 2), + (196, 2), + (197, 2), + (198, 2), + (199, 2), + (200, 2), + (201, 2), + (202, 2), + (203, 2), + (204, 2), + (205, 2), + (206, 2), + (207, 2), + (208, 2), + (209, 2), + (210, 2), + (211, 2), + (212, 2), + (213, 2), + (214, 2), + (215, 2), + (216, 2), + (217, 2), + (218, 2), + (219, 2), + (220, 2), + (221, 2), + (222, 2), + (223, 2), + (224, 2), + (225, 2), + (226, 2), + (227, 2), + (228, 2), + (229, 2), + (230, 2), + (231, 2), + (232, 2), + (233, 2), + (234, 2), + (235, 2), + (236, 2), + (237, 2), + (238, 2), + (239, 2), + (240, 2), + (241, 2), + (242, 2), + (243, 2), + (244, 2), + (245, 2), + (246, 2), + (247, 2), + (248, 2), + (249, 2), + (250, 2), + (251, 2), + (252, 2), + (253, 2), + (254, 2), + (255, 2), + ], + ), + ( + 1, + &[ + (0, 799), + (1, 14), + (2, 10), + (3, 4), + (4, 3), + (5, 2), + (6, 1), + (7, 1), + (8, 2), + (9, 1), + (10, 1), + (11, 1), + (12, 1), + (29, 1), + (78, 1), + (79, 1), + (80, 1), + (81, 1), + (82, 1), + (83, 1), + (84, 1), + (85, 1), + (86, 1), + (87, 1), + (88, 1), + (89, 1), + (90, 1), + (91, 1), + (92, 1), + (93, 1), + (94, 1), + (95, 1), + (96, 1), + (97, 1), + (98, 1), + (99, 1), + (100, 1), + (101, 1), + (102, 1), + (103, 1), + (104, 1), + (105, 1), + (106, 1), + (107, 1), + (108, 1), + (109, 1), + (110, 1), + (111, 1), + (112, 1), + (113, 1), + (114, 1), + (115, 1), + (116, 1), + (117, 1), + (118, 1), + (119, 1), + (120, 1), + (121, 1), + (122, 1), + (123, 1), + (124, 1), + (125, 1), + (126, 1), + (127, 1), + (128, 1), + (129, 1), + (130, 1), + (131, 1), + (132, 1), + (133, 1), + (134, 1), + (135, 1), + (136, 1), + (137, 1), + (138, 1), + (139, 1), + (140, 1), + (141, 1), + (192, 15), + (193, 16), + (194, 15), + (195, 16), + (196, 16), + (197, 14), + (198, 15), + (199, 15), + (200, 15), + (201, 17), + (202, 15), + (203, 14), + (204, 17), + (205, 15), + (206, 15), + (207, 14), + (208, 17), + (209, 16), + (210, 15), + (211, 15), + (212, 15), + (213, 15), + (214, 15), + (215, 15), + (216, 17), + (217, 15), + (218, 15), + (219, 17), + (220, 15), + (221, 17), + (222, 17), + (223, 14), + (224, 17), + (225, 15), + (226, 15), + (227, 16), + (228, 15), + (229, 14), + (230, 15), + (231, 17), + (232, 17), + (233, 15), + (234, 15), + (235, 17), + (236, 15), + (237, 16), + (238, 15), + (239, 16), + (240, 15), + (241, 15), + (242, 15), + (243, 14), + (244, 15), + (245, 14), + (246, 15), + (247, 14), + (248, 15), + (249, 14), + (250, 15), + (251, 15), + (252, 17), + (253, 17), + (254, 15), + (255, 14), + ], + ), + ( + 2, + &[ + (0, 2054), + (1, 36), + (2, 22), + (3, 17), + (4, 14), + (5, 9), + (6, 11), + (7, 6), + (8, 8), + (9, 5), + (10, 2), + (11, 2), + (12, 6), + (13, 1), + (14, 1), + (15, 2), + (16, 3), + (17, 3), + (18, 1), + (19, 2), + (20, 3), + (21, 2), + (22, 3), + (23, 2), + (24, 2), + (25, 3), + (26, 2), + (27, 2), + (28, 4), + (29, 2), + (30, 2), + (31, 3), + (32, 3), + (33, 3), + (34, 2), + (35, 2), + (36, 3), + (37, 2), + (38, 1), + (39, 2), + (40, 2), + (41, 1), + (42, 1), + (43, 2), + (44, 1), + (45, 2), + (46, 2), + (47, 1), + (48, 1), + (51, 1), + (60, 1), + (66, 1), + (86, 1), + (88, 1), + (105, 1), + (108, 1), + (109, 2), + (111, 1), + (112, 2), + (116, 1), + (124, 1), + (136, 1), + (154, 1), + (156, 1), + (160, 1), + (162, 1), + (166, 1), + (168, 1), + (170, 1), + (172, 2), + (176, 1), + (180, 1), + (182, 1), + (184, 1), + (192, 24), + (193, 18), + (194, 19), + (195, 18), + (196, 19), + (197, 18), + (198, 21), + (199, 19), + (200, 21), + (201, 19), + (202, 20), + (203, 18), + (204, 19), + (205, 19), + (206, 19), + (207, 23), + (208, 19), + (209, 18), + (210, 21), + (211, 19), + (212, 21), + (213, 19), + (214, 19), + (215, 20), + (216, 19), + (217, 19), + (218, 19), + (219, 19), + (220, 20), + (221, 19), + (222, 20), + (223, 18), + (224, 19), + (225, 19), + (226, 19), + (227, 18), + (228, 20), + (229, 18), + (230, 20), + (231, 19), + (232, 22), + (233, 19), + (234, 19), + (235, 19), + (236, 20), + (237, 18), + (238, 19), + (239, 18), + (240, 19), + (241, 19), + (242, 21), + (243, 18), + (244, 20), + (245, 18), + (246, 19), + (247, 18), + (248, 19), + (249, 18), + (250, 19), + (251, 19), + (252, 24), + (253, 19), + (254, 19), + (255, 18), + ], + ), + ( + 3, + &[ + (0, 3912), + (1, 395), + (2, 102), + (3, 97), + (4, 69), + (5, 72), + (6, 59), + (7, 60), + (8, 58), + (9, 41), + (10, 42), + (11, 45), + (12, 44), + (13, 49), + (14, 39), + (15, 37), + (16, 30), + (17, 25), + (18, 28), + (19, 23), + (20, 26), + (21, 23), + (22, 19), + (23, 24), + (24, 17), + (25, 15), + (26, 18), + (27, 16), + (28, 19), + (29, 17), + (30, 15), + (31, 17), + (32, 12), + (33, 15), + (34, 12), + (35, 9), + (36, 10), + (37, 9), + (38, 9), + (39, 9), + (40, 9), + (41, 11), + (42, 8), + (43, 8), + (44, 11), + (45, 10), + (46, 7), + (47, 6), + (48, 8), + (49, 6), + (50, 6), + (51, 7), + (52, 6), + (53, 7), + (54, 7), + (55, 6), + (56, 8), + (57, 4), + (58, 6), + (59, 6), + (60, 7), + (61, 4), + (62, 6), + (63, 6), + (64, 5), + (65, 5), + (66, 4), + (67, 5), + (68, 4), + (69, 5), + (70, 4), + (71, 7), + (72, 6), + (73, 6), + (74, 4), + (75, 4), + (76, 3), + (77, 3), + (78, 6), + (79, 3), + (80, 2), + (81, 2), + (82, 1), + (83, 1), + (84, 2), + (85, 2), + (86, 1), + (87, 2), + (88, 3), + (91, 2), + (92, 2), + (95, 1), + (96, 1), + (100, 1), + (103, 1), + (106, 1), + (108, 1), + (112, 1), + (114, 1), + (116, 2), + (117, 4), + (119, 1), + (132, 4), + (133, 2), + (134, 3), + (135, 1), + (140, 2), + (149, 1), + (150, 2), + (151, 1), + (161, 2), + (165, 3), + (168, 3), + (173, 3), + (177, 3), + (179, 2), + (183, 3), + (191, 3), + (192, 28), + (193, 21), + (194, 22), + (195, 20), + (196, 20), + (197, 20), + (198, 20), + (199, 19), + (200, 20), + (201, 19), + (202, 20), + (203, 20), + (204, 20), + (205, 20), + (206, 20), + (207, 38), + (208, 20), + (209, 20), + (210, 24), + (211, 20), + (212, 22), + (213, 20), + (214, 20), + (215, 21), + (216, 20), + (217, 19), + (218, 20), + (219, 19), + (220, 20), + (221, 20), + (222, 21), + (223, 20), + (224, 21), + (225, 21), + (226, 20), + (227, 21), + (228, 22), + (229, 20), + (230, 20), + (231, 20), + (232, 20), + (233, 20), + (234, 20), + (235, 21), + (236, 21), + (237, 20), + (238, 21), + (239, 20), + (240, 20), + (241, 20), + (242, 20), + (243, 20), + (244, 21), + (245, 20), + (246, 21), + (247, 20), + (248, 20), + (249, 20), + (250, 19), + (251, 19), + (252, 36), + (253, 20), + (254, 21), + (255, 20), + ], + ), + ( + 4, + &[ + (0, 14998), + (1, 1032), + (2, 194), + (3, 129), + (4, 91), + (5, 83), + (6, 55), + (7, 51), + (8, 51), + (9, 53), + (10, 47), + (11, 44), + (12, 35), + (13, 35), + (14, 27), + (15, 30), + (16, 25), + (17, 20), + (18, 25), + (19, 23), + (20, 15), + (21, 19), + (22, 16), + (23, 16), + (24, 13), + (25, 18), + (26, 13), + (27, 10), + (28, 13), + (29, 7), + (30, 5), + (31, 14), + (32, 7), + (33, 9), + (34, 17), + (35, 4), + (36, 6), + (37, 13), + (38, 10), + (39, 12), + (40, 6), + (41, 5), + (42, 15), + (43, 10), + (44, 9), + (45, 13), + (46, 12), + (47, 8), + (48, 7), + (49, 6), + (50, 5), + (51, 6), + (52, 2), + (53, 5), + (54, 6), + (55, 6), + (56, 7), + (57, 18), + (58, 2), + (59, 9), + (60, 16), + (61, 4), + (62, 17), + (63, 6), + (64, 7), + (65, 5), + (66, 7), + (67, 1), + (68, 5), + (69, 5), + (70, 5), + (71, 6), + (72, 8), + (73, 6), + (74, 7), + (75, 7), + (76, 4), + (77, 4), + (78, 7), + (79, 5), + (80, 6), + (81, 5), + (82, 2), + (83, 10), + (84, 6), + (85, 8), + (86, 6), + (87, 5), + (88, 5), + (89, 4), + (90, 6), + (91, 7), + (92, 3), + (93, 4), + (94, 5), + (95, 6), + (96, 9), + (97, 1), + (98, 4), + (99, 11), + (100, 6), + (101, 4), + (102, 7), + (103, 5), + (104, 4), + (105, 4), + (106, 8), + (107, 6), + (108, 1), + (109, 6), + (110, 2), + (111, 3), + (112, 2), + (113, 5), + (114, 1), + (115, 2), + (116, 4), + (117, 7), + (118, 5), + (119, 9), + (120, 5), + (121, 5), + (122, 4), + (123, 2), + (124, 4), + (125, 5), + (126, 4), + (127, 7), + (128, 7), + (129, 1), + (130, 3), + (131, 3), + (132, 2), + (133, 5), + (134, 7), + (135, 7), + (136, 7), + (137, 4), + (138, 4), + (139, 2), + (140, 11), + (141, 7), + (142, 4), + (143, 4), + (144, 2), + (145, 5), + (146, 3), + (147, 2), + (148, 3), + (149, 5), + (150, 5), + (151, 4), + (152, 5), + (153, 7), + (154, 3), + (155, 5), + (156, 5), + (157, 7), + (158, 4), + (159, 5), + (160, 4), + (161, 6), + (162, 2), + (163, 4), + (164, 8), + (165, 4), + (166, 4), + (167, 6), + (168, 15), + (169, 5), + (170, 7), + (171, 13), + (172, 1), + (173, 2), + (174, 3), + (175, 2), + (176, 12), + (177, 4), + (178, 3), + (179, 15), + (180, 5), + (181, 2), + (182, 6), + (183, 20), + (184, 10), + (185, 5), + (186, 1), + (187, 2), + (188, 6), + (189, 4), + (190, 3), + (191, 14), + (192, 74), + (193, 21), + (194, 45), + (195, 32), + (196, 36), + (197, 25), + (198, 23), + (199, 52), + (200, 44), + (201, 16), + (202, 44), + (203, 35), + (204, 18), + (205, 15), + (206, 30), + (207, 67), + (208, 39), + (209, 14), + (210, 29), + (211, 16), + (212, 31), + (213, 16), + (214, 27), + (215, 53), + (216, 21), + (217, 35), + (218, 49), + (219, 12), + (220, 62), + (221, 30), + (222, 19), + (223, 31), + (224, 20), + (225, 14), + (226, 30), + (227, 21), + (228, 31), + (229, 12), + (230, 32), + (231, 28), + (232, 18), + (233, 17), + (234, 38), + (235, 9), + (236, 43), + (237, 12), + (238, 31), + (239, 11), + (240, 22), + (241, 11), + (242, 20), + (243, 10), + (244, 22), + (245, 13), + (246, 22), + (247, 9), + (248, 18), + (249, 14), + (250, 40), + (251, 21), + (252, 94), + (253, 12), + (254, 19), + (255, 10), + ], + ), + ( + 5, + &[ + (0, 12542), + (1, 790), + (2, 646), + (3, 605), + (4, 561), + (5, 533), + (6, 524), + (7, 450), + (8, 417), + (9, 422), + (10, 346), + (11, 334), + (12, 303), + (13, 315), + (14, 278), + (15, 245), + (16, 246), + (17, 251), + (18, 223), + (19, 207), + (20, 188), + (21, 159), + (22, 182), + (23, 165), + (24, 159), + (25, 146), + (26, 137), + (27, 121), + (28, 119), + (29, 110), + (30, 113), + (31, 106), + (32, 98), + (33, 92), + (34, 82), + (35, 87), + (36, 68), + (37, 75), + (38, 70), + (39, 57), + (40, 68), + (41, 68), + (42, 52), + (43, 52), + (44, 45), + (45, 43), + (46, 42), + (47, 39), + (48, 39), + (49, 34), + (50, 37), + (51, 35), + (52, 25), + (53, 28), + (54, 26), + (55, 30), + (56, 31), + (57, 32), + (58, 32), + (59, 24), + (60, 27), + (61, 17), + (62, 27), + (63, 24), + (64, 20), + (65, 18), + (66, 20), + (67, 23), + (68, 18), + (69, 11), + (70, 11), + (71, 20), + (72, 20), + (73, 12), + (74, 13), + (75, 11), + (76, 19), + (77, 7), + (78, 12), + (79, 13), + (80, 12), + (81, 10), + (82, 6), + (83, 7), + (84, 10), + (85, 7), + (86, 8), + (87, 9), + (88, 13), + (89, 8), + (90, 8), + (91, 7), + (92, 11), + (93, 7), + (94, 6), + (95, 12), + (96, 9), + (97, 8), + (98, 8), + (99, 9), + (100, 10), + (101, 5), + (102, 4), + (103, 11), + (104, 10), + (105, 12), + (106, 5), + (107, 9), + (108, 5), + (109, 9), + (110, 8), + (111, 7), + (112, 7), + (113, 4), + (114, 3), + (115, 8), + (116, 9), + (117, 8), + (118, 3), + (119, 6), + (120, 6), + (121, 2), + (122, 8), + (123, 4), + (124, 7), + (125, 11), + (126, 4), + (127, 7), + (128, 7), + (129, 7), + (130, 6), + (131, 7), + (132, 5), + (133, 8), + (134, 7), + (135, 6), + (136, 7), + (137, 7), + (138, 9), + (139, 5), + (140, 4), + (141, 4), + (142, 5), + (143, 5), + (145, 4), + (146, 3), + (147, 6), + (148, 6), + (149, 4), + (150, 5), + (151, 2), + (152, 4), + (153, 3), + (154, 3), + (155, 4), + (156, 6), + (157, 6), + (159, 2), + (160, 8), + (161, 3), + (162, 2), + (163, 4), + (164, 3), + (165, 8), + (166, 7), + (167, 5), + (168, 10), + (169, 5), + (170, 5), + (171, 7), + (172, 3), + (173, 3), + (174, 4), + (175, 5), + (176, 6), + (177, 2), + (178, 2), + (179, 5), + (180, 5), + (181, 2), + (182, 1), + (183, 5), + (184, 4), + (185, 6), + (186, 7), + (187, 8), + (188, 4), + (189, 3), + (190, 4), + (191, 5), + (192, 128), + (193, 23), + (194, 67), + (195, 79), + (196, 34), + (197, 27), + (198, 27), + (199, 31), + (200, 78), + (201, 31), + (202, 31), + (203, 76), + (204, 27), + (205, 28), + (206, 24), + (207, 136), + (208, 83), + (209, 27), + (210, 23), + (211, 24), + (212, 27), + (213, 26), + (214, 33), + (215, 162), + (216, 25), + (217, 27), + (218, 106), + (219, 18), + (220, 112), + (221, 64), + (222, 22), + (223, 79), + (224, 22), + (225, 19), + (226, 82), + (227, 24), + (228, 25), + (229, 24), + (230, 61), + (231, 59), + (232, 22), + (233, 23), + (234, 76), + (235, 20), + (236, 95), + (237, 20), + (238, 69), + (239, 22), + (240, 21), + (241, 17), + (242, 21), + (243, 19), + (244, 18), + (245, 18), + (246, 22), + (247, 19), + (248, 22), + (249, 19), + (250, 26), + (251, 71), + (252, 192), + (253, 18), + (254, 22), + (255, 18), + ], + ), + ( + 6, + &[ + (0, 2615), + (1, 81), + (2, 62), + (3, 64), + (4, 75), + (5, 81), + (6, 77), + (7, 76), + (8, 64), + (9, 82), + (10, 73), + (11, 66), + (12, 67), + (13, 70), + (14, 78), + (15, 71), + (16, 70), + (17, 69), + (18, 67), + (19, 56), + (20, 65), + (21, 65), + (22, 84), + (23, 88), + (24, 66), + (25, 65), + (26, 58), + (27, 70), + (28, 55), + (29, 70), + (30, 64), + (31, 55), + (32, 53), + (33, 62), + (34, 75), + (35, 77), + (36, 62), + (37, 63), + (38, 68), + (39, 69), + (40, 55), + (41, 75), + (42, 68), + (43, 55), + (44, 74), + (45, 59), + (46, 50), + (47, 55), + (48, 64), + (49, 44), + (50, 67), + (51, 69), + (52, 57), + (53, 55), + (54, 61), + (55, 61), + (56, 57), + (57, 45), + (58, 63), + (59, 51), + (60, 65), + (61, 48), + (62, 64), + (63, 61), + (64, 49), + (65, 63), + (66, 50), + (67, 48), + (68, 57), + (69, 42), + (70, 59), + (71, 44), + (72, 51), + (73, 49), + (74, 59), + (75, 52), + (76, 46), + (77, 48), + (78, 59), + (79, 41), + (80, 53), + (81, 66), + (82, 57), + (83, 49), + (84, 37), + (85, 49), + (86, 54), + (87, 42), + (88, 54), + (89, 39), + (90, 42), + (91, 50), + (92, 57), + (93, 49), + (94, 53), + (95, 58), + (96, 50), + (97, 48), + (98, 40), + (99, 47), + (100, 46), + (101, 60), + (102, 40), + (103, 39), + (104, 41), + (105, 41), + (106, 46), + (107, 38), + (108, 40), + (109, 48), + (110, 45), + (111, 43), + (112, 47), + (113, 50), + (114, 49), + (115, 56), + (116, 54), + (117, 51), + (118, 64), + (119, 33), + (120, 38), + (121, 54), + (122, 49), + (123, 56), + (124, 46), + (125, 51), + (126, 55), + (127, 48), + (128, 42), + (129, 55), + (130, 55), + (131, 31), + (132, 48), + (133, 55), + (134, 31), + (135, 37), + (136, 44), + (137, 52), + (138, 38), + (139, 39), + (140, 40), + (141, 43), + (142, 46), + (143, 37), + (144, 56), + (145, 35), + (146, 38), + (147, 39), + (148, 39), + (149, 25), + (150, 41), + (151, 41), + (152, 47), + (153, 38), + (154, 40), + (155, 37), + (156, 33), + (157, 34), + (158, 36), + (159, 33), + (160, 40), + (161, 39), + (162, 31), + (163, 36), + (164, 48), + (165, 39), + (166, 35), + (167, 33), + (168, 42), + (169, 33), + (170, 28), + (171, 31), + (172, 31), + (173, 36), + (174, 41), + (175, 33), + (176, 31), + (177, 39), + (178, 29), + (179, 38), + (180, 34), + (181, 33), + (182, 34), + (183, 39), + (184, 36), + (185, 27), + (186, 27), + (187, 23), + (188, 39), + (189, 23), + (190, 30), + (191, 33), + (192, 207), + (193, 111), + (194, 134), + (195, 169), + (196, 128), + (197, 124), + (198, 108), + (199, 90), + (200, 182), + (201, 123), + (202, 109), + (203, 161), + (204, 108), + (205, 105), + (206, 127), + (207, 222), + (208, 176), + (209, 101), + (210, 111), + (211, 101), + (212, 120), + (213, 80), + (214, 136), + (215, 230), + (216, 101), + (217, 100), + (218, 173), + (219, 90), + (220, 202), + (221, 138), + (222, 93), + (223, 150), + (224, 89), + (225, 79), + (226, 170), + (227, 87), + (228, 95), + (229, 86), + (230, 138), + (231, 137), + (232, 99), + (233, 77), + (234, 158), + (235, 78), + (236, 177), + (237, 83), + (238, 155), + (239, 80), + (240, 93), + (241, 77), + (242, 108), + (243, 64), + (244, 90), + (245, 77), + (246, 81), + (247, 76), + (248, 77), + (249, 67), + (250, 88), + (251, 128), + (252, 264), + (253, 72), + (254, 76), + (255, 78), + ], + ), + ( + 7, + &[ + (0, 1579), + (1, 6), + (2, 9), + (3, 3), + (4, 7), + (5, 6), + (6, 6), + (7, 8), + (8, 4), + (9, 4), + (10, 4), + (11, 6), + (12, 4), + (13, 3), + (14, 8), + (15, 2), + (16, 5), + (17, 6), + (18, 7), + (19, 9), + (20, 3), + (21, 8), + (22, 5), + (23, 7), + (24, 1), + (25, 9), + (26, 12), + (27, 1), + (28, 5), + (29, 7), + (30, 8), + (31, 1), + (33, 5), + (34, 3), + (35, 6), + (36, 6), + (37, 4), + (38, 1), + (39, 7), + (40, 8), + (41, 4), + (42, 4), + (43, 5), + (44, 2), + (45, 6), + (46, 4), + (47, 8), + (48, 9), + (49, 4), + (50, 2), + (51, 4), + (52, 4), + (53, 11), + (54, 1), + (55, 2), + (56, 5), + (57, 10), + (58, 3), + (59, 2), + (60, 5), + (61, 4), + (62, 11), + (64, 2), + (65, 2), + (66, 12), + (67, 6), + (68, 10), + (69, 3), + (70, 2), + (71, 12), + (72, 4), + (73, 4), + (74, 4), + (75, 9), + (76, 7), + (77, 3), + (78, 8), + (79, 6), + (80, 2), + (81, 3), + (82, 5), + (83, 2), + (84, 8), + (85, 2), + (86, 3), + (87, 3), + (88, 2), + (89, 3), + (90, 6), + (91, 3), + (92, 4), + (93, 10), + (94, 7), + (95, 2), + (96, 1), + (97, 4), + (98, 12), + (99, 5), + (100, 4), + (101, 6), + (102, 3), + (103, 5), + (104, 9), + (105, 4), + (106, 4), + (107, 5), + (108, 8), + (109, 3), + (110, 2), + (111, 3), + (112, 8), + (113, 7), + (114, 5), + (115, 6), + (116, 5), + (117, 7), + (118, 3), + (119, 10), + (120, 5), + (121, 9), + (122, 3), + (123, 2), + (124, 2), + (125, 2), + (126, 8), + (127, 3), + (128, 7), + (129, 4), + (130, 2), + (131, 3), + (132, 7), + (133, 6), + (134, 6), + (135, 5), + (136, 3), + (137, 3), + (138, 10), + (139, 6), + (140, 1), + (141, 3), + (142, 6), + (143, 7), + (144, 11), + (145, 4), + (146, 5), + (147, 12), + (148, 4), + (149, 8), + (150, 4), + (151, 2), + (152, 4), + (153, 7), + (154, 6), + (155, 5), + (156, 6), + (157, 5), + (158, 8), + (159, 3), + (160, 1), + (161, 9), + (162, 8), + (163, 4), + (164, 6), + (165, 4), + (166, 7), + (167, 3), + (168, 7), + (169, 4), + (170, 5), + (171, 2), + (172, 5), + (173, 5), + (174, 6), + (175, 4), + (176, 2), + (177, 12), + (178, 4), + (179, 3), + (180, 4), + (181, 8), + (182, 6), + (183, 12), + (184, 6), + (185, 5), + (186, 1), + (187, 10), + (188, 6), + (189, 10), + (190, 7), + (191, 8), + (192, 76), + (193, 10), + (194, 45), + (195, 41), + (196, 13), + (197, 14), + (198, 12), + (199, 16), + (200, 62), + (201, 14), + (202, 12), + (203, 49), + (204, 14), + (205, 26), + (206, 12), + (207, 86), + (208, 49), + (209, 11), + (210, 22), + (211, 14), + (212, 18), + (213, 11), + (214, 20), + (215, 104), + (216, 19), + (217, 16), + (218, 61), + (219, 19), + (220, 72), + (221, 41), + (222, 7), + (223, 46), + (224, 19), + (225, 13), + (226, 59), + (227, 5), + (228, 15), + (229, 10), + (230, 35), + (231, 41), + (232, 11), + (233, 9), + (234, 58), + (235, 13), + (236, 66), + (237, 12), + (238, 50), + (239, 15), + (240, 10), + (241, 10), + (242, 11), + (243, 7), + (244, 15), + (245, 8), + (246, 15), + (247, 8), + (248, 13), + (249, 6), + (250, 7), + (251, 52), + (252, 120), + (253, 2), + (254, 19), + (255, 9), + ], + ), + ( + 8, + &[ + (0, 282), + (5, 1), + (11, 2), + (18, 2), + (20, 2), + (23, 2), + (24, 2), + (43, 2), + (54, 2), + (60, 2), + (68, 2), + (87, 2), + (95, 2), + (99, 2), + (127, 2), + (148, 2), + (158, 2), + (164, 2), + (169, 2), + (170, 2), + (185, 1), + (192, 19), + (194, 4), + (195, 4), + (200, 4), + (203, 7), + (207, 20), + (208, 5), + (212, 3), + (215, 18), + (218, 3), + (220, 7), + (221, 4), + (223, 4), + (225, 2), + (226, 5), + (229, 2), + (230, 3), + (231, 5), + (232, 2), + (234, 5), + (236, 17), + (238, 3), + (241, 2), + (245, 2), + (251, 12), + (252, 25), + (253, 2), + ], + ), + ( + 9, + &[ + (0, 14), + (28, 1), + (159, 2), + (192, 10), + (207, 12), + (215, 8), + (218, 2), + (236, 10), + (238, 1), + (252, 11), + ], + ), + (10, &[(0, 4), (192, 1), (207, 1), (215, 1), (252, 1)]), ]; pub const VALUE_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ - (1, 66581), - (2, 95), + (1, 66330), + (2, 100), (3, 1), - (4, 283269), - (5, 1308), - (6, 169), - (7, 3), - (8, 73), - (9, 10), + (4, 267500), + (5, 1304), + (6, 182), + (7, 45), + (8, 108), + (9, 11), (10, 2), - (11, 205), - (12, 5), - (13, 4), - (14, 4), - (15, 7), - (16, 559), - (17, 418), - (18, 3), - (19, 4), - (20, 609), - (21, 57), - (22, 1), - (23, 1), + (11, 6), + (12, 255), + (13, 6), + (14, 5), + (15, 25), + (16, 595), + (17, 441), + (18, 2), + (19, 373), + (20, 591), + (21, 60), + (23, 2), (24, 6), - (25, 5), - (26, 69428), + (25, 7), + (26, 69031), (27, 1), (28, 6), - (29, 8), - (30, 9), - (31, 12), - (32, 85052), - (33, 3212), - (34, 116), - (35, 220), - (36, 454), - (37, 10344), - (38, 9378), + (29, 22), + (30, 10), + (31, 10), + (32, 84843), + (33, 3429), + (34, 119), + (35, 224), + (36, 288), + (37, 13121), + (38, 9153), (39, 31), - (40, 23), - (41, 27), - (42, 17), - (43, 18), - (44, 20), - (45, 19), - (46, 74), - (47, 7), - (48, 175), - (49, 3835), - (50, 1851), - (51, 890), - (52, 29), - (53, 85), - (54, 2992), - (55, 15), - (56, 98), - (57, 688), - (58, 34), - (59, 22), - (60, 21), - (61, 12), - (62, 14), - (63, 9), - (64, 21), - (65, 187), - (66, 176), - (67, 16), - (68, 12), - (69, 38), - (70, 2318), - (71, 20), - (72, 19), - (73, 94), - (74, 25), - (75, 12), - (76, 1778), - (77, 50), + (40, 26), + (41, 29), + (42, 18), + (43, 44), + (44, 46), + (45, 21), + (46, 70), + (47, 6), + (48, 47), + (49, 3852), + (50, 3006), + (51, 1059), + (52, 28), + (53, 147), + (54, 3619), + (55, 84), + (56, 90), + (57, 801), + (58, 32), + (59, 21), + (60, 29), + (61, 16), + (62, 19), + (63, 10), + (64, 23), + (65, 186), + (66, 177), + (67, 15), + (68, 14), + (69, 33), + (70, 2229), + (71, 19), + (72, 17), + (73, 128), + (74, 22), + (75, 14), + (76, 2786), + (77, 76), (78, 22), - (79, 21), - (80, 1098004), - (81, 44), - (82, 295), - (83, 132), - (84, 17), - (85, 96), - (86, 27), - (87, 12), - (88, 150), - (89, 360), - (90, 517), - (91, 85), + (79, 19), + (80, 1136051), + (81, 43), + (82, 297), + (83, 136), + (84, 23), + (85, 122), + (86, 29), + (87, 14), + (88, 148), + (89, 295), + (90, 961), + (91, 124), (92, 22), - (93, 7), - (94, 22), - (95, 79), - (96, 86), - (97, 88), - (98, 388), + (93, 8), + (94, 21), + (95, 56), + (96, 103), + (97, 107), + (98, 645), (99, 14), (100, 44), - (101, 36), - (102, 2957), + (101, 199), + (102, 5085), (103, 11), - (104, 22), - (105, 24), - (106, 14), - (107, 8), - (108, 24), - (109, 81), - (110, 13), + (104, 21), + (105, 30), + (106, 16), + (107, 22), + (108, 16), + (109, 85), + (110, 17), (111, 11), - (112, 18), - (113, 23), - (114, 45194), + (112, 20), + (113, 22), + (114, 44262), (115, 503), - (116, 18), + (116, 25), (117, 11), (118, 13), - (119, 10), - (120, 167), - (121, 38), - (122, 43), + (119, 9), + (120, 372), + (121, 32), + (122, 47), (123, 67), - (124, 17), + (124, 26), (125, 10), - (126, 23), - (127, 17), - (128, 191), - (129, 241), - (130, 139), + (126, 21), + (127, 29), + (128, 187), + (129, 211), + (130, 138), (131, 6), - (132, 24), - (133, 15), - (134, 1944), - (135, 14), - (136, 16), + (132, 25), + (133, 13), + (134, 1865), + (135, 11), + (136, 13), (137, 13), - (138, 5), + (138, 4), (139, 5), - (140, 11), - (141, 13), - (142, 66), - (143, 4), - (144, 12), - (145, 58), - (146, 16), - (147, 2), - (148, 20), - (149, 2), + (140, 9), + (141, 11), + (142, 157), + (143, 6), + (144, 11), + (145, 94), + (146, 11), + (147, 1), + (148, 17), + (149, 4), (150, 1), - (151, 2), - (152, 128), - (153, 29), - (154, 2), + (151, 9), + (152, 3), + (153, 20), + (154, 1), (155, 1), - (156, 5), - (157, 1), + (156, 137), + (157, 2), (158, 4), (159, 3), - (160, 7), - (161, 41), - (162, 9), - (163, 2), - (164, 41), - (165, 29), - (166, 1891), - (167, 60), - (168, 70), - (169, 52), - (170, 63), + (160, 5), + (161, 40), + (162, 10), + (163, 13), + (164, 113), + (165, 26), + (166, 1681), + (167, 72), + (168, 60), + (169, 99), + (170, 64), (171, 2), - (172, 6), - (173, 28), - (174, 8), + (172, 2), + (173, 33), + (174, 14), + (175, 5), (176, 3), - (177, 5), + (177, 9), (178, 7), (179, 1), (180, 2), - (181, 52), - (182, 2), - (184, 2), - (185, 2), - (186, 30), - (188, 28), + (181, 59), + (182, 3), + (183, 1), + (185, 1), + (186, 115), + (188, 24), (189, 2), - (190, 4), - (192, 1918), + (190, 3), + (192, 1965), (193, 27), - (194, 2), + (194, 1), (195, 2), - (196, 2), + (196, 3), (197, 9), - (198, 1454), - (199, 23), - (200, 1), + (198, 1440), + (199, 98), + (200, 4), (201, 4), - (202, 26), - (203, 1), + (202, 22), + (204, 1), (205, 8), - (206, 66), - (207, 44), - (208, 139), - (209, 42), - (210, 44), - (211, 6), - (212, 22), - (213, 6), - (214, 5), - (216, 6), - (217, 29), + (206, 28), + (207, 22), + (208, 186), + (209, 35), + (210, 160), + (211, 3), + (212, 12), + (213, 16), + (214, 8), + (216, 23), + (217, 51), (218, 2), - (219, 1), (220, 3), (221, 2), (222, 2), (223, 2), - (225, 14), - (226, 1), - (228, 4), - (229, 1), - (230, 1178), + (225, 13), + (226, 4), + (228, 6), + (229, 2), + (230, 1224), (232, 1), (233, 3), - (234, 3), - (237, 2), + (234, 4), + (235, 1), + (237, 1), (238, 3), - (239, 4), - (241, 1), + (239, 25), + (241, 5), (242, 6), (243, 1), - (244, 8), - (245, 28), - (246, 38), - (247, 41), - (248, 17), - (249, 32), - (250, 81), - (251, 18), - (252, 24), - (253, 36), - (254, 1), - (255, 3), - (257, 13), - (258, 5), - (259, 1), + (244, 9), + (245, 41), + (246, 35), + (247, 20), + (248, 18), + (249, 20), + (250, 59), + (251, 13), + (252, 49), + (253, 33), + (255, 1), + (257, 11), + (258, 3), + (259, 2), (260, 1), - (261, 2), - (262, 1306), - (264, 16), + (261, 6), + (262, 1247), + (264, 15), (265, 3), - (266, 10), - (268, 7), + (266, 9), + (268, 8), (269, 8), - (270, 21), - (272, 10), - (273, 11), - (274, 30), - (276, 7), - (277, 3), - (278, 10), - (279, 7), - (280, 10), + (270, 23), + (271, 162), + (272, 11), + (273, 10), + (274, 91), + (276, 5), + (277, 4), + (278, 8), + (279, 8), + (280, 8), (281, 7), - (282, 4), - (283, 9), - (284, 56), + (282, 5), + (283, 10), + (284, 59), (285, 39), - (286, 35), - (287, 22), - (288, 32), - (289, 55), - (290, 41), - (291, 2), - (292, 2), + (286, 34), + (287, 25), + (288, 30), + (289, 64), + (290, 36), + (291, 5), + (292, 10), (293, 5), - (294, 992), + (294, 990), (295, 8), - (296, 10), + (296, 59), (297, 1), - (298, 6), + (298, 5), (300, 1), - (301, 2), - (303, 7), - (305, 5), + (301, 3), + (303, 8), + (305, 7), (306, 2), (307, 5), - (308, 1), - (309, 1), - (311, 3), + (309, 2), + (311, 6), (313, 3), (315, 3), - (317, 1), - (318, 12), - (319, 1), - (321, 22), - (322, 3), - (323, 33), - (324, 39), - (325, 29), - (326, 1337), - (327, 29), - (328, 20), - (329, 32), - (330, 17), - (331, 12), - (332, 1), + (317, 2), + (318, 55), + (319, 2), + (321, 18), + (322, 1), + (323, 67), + (324, 28), + (325, 36), + (326, 1303), + (327, 21), + (328, 33), + (329, 36), + (330, 9), + (331, 11), + (332, 4), (333, 4), - (334, 4), - (335, 9), - (336, 2), - (337, 5), + (334, 3), + (335, 10), + (336, 4), + (337, 3), (338, 1), (339, 7), - (340, 13), + (340, 39), (341, 1), - (342, 3), - (343, 6), + (342, 1), + (343, 4), (344, 8), (345, 2), - (347, 8), - (349, 2), + (346, 1), + (347, 4), + (349, 8), (350, 3), - (351, 5), - (352, 1), - (353, 13), + (351, 7), + (353, 11), (354, 2), - (355, 12), - (357, 3), - (358, 1063), - (359, 9), + (355, 11), + (357, 1), + (358, 1030), + (359, 7), (360, 6), (361, 9), - (362, 22), - (363, 62), - (364, 17), - (365, 26), - (366, 21), - (367, 25), - (368, 25), - (369, 30), - (370, 7), - (371, 21), - (373, 18), - (374, 4), - (375, 90), - (377, 27), - (378, 8), - (379, 125), - (380, 2), + (362, 46), + (363, 68), + (364, 39), + (365, 18), + (366, 19), + (367, 31), + (368, 44), + (369, 24), + (370, 8), + (371, 39), + (372, 2), + (373, 17), + (374, 5), + (375, 74), + (376, 1), + (377, 26), + (378, 7), + (379, 156), + (380, 3), (381, 34), - (382, 51), - (383, 18996), - (384, 52), - (385, 33308), - (386, 7601), - (387, 949), - (388, 3922), - (389, 72), - (390, 1089), - (391, 287), - (392, 175), - (393, 571), - (394, 352), - (395, 35), - (396, 92), - (397, 29), - (398, 5), - (399, 9), - (400, 14), - (401, 44), - (402, 50), - (403, 54), - (404, 26), - (405, 19), - (406, 12), - (407, 15), - (408, 9), - (409, 25), - (410, 7), - (412, 5), - (413, 2), - (415, 1), + (382, 49), + (383, 18546), + (384, 55), + (385, 33545), + (386, 7395), + (387, 982), + (388, 3862), + (389, 73), + (390, 1055), + (391, 281), + (392, 151), + (393, 579), + (394, 317), + (395, 31), + (396, 84), + (397, 32), + (398, 4), + (399, 10), + (400, 11), + (401, 45), + (402, 73), + (403, 90), + (404, 25), + (405, 24), + (406, 18), + (407, 28), + (408, 39), + (409, 19), + (410, 4), + (411, 4), + (412, 1), + (413, 1), + (414, 2), + (415, 2), (417, 12), - (418, 1), - (419, 2), - (422, 1086), - (424, 1), - (425, 4), - (426, 1), - (427, 2), - (428, 2), - (429, 2), + (418, 5), + (419, 4), + (420, 1), + (421, 1), + (422, 1033), + (424, 2), + (425, 2), + (426, 4), + (428, 7), + (429, 3), (431, 2), + (432, 4), (433, 3), (436, 7), - (440, 8), - (441, 48), - (442, 38), - (443, 25), - (444, 11), - (445, 9), - (446, 14), - (447, 16), - (448, 5), - (449, 18), - (450, 15), - (452, 2), - (454, 1085), - (455, 5), - (456, 1), + (437, 1), + (438, 2), + (440, 25), + (441, 82), + (442, 117), + (443, 40), + (444, 19), + (445, 13), + (446, 23), + (447, 19), + (448, 11), + (449, 7), + (450, 14), + (451, 2), + (454, 1097), + (455, 2), + (456, 2), (460, 1), - (461, 1), - (465, 1), - (469, 2), - (471, 1), - (472, 6), + (463, 1), + (465, 4), + (466, 1), + (469, 3), + (470, 1), + (472, 3), + (474, 1), (477, 1), - (478, 2), - (479, 5), - (480, 18), - (481, 90), - (482, 31), - (483, 9), - (484, 7), - (485, 12), - (486, 1796), - (487, 7), + (479, 8), + (480, 73), + (481, 132), + (482, 65), + (483, 18), + (484, 11), + (485, 31), + (486, 1711), + (487, 9), (488, 7), (489, 8), - (490, 5), - (491, 3), - (492, 1), + (490, 2), + (491, 1), (493, 2), - (494, 2), + (494, 4), (495, 1), - (497, 1), + (500, 1), (501, 1), - (513, 7), - (516, 10), - (518, 14326), - (519, 21), - (520, 35), - (521, 20), - (522, 3), - (523, 10), - (524, 17), - (525, 8), - (526, 11), - (527, 6), - (528, 4), + (502, 1), + (513, 8), + (516, 3), + (518, 14410), + (519, 55), + (520, 99), + (521, 76), + (522, 21), + (523, 19), + (524, 24), + (525, 15), + (526, 4), + (527, 4), + (528, 1), (529, 3), - (530, 2), - (533, 1), - (534, 2), - (538, 3), + (530, 10), + (535, 1), + (537, 1), + (538, 14), (543, 1), (545, 7), - (549, 1), - (557, 1), - (558, 13), - (559, 17), - (560, 13), - (561, 7), - (562, 18), - (563, 14), - (564, 9), - (565, 9), - (566, 7), - (567, 8), - (568, 2), - (569, 5), - (570, 2), - (572, 2), - (573, 2), + (557, 4), + (558, 28), + (559, 45), + (560, 64), + (561, 22), + (562, 10), + (563, 13), + (564, 15), + (565, 14), + (566, 1), + (567, 4), + (569, 6), + (570, 7), + (572, 4), + (573, 3), (577, 1), - (582, 4), - (596, 11), - (597, 4), - (598, 7), - (599, 4), - (600, 8), + (578, 1), + (582, 11), + (591, 2), + (596, 12), + (597, 16), + (598, 23), + (599, 28), + (600, 18), (601, 20), (602, 20), - (603, 6), - (604, 12), - (605, 14), - (606, 4), + (603, 20), + (604, 36), + (605, 6), + (606, 3), (607, 1), - (608, 3), - (609, 2), - (610, 5), (612, 1), - (613, 1), + (613, 2), (614, 1), (617, 1), - (624, 1), - (626, 1), - (630, 1), - (635, 15), - (636, 6), - (637, 8), - (638, 11), - (639, 2), - (640, 15), - (641, 25), - (642, 15), - (643, 17), - (644, 10), - (645, 2), - (646, 2), - (647, 16), - (648, 5), + (626, 7), + (628, 1), + (635, 16), + (636, 11), + (637, 12), + (638, 16), + (639, 19), + (640, 10), + (641, 16), + (642, 18), + (643, 33), + (644, 7), + (645, 4), + (648, 7), (649, 2), - (650, 2), - (653, 1), - (670, 4), + (650, 1), + (655, 3), + (656, 3), + (657, 1), + (670, 12), (673, 6), - (674, 15), - (676, 9), - (677, 6), - (678, 2), - (679, 15), - (680, 17), - (681, 18), - (682, 15), - (683, 7), - (685, 1), - (686, 1), - (687, 1), + (674, 7), + (675, 15), + (676, 18), + (677, 17), + (678, 3), + (679, 12), + (680, 10), + (681, 11), + (682, 23), + (683, 8), + (684, 9), + (685, 2), + (687, 2), (688, 1), (689, 1), - (690, 1), - (691, 2), - (693, 1), - (709, 1), - (713, 13), - (714, 7), - (715, 7), - (716, 2), - (717, 3), + (692, 23), + (695, 3), + (696, 2), + (703, 1), + (706, 1), + (708, 1), + (713, 8), + (714, 34), + (715, 16), + (716, 12), + (717, 5), (718, 6), - (719, 17), - (720, 14), - (721, 8), - (722, 3), - (723, 4), - (724, 4), - (725, 1), - (726, 3), - (727, 1), - (728, 1), - (729, 1), - (730, 2), - (731, 1), + (719, 8), + (720, 8), + (721, 11), + (722, 5), + (723, 7), + (724, 7), + (726, 2), + (727, 2), + (730, 1), + (734, 3), + (735, 5), (736, 3), (737, 1), - (752, 19), - (753, 5), - (754, 9), - (755, 6), - (756, 2), - (757, 3), - (758, 16), - (759, 9), + (745, 3), + (750, 1), + (752, 18), + (753, 13), + (754, 13), + (755, 5), + (756, 12), + (757, 5), + (758, 7), + (759, 10), (760, 12), - (761, 11), - (763, 1), - (764, 3), - (765, 5), - (766, 1), - (768, 1), - (769, 2), - (770, 4), - (772, 1), - (780, 3), + (761, 16), + (762, 7), + (763, 3), + (764, 2), + (765, 3), + (770, 1), + (774, 2), + (776, 1), + (780, 1), (785, 1), (789, 6), - (791, 15), - (792, 6), - (793, 16), - (794, 1), - (795, 2), - (796, 5), - (797, 12), - (798, 15), - (799, 18), - (800, 6), - (801, 1), - (802, 8), - (803, 1), - (808, 3), - (809, 1), - (810, 2), - (814, 1), + (791, 16), + (792, 10), + (793, 29), + (794, 10), + (795, 12), + (796, 7), + (797, 10), + (798, 12), + (799, 9), + (800, 4), + (801, 3), + (802, 7), + (803, 5), + (804, 6), + (805, 1), + (808, 2), + (811, 1), + (813, 3), + (816, 1), (824, 1), - (830, 13), - (831, 7), - (832, 8), - (833, 8), - (834, 7), - (835, 3), - (836, 13), + (830, 15), + (831, 4), + (832, 15), + (833, 12), + (834, 14), + (835, 11), + (836, 12), (837, 8), - (838, 9), - (839, 4), - (841, 3), - (842, 2), - (843, 4), - (844, 1), - (846, 2), + (838, 7), + (839, 6), + (840, 5), + (841, 7), + (842, 3), + (843, 3), + (844, 2), + (845, 1), + (846, 1), (847, 5), - (849, 2), - (853, 1), - (854, 1), - (855, 1), - (868, 2), - (869, 13), - (870, 6), - (871, 10), - (872, 2), - (873, 2), - (874, 2), - (875, 10), - (876, 15), - (877, 14), - (878, 5), - (879, 4), - (880, 2), - (881, 3), - (882, 5), - (883, 2), - (884, 2), - (886, 1), - (888, 1), - (889, 2), - (890, 2), - (891, 2), - (908, 3), - (909, 5), - (910, 10), - (911, 5), - (912, 6), - (914, 3), - (915, 3), - (916, 8), - (917, 2), - (918, 6), - (919, 1), - (920, 7), - (921, 5), - (922, 2), - (923, 3), - (926, 2), - (927, 2), - (929, 2), - (930, 5), + (849, 1), + (852, 2), + (860, 1), + (869, 19), + (870, 4), + (871, 12), + (872, 10), + (873, 7), + (874, 13), + (875, 9), + (876, 7), + (877, 12), + (878, 6), + (879, 5), + (880, 1), + (881, 7), + (882, 10), + (883, 3), + (887, 1), + (888, 2), + (890, 3), + (891, 4), + (908, 1), + (909, 3), + (910, 9), + (911, 7), + (912, 14), + (913, 14), + (914, 7), + (915, 5), + (916, 9), + (917, 9), + (918, 2), + (919, 5), + (920, 6), + (921, 1), + (922, 1), + (924, 1), + (926, 1), + (927, 3), + (928, 4), + (930, 12), (931, 2), - (932, 5), - (933, 2), - (934, 3), - (947, 3), - (948, 6), - (949, 7), - (950, 2), + (932, 3), + (934, 2), + (948, 5), + (949, 9), + (950, 7), (951, 5), - (952, 1), - (953, 3), - (954, 7), - (955, 10), + (952, 11), + (953, 14), + (954, 12), + (955, 6), (956, 6), - (957, 3), - (958, 6), - (959, 10), - (960, 3), - (961, 4), + (957, 1), + (958, 4), + (959, 6), + (960, 4), + (961, 1), (962, 1), - (966, 1), - (967, 1), - (968, 3), - (969, 10), - (970, 9), - (971, 3), - (972, 3), + (968, 2), + (969, 7), + (970, 12), + (971, 4), + (972, 2), (977, 1), - (978, 3), + (978, 2), (986, 2), - (987, 5), - (988, 16), + (987, 3), + (988, 13), (989, 3), - (990, 3), - (991, 1), - (992, 7), - (993, 7), - (994, 11), - (995, 4), - (996, 10), - (997, 6), - (998, 4), - (999, 2), + (990, 4), + (991, 11), + (992, 10), + (993, 5), + (994, 10), + (995, 7), + (996, 6), + (997, 2), + (998, 5), + (999, 1), (1000, 1), - (1001, 1), - (1002, 2), + (1002, 3), (1005, 1), - (1008, 7), - (1009, 7), - (1010, 9), - (1011, 6), - (1012, 1), - (1013, 1), - (1014, 2), - (1022, 3), + (1008, 5), + (1009, 8), + (1010, 5), + (1011, 3), + (1012, 2), + (1022, 4), (1025, 1), - (1026, 10), - (1027, 10), - (1028, 6), - (1029, 2), - (1030, 6), - (1031, 6), - (1032, 13), - (1033, 10), - (1034, 3), - (1035, 6), - (1036, 7), - (1037, 4), - (1038, 1), - (1040, 1), - (1041, 1), - (1044, 7), - (1046, 5), - (1047, 11), - (1048, 4), - (1050, 1), - (1052, 2), - (1065, 10), - (1066, 9), - (1067, 4), - (1068, 3), - (1069, 4), - (1070, 1), - (1071, 4), - (1072, 11), - (1073, 4), - (1074, 4), + (1026, 6), + (1027, 8), + (1028, 5), + (1029, 5), + (1030, 10), + (1031, 7), + (1032, 8), + (1033, 12), + (1034, 6), + (1035, 4), + (1039, 2), + (1040, 4), + (1041, 4), + (1044, 6), + (1047, 10), + (1048, 3), + (1049, 5), + (1050, 4), + (1051, 1), + (1055, 2), + (1064, 2), + (1065, 2), + (1066, 5), + (1068, 1), + (1069, 3), + (1070, 5), + (1071, 8), + (1072, 12), + (1073, 8), + (1074, 5), (1075, 1), - (1076, 2), - (1077, 1), - (1078, 2), - (1079, 5), - (1085, 1), - (1086, 7), - (1087, 4), - (1088, 3), - (1089, 2), - (1104, 4), - (1105, 9), - (1106, 5), - (1107, 2), - (1108, 4), - (1109, 4), - (1110, 14), + (1076, 1), + (1080, 5), + (1085, 2), + (1086, 5), + (1087, 8), + (1088, 7), + (1089, 1), + (1090, 1), + (1105, 2), + (1106, 4), + (1107, 6), + (1108, 12), + (1109, 7), + (1110, 9), (1111, 12), - (1112, 8), - (1113, 2), - (1114, 3), - (1115, 1), - (1116, 1), - (1117, 4), - (1118, 3), - (1124, 1), + (1112, 12), + (1113, 4), + (1114, 2), + (1115, 2), + (1117, 1), + (1119, 2), (1125, 4), - (1126, 10), - (1127, 3), + (1126, 4), + (1127, 6), + (1128, 2), + (1131, 1), + (1132, 2), (1141, 6), - (1143, 6), - (1144, 12), - (1145, 5), + (1143, 7), + (1144, 9), + (1145, 13), (1146, 3), - (1147, 4), - (1148, 4), - (1149, 6), - (1150, 7), + (1147, 6), + (1148, 5), + (1149, 7), + (1150, 6), (1151, 7), - (1152, 1), + (1152, 3), (1153, 2), (1154, 1), (1155, 2), - (1156, 2), - (1164, 2), - (1165, 8), - (1166, 6), + (1164, 1), + (1165, 6), + (1166, 4), (1167, 3), - (1168, 2), - (1171, 1), (1176, 1), (1181, 1), - (1182, 3), - (1183, 11), - (1184, 3), - (1185, 4), - (1186, 4), - (1187, 3), + (1183, 8), + (1184, 1), + (1185, 3), + (1186, 3), + (1187, 4), (1188, 7), - (1189, 6), - (1190, 5), - (1191, 1), - (1193, 1), - (1196, 1), - (1198, 3), - (1202, 1), - (1203, 4), - (1204, 3), - (1205, 9), - (1206, 7), + (1189, 7), + (1190, 13), + (1191, 8), + (1192, 2), + (1193, 3), + (1194, 2), + (1198, 2), + (1204, 1), + (1205, 3), + (1206, 1), (1207, 3), - (1208, 1), - (1210, 1), - (1220, 4), - (1221, 3), - (1222, 5), - (1223, 4), - (1224, 1), - (1225, 2), - (1226, 5), - (1227, 14), - (1228, 6), - (1229, 4), - (1230, 4), - (1231, 3), - (1232, 3), + (1221, 4), + (1223, 3), + (1224, 5), + (1225, 1), + (1226, 4), + (1227, 5), + (1228, 8), + (1229, 6), + (1230, 5), + (1231, 5), + (1232, 4), + (1233, 1), (1234, 1), - (1242, 5), (1243, 1), - (1244, 5), - (1245, 6), - (1246, 2), - (1247, 3), + (1244, 1), + (1245, 2), (1248, 1), - (1249, 1), - (1259, 4), - (1260, 1), + (1258, 1), + (1259, 2), (1261, 1), - (1262, 6), - (1263, 5), - (1264, 4), - (1265, 3), - (1266, 3), - (1267, 9), - (1268, 2), - (1269, 7), - (1270, 2), - (1281, 2), - (1283, 3), - (1284, 3), - (1286, 3), - (1287, 1), - (1288, 1), + (1262, 1), + (1263, 4), + (1264, 8), + (1265, 4), + (1266, 7), + (1267, 18), + (1268, 8), + (1269, 6), + (1270, 3), + (1271, 2), + (1272, 1), + (1285, 2), + (1286, 1), (1296, 6), (1298, 1), - (1299, 1), - (1300, 7), - (1301, 3), - (1302, 3), - (1303, 1), - (1304, 8), - (1305, 10), - (1306, 11), - (1307, 4), - (1308, 3), + (1300, 9), + (1302, 6), + (1303, 4), + (1304, 7), + (1305, 4), + (1306, 12), + (1307, 14), + (1308, 7), + (1309, 1), (1311, 1), - (1320, 4), - (1321, 1), + (1312, 1), (1322, 1), (1323, 2), (1324, 1), - (1325, 1), - (1327, 1), - (1330, 2), - (1338, 2), + (1330, 3), + (1338, 1), (1339, 2), - (1341, 4), - (1342, 2), - (1343, 3), - (1344, 17), - (1345, 16), - (1346, 7), - (1347, 2), + (1340, 1), + (1341, 3), + (1342, 1), + (1343, 2), + (1344, 8), + (1345, 7), + (1346, 14), + (1347, 6), (1348, 1), - (1350, 1), - (1352, 3), - (1359, 3), - (1360, 1), - (1362, 2), - (1365, 1), - (1366, 1), - (1374, 2), - (1375, 1), - (1376, 1), + (1349, 1), + (1352, 1), + (1374, 1), (1377, 1), - (1378, 2), + (1378, 4), + (1379, 2), (1380, 1), - (1381, 2), - (1382, 3), - (1383, 9), - (1384, 7), - (1385, 13), - (1386, 5), - (1388, 1), - (1389, 1), - (1394, 1), - (1396, 2), - (1400, 2), - (1415, 2), - (1416, 1), - (1417, 1), + (1381, 4), + (1382, 5), + (1383, 11), + (1384, 5), + (1385, 12), + (1386, 6), + (1387, 3), + (1388, 2), + (1396, 1), + (1404, 1), + (1416, 3), + (1417, 2), (1418, 4), - (1419, 6), (1420, 5), - (1421, 2), - (1422, 3), + (1421, 7), + (1422, 10), (1423, 8), - (1424, 10), + (1424, 9), (1425, 5), - (1426, 1), + (1426, 4), + (1427, 1), (1428, 1), - (1443, 1), - (1445, 2), - (1454, 1), - (1455, 3), + (1430, 1), + (1442, 1), + (1455, 1), (1456, 1), - (1457, 2), + (1457, 1), (1458, 4), - (1459, 4), + (1459, 6), (1460, 10), - (1461, 8), - (1462, 11), - (1463, 5), - (1464, 5), - (1465, 1), - (1480, 1), - (1483, 1), + (1461, 12), + (1462, 10), + (1463, 10), + (1464, 7), + (1465, 2), + (1466, 2), + (1473, 1), (1485, 1), (1494, 2), - (1495, 1), - (1496, 7), - (1497, 7), - (1498, 5), - (1499, 4), - (1500, 5), - (1501, 12), - (1502, 10), - (1503, 3), - (1504, 2), - (1505, 2), - (1507, 3), - (1520, 1), + (1495, 7), + (1496, 9), + (1497, 8), + (1498, 7), + (1499, 6), + (1500, 11), + (1501, 10), + (1502, 12), + (1503, 9), + (1504, 3), + (1505, 4), + (1506, 1), (1529, 3), - (1532, 2), - (1533, 23), - (1535, 14), - (1536, 8), - (1537, 2), - (1538, 3), - (1539, 10), + (1532, 1), + (1533, 25), + (1534, 3), + (1535, 8), + (1536, 5), + (1537, 3), + (1538, 5), + (1539, 17), (1540, 11), - (1541, 13), - (1542, 4), - (1543, 2), - (1546, 1), + (1541, 14), + (1542, 11), + (1543, 4), + (1544, 3), + (1545, 1), (1548, 1), - (1551, 2), - (1571, 2), - (1572, 6), + (1572, 3), (1573, 4), - (1574, 4), - (1575, 2), - (1576, 7), - (1577, 5), - (1578, 8), - (1579, 12), - (1580, 4), - (1581, 5), - (1582, 1), - (1586, 1), + (1574, 2), + (1575, 3), + (1576, 5), + (1577, 3), + (1578, 10), + (1579, 18), + (1580, 10), + (1581, 11), + (1582, 4), + (1583, 4), (1595, 1), (1609, 2), - (1610, 2), + (1610, 1), (1611, 3), - (1612, 3), - (1613, 5), - (1614, 6), - (1615, 1), - (1616, 8), - (1617, 11), - (1618, 12), - (1619, 11), - (1620, 5), - (1621, 1), + (1613, 3), + (1614, 3), + (1615, 5), + (1616, 12), + (1617, 13), + (1618, 15), + (1619, 25), + (1620, 2), (1622, 1), + (1639, 2), (1649, 2), - (1650, 2), - (1651, 8), - (1652, 2), - (1653, 5), - (1654, 5), - (1655, 2), - (1656, 13), - (1657, 20), - (1658, 10), - (1659, 8), - (1660, 4), - (1661, 2), - (1663, 1), + (1650, 3), + (1651, 9), + (1652, 3), + (1653, 4), + (1654, 3), + (1655, 4), + (1656, 12), + (1657, 18), + (1658, 11), + (1659, 10), + (1660, 1), + (1664, 1), (1688, 2), (1689, 2), - (1690, 1), - (1691, 5), - (1692, 3), - (1693, 5), - (1694, 8), - (1695, 13), - (1696, 12), - (1697, 5), - (1698, 1), + (1690, 4), + (1691, 1), + (1692, 2), + (1693, 7), + (1694, 7), + (1695, 11), + (1696, 17), + (1697, 13), + (1698, 8), (1699, 2), - (1700, 1), + (1700, 2), (1701, 1), - (1702, 1), (1703, 1), - (1705, 1), - (1727, 3), - (1728, 3), - (1729, 2), + (1705, 5), + (1727, 6), + (1728, 1), + (1729, 4), (1730, 3), - (1731, 4), - (1732, 5), - (1733, 3), - (1734, 7), - (1735, 15), - (1736, 15), - (1737, 7), - (1738, 6), - (1739, 1), + (1732, 7), + (1733, 7), + (1734, 4), + (1735, 19), + (1736, 9), + (1737, 5), + (1738, 1), + (1739, 2), + (1740, 1), (1741, 1), (1742, 1), + (1744, 1), (1763, 6), - (1766, 8), - (1767, 2), - (1768, 1), - (1769, 4), - (1770, 5), - (1771, 1), + (1766, 10), + (1767, 3), + (1768, 4), + (1769, 2), + (1770, 2), (1772, 5), - (1773, 13), - (1774, 10), - (1775, 9), - (1776, 9), + (1773, 19), + (1774, 18), + (1775, 16), + (1776, 7), (1777, 4), - (1778, 2), - (1779, 2), - (1804, 1), - (1805, 2), + (1778, 3), + (1780, 1), + (1805, 1), + (1806, 4), (1807, 2), - (1808, 2), - (1809, 3), - (1810, 3), - (1811, 6), - (1812, 12), - (1813, 13), - (1814, 9), - (1815, 3), - (1816, 2), - (1817, 4), - (1821, 2), - (1844, 2), + (1808, 5), + (1809, 5), + (1810, 7), + (1811, 4), + (1812, 13), + (1813, 17), + (1814, 10), + (1815, 8), + (1816, 4), + (1817, 3), + (1825, 2), (1845, 1), - (1846, 2), - (1847, 8), - (1848, 6), - (1849, 5), - (1850, 7), - (1851, 4), - (1852, 3), - (1853, 9), - (1854, 5), - (1855, 6), - (1856, 3), - (1858, 1), - (1860, 1), - (1882, 1), - (1883, 2), - (1884, 1), - (1885, 4), + (1846, 3), + (1847, 1), + (1848, 5), + (1849, 3), + (1850, 4), + (1851, 7), + (1852, 10), + (1853, 20), + (1854, 10), + (1855, 7), + (1856, 1), + (1861, 1), + (1883, 4), + (1884, 8), (1886, 1), - (1887, 2), + (1887, 4), (1888, 3), - (1889, 2), + (1889, 9), (1890, 8), - (1891, 6), - (1892, 14), - (1893, 3), - (1894, 1), + (1891, 12), + (1892, 11), + (1893, 6), + (1894, 2), (1895, 1), - (1896, 1), - (1898, 1), - (1922, 6), - (1923, 1), + (1899, 1), + (1922, 7), (1924, 3), - (1925, 5), - (1926, 4), - (1927, 6), + (1925, 3), + (1926, 7), + (1927, 8), (1928, 7), - (1929, 7), + (1929, 11), (1930, 13), - (1931, 11), - (1932, 8), - (1933, 3), - (1934, 1), - (1936, 2), - (1937, 2), - (1938, 1), + (1931, 13), + (1932, 9), + (1933, 4), + (1934, 5), + (1936, 1), + (1937, 1), (1939, 2), - (1961, 3), - (1963, 3), + (1961, 8), + (1962, 2), (1964, 2), - (1965, 5), + (1965, 9), (1966, 7), - (1967, 4), - (1968, 5), - (1969, 9), - (1970, 11), - (1971, 7), + (1967, 7), + (1968, 11), + (1969, 5), + (1970, 13), + (1971, 9), (1972, 5), - (1973, 3), - (1974, 2), + (1973, 1), (1977, 1), + (1978, 1), (1997, 2), - (2000, 2), - (2001, 1), - (2002, 4), + (2000, 8), + (2001, 6), (2003, 4), (2004, 7), - (2005, 3), - (2006, 9), - (2007, 13), - (2008, 22), - (2009, 8), - (2010, 10), - (2011, 5), + (2005, 6), + (2006, 6), + (2007, 10), + (2008, 15), + (2009, 10), + (2010, 14), + (2011, 3), (2012, 2), - (2014, 1), + (2013, 1), + (2014, 3), (2016, 1), + (2017, 1), + (2018, 2), (2021, 1), - (2039, 3), - (2041, 5), - (2042, 5), - (2043, 8), - (2044, 6), - (2045, 2), - (2046, 12), + (2039, 2), + (2040, 2), + (2041, 1), + (2042, 4), + (2044, 7), + (2045, 10), + (2046, 13), (2047, 10), - (2048, 9), - (2049, 4), - (2050, 4), - (2051, 2), + (2048, 18), + (2049, 12), + (2050, 7), + (2051, 1), (2054, 3), + (2057, 1), + (2058, 1), + (2059, 1), (2062, 1), (2070, 5), (2077, 1), (2078, 4), - (2079, 4), - (2080, 2), - (2081, 4), - (2082, 5), + (2079, 6), + (2081, 1), + (2082, 6), (2083, 7), (2084, 4), - (2085, 13), - (2086, 4), - (2087, 7), - (2088, 6), - (2089, 8), - (2090, 1), - (2091, 1), - (2092, 4), + (2085, 15), + (2086, 16), + (2087, 10), + (2088, 9), + (2089, 11), + (2090, 2), + (2091, 2), + (2092, 2), + (2093, 1), + (2094, 1), + (2096, 2), + (2099, 1), (2113, 6), - (2117, 6), + (2117, 3), (2118, 2), + (2119, 1), (2120, 3), (2121, 5), (2122, 9), - (2123, 8), - (2124, 8), - (2125, 9), - (2126, 6), - (2127, 7), - (2128, 7), - (2130, 2), + (2123, 5), + (2124, 10), + (2125, 16), + (2126, 10), + (2127, 4), + (2128, 2), + (2129, 1), + (2130, 3), + (2131, 1), (2133, 1), - (2156, 4), - (2157, 1), - (2158, 3), - (2159, 1), - (2160, 6), - (2161, 3), - (2162, 7), + (2134, 1), + (2135, 4), + (2136, 1), + (2137, 1), + (2156, 5), + (2158, 1), + (2160, 2), + (2161, 2), + (2162, 5), (2163, 10), - (2164, 9), - (2165, 9), - (2166, 8), + (2164, 12), + (2165, 3), + (2166, 9), (2167, 5), - (2170, 3), + (2168, 4), + (2169, 1), + (2170, 2), (2171, 1), - (2193, 1), + (2175, 1), + (2176, 1), (2194, 1), (2195, 2), (2196, 2), - (2197, 2), - (2198, 4), - (2199, 5), - (2200, 9), - (2201, 5), - (2202, 13), - (2203, 17), - (2204, 13), - (2205, 11), - (2206, 1), - (2207, 2), - (2209, 1), - (2210, 2), + (2198, 1), + (2199, 4), + (2200, 7), + (2201, 4), + (2202, 4), + (2203, 14), + (2204, 3), + (2205, 5), + (2206, 6), + (2207, 3), + (2208, 1), + (2209, 2), + (2210, 1), + (2214, 1), (2234, 7), (2235, 1), - (2236, 2), - (2238, 6), - (2239, 9), - (2240, 7), + (2236, 3), + (2237, 2), + (2238, 1), + (2239, 3), + (2240, 10), (2241, 13), (2242, 12), - (2243, 9), - (2244, 6), - (2245, 4), + (2243, 14), + (2244, 16), + (2245, 5), (2246, 2), - (2247, 3), - (2273, 2), - (2274, 4), - (2275, 2), - (2277, 4), - (2278, 9), - (2279, 7), - (2280, 8), - (2281, 7), - (2282, 4), - (2283, 3), + (2247, 1), + (2248, 2), + (2251, 3), + (2271, 1), + (2273, 8), + (2274, 2), + (2275, 1), + (2276, 3), + (2277, 5), + (2278, 5), + (2279, 3), + (2280, 11), + (2281, 8), + (2282, 11), + (2283, 5), (2284, 2), (2285, 2), - (2286, 1), + (2286, 2), + (2287, 2), + (2288, 1), + (2289, 1), (2290, 1), - (2311, 2), - (2312, 3), - (2313, 1), - (2314, 4), - (2315, 3), - (2316, 3), - (2317, 10), - (2318, 11), - (2319, 12), - (2320, 11), - (2321, 17), - (2322, 9), - (2323, 3), - (2325, 3), - (2326, 4), + (2312, 17), + (2315, 1), + (2316, 5), + (2317, 3), + (2318, 9), + (2319, 7), + (2320, 10), + (2321, 18), + (2322, 13), + (2323, 7), + (2324, 1), + (2325, 1), + (2326, 7), + (2329, 1), (2341, 1), - (2351, 12), - (2352, 3), - (2353, 4), - (2354, 5), - (2355, 7), - (2356, 7), - (2357, 5), - (2358, 8), - (2359, 7), - (2360, 10), - (2361, 7), - (2362, 4), - (2363, 2), - (2364, 2), - (2365, 5), - (2367, 1), - (2369, 1), - (2390, 1), + (2351, 15), + (2353, 3), + (2354, 10), + (2355, 8), + (2356, 5), + (2357, 7), + (2358, 9), + (2359, 12), + (2360, 8), + (2361, 9), + (2362, 5), + (2364, 4), + (2365, 4), + (2390, 7), (2391, 1), - (2392, 5), - (2394, 4), + (2392, 4), + (2393, 4), + (2394, 3), (2395, 6), - (2396, 7), - (2397, 8), - (2398, 7), - (2399, 5), - (2400, 10), - (2401, 3), - (2402, 1), - (2403, 1), - (2408, 5), + (2396, 13), + (2397, 3), + (2398, 6), + (2399, 12), + (2400, 8), + (2401, 7), + (2402, 5), + (2403, 2), + (2404, 1), + (2405, 1), + (2406, 1), + (2408, 7), (2412, 1), (2428, 1), - (2429, 12), + (2429, 11), (2430, 2), (2431, 4), - (2433, 2), - (2434, 9), - (2435, 8), - (2436, 10), - (2437, 11), - (2438, 13), - (2439, 11), - (2440, 3), + (2432, 2), + (2433, 5), + (2434, 10), + (2435, 15), + (2436, 7), + (2437, 17), + (2438, 10), + (2439, 8), + (2440, 8), (2441, 1), - (2442, 1), + (2442, 4), (2443, 2), - (2445, 1), + (2444, 1), + (2445, 2), (2464, 2), - (2468, 1), - (2469, 2), - (2470, 6), - (2471, 3), - (2472, 3), - (2473, 5), - (2474, 7), - (2475, 6), - (2476, 13), - (2477, 16), - (2478, 10), - (2479, 10), - (2480, 1), + (2468, 4), + (2470, 13), + (2471, 2), + (2472, 5), + (2473, 7), + (2474, 6), + (2475, 8), + (2476, 8), + (2477, 7), + (2478, 5), + (2479, 9), + (2481, 4), (2482, 1), (2483, 1), - (2484, 2), - (2509, 1), + (2484, 1), + (2486, 2), + (2488, 1), + (2508, 8), + (2509, 7), (2510, 2), - (2511, 8), - (2512, 6), - (2513, 7), - (2514, 12), - (2515, 10), - (2516, 10), - (2517, 9), - (2518, 9), - (2519, 4), - (2520, 2), - (2521, 3), + (2511, 7), + (2512, 9), + (2513, 9), + (2514, 10), + (2515, 15), + (2516, 8), + (2517, 10), + (2518, 8), + (2519, 3), + (2520, 3), + (2521, 4), (2522, 3), - (2546, 2), - (2547, 1), + (2523, 2), + (2524, 1), + (2525, 1), + (2546, 1), + (2547, 3), (2548, 1), - (2549, 2), - (2550, 7), - (2551, 2), - (2552, 5), + (2550, 6), + (2551, 4), + (2552, 2), (2553, 6), - (2554, 13), - (2555, 14), - (2556, 8), - (2557, 5), - (2558, 2), - (2559, 1), - (2561, 1), - (2589, 5), - (2590, 6), + (2554, 14), + (2555, 10), + (2556, 10), + (2557, 8), + (2558, 3), + (2559, 2), + (2560, 1), + (2561, 2), + (2562, 2), + (2564, 1), + (2565, 1), + (2586, 1), + (2587, 2), + (2588, 1), + (2589, 4), + (2590, 4), (2591, 3), - (2592, 8), + (2592, 4), (2593, 10), - (2594, 14), - (2595, 3), - (2596, 7), - (2597, 8), + (2594, 13), + (2595, 9), + (2596, 9), + (2597, 5), (2598, 2), - (2599, 2), - (2600, 2), - (2604, 1), - (2625, 1), - (2628, 2), - (2629, 5), - (2630, 2), - (2631, 4), - (2632, 9), - (2633, 8), - (2634, 14), - (2635, 3), - (2636, 6), - (2637, 2), + (2599, 3), + (2600, 4), + (2601, 1), + (2602, 2), + (2603, 1), + (2627, 1), + (2628, 5), + (2629, 3), + (2630, 9), + (2631, 5), + (2632, 14), + (2633, 7), + (2634, 5), + (2635, 6), + (2636, 4), + (2637, 1), (2638, 1), - (2639, 2), + (2639, 5), + (2640, 6), (2641, 1), (2642, 1), - (2643, 1), - (2664, 4), - (2665, 6), - (2666, 7), - (2667, 3), - (2668, 3), - (2669, 5), - (2670, 9), - (2671, 11), - (2672, 12), - (2673, 15), - (2674, 3), - (2675, 6), + (2662, 1), + (2665, 9), + (2666, 9), + (2667, 2), + (2668, 6), + (2669, 6), + (2670, 8), + (2671, 5), + (2672, 14), + (2673, 11), + (2674, 8), + (2675, 5), (2676, 1), - (2677, 2), + (2677, 1), (2678, 2), - (2679, 1), - (2682, 1), - (2683, 2), - (2703, 3), - (2704, 3), - (2705, 2), + (2679, 4), + (2680, 1), + (2681, 1), + (2703, 2), + (2704, 1), + (2705, 4), (2706, 4), - (2707, 4), - (2708, 4), - (2709, 4), - (2710, 8), - (2711, 8), - (2712, 11), - (2713, 6), - (2714, 7), - (2715, 2), - (2716, 2), - (2717, 1), - (2718, 2), + (2707, 7), + (2708, 5), + (2709, 5), + (2710, 3), + (2711, 10), + (2712, 6), + (2713, 8), + (2714, 6), + (2716, 3), + (2717, 2), + (2718, 3), + (2719, 3), + (2720, 1), + (2722, 1), (2731, 2), - (2742, 1), - (2743, 2), - (2745, 2), - (2746, 8), + (2743, 1), + (2744, 2), + (2745, 5), + (2746, 3), (2747, 3), - (2748, 5), + (2748, 2), (2749, 8), (2750, 8), - (2751, 6), - (2752, 4), - (2753, 5), - (2755, 1), - (2756, 1), - (2757, 4), + (2751, 7), + (2752, 10), + (2753, 2), + (2754, 1), + (2756, 5), + (2757, 2), (2758, 1), - (2760, 5), + (2760, 6), (2775, 1), (2778, 1), - (2781, 2), - (2782, 2), + (2782, 1), (2783, 1), - (2784, 3), - (2785, 3), - (2786, 2), - (2787, 11), - (2788, 7), - (2789, 8), - (2790, 9), - (2791, 4), - (2792, 4), + (2784, 4), + (2785, 2), + (2786, 3), + (2787, 4), + (2788, 3), + (2789, 9), + (2790, 11), + (2791, 5), + (2792, 2), (2793, 3), - (2795, 3), - (2796, 4), - (2797, 1), + (2794, 1), + (2795, 4), + (2797, 2), (2798, 1), (2799, 1), - (2820, 2), (2822, 1), (2823, 2), - (2825, 4), + (2824, 1), + (2825, 2), (2826, 4), - (2827, 6), - (2828, 4), + (2827, 3), + (2828, 5), (2829, 8), - (2830, 5), + (2830, 6), (2831, 3), (2832, 2), - (2835, 3), - (2836, 3), - (2837, 1), - (2859, 3), - (2861, 5), - (2862, 3), - (2863, 7), - (2864, 3), - (2865, 6), - (2866, 5), - (2867, 11), - (2868, 9), + (2833, 1), + (2834, 2), + (2835, 1), + (2836, 1), + (2837, 2), + (2860, 2), + (2861, 1), + (2862, 9), + (2863, 4), + (2864, 5), + (2865, 5), + (2866, 7), + (2867, 7), + (2868, 18), (2869, 5), - (2870, 6), - (2871, 1), + (2870, 4), + (2872, 1), (2873, 2), + (2874, 1), (2877, 1), - (2898, 6), - (2900, 1), - (2901, 2), - (2902, 7), - (2903, 4), - (2904, 2), - (2905, 7), + (2878, 2), + (2899, 1), + (2900, 7), + (2901, 10), + (2902, 5), + (2903, 8), + (2904, 1), + (2905, 6), (2906, 7), - (2907, 9), + (2907, 4), (2908, 4), - (2909, 3), - (2910, 2), + (2909, 5), + (2910, 1), (2911, 2), - (2912, 2), - (2913, 1), + (2912, 1), (2916, 1), - (2937, 2), - (2938, 1), - (2940, 4), - (2941, 4), - (2942, 4), + (2939, 2), + (2940, 2), + (2942, 2), (2943, 4), - (2944, 16), - (2945, 11), - (2946, 3), - (2947, 11), - (2948, 3), - (2949, 2), - (2950, 2), + (2944, 7), + (2945, 5), + (2946, 4), + (2947, 7), + (2948, 4), (2951, 1), - (2954, 1), + (2954, 2), + (2955, 1), (2962, 6), - (2976, 1), - (2977, 1), - (2978, 2), - (2979, 2), - (2980, 3), - (2981, 3), + (2977, 2), + (2979, 1), + (2980, 4), + (2981, 4), (2982, 2), - (2983, 2), - (2984, 5), - (2985, 11), - (2986, 6), + (2983, 5), + (2984, 8), + (2985, 3), + (2986, 5), (2987, 2), - (2988, 1), - (2989, 2), - (2992, 1), - (3015, 2), - (3016, 4), - (3017, 4), - (3018, 2), + (2989, 1), + (2995, 2), + (2996, 2), + (3016, 3), + (3017, 5), + (3018, 3), (3019, 3), (3020, 3), - (3021, 6), - (3022, 11), - (3023, 10), - (3024, 2), + (3021, 2), + (3022, 8), + (3023, 4), + (3024, 5), (3025, 5), - (3026, 1), - (3027, 3), - (3029, 2), + (3026, 4), + (3027, 1), + (3029, 6), + (3030, 1), + (3031, 1), + (3033, 1), (3035, 1), - (3054, 4), - (3057, 2), - (3058, 3), - (3059, 5), - (3060, 3), - (3061, 8), - (3062, 5), - (3063, 4), - (3064, 6), - (3065, 2), - (3066, 1), + (3054, 1), + (3055, 1), + (3056, 4), + (3057, 3), + (3058, 1), + (3059, 4), + (3061, 3), + (3062, 7), + (3063, 2), + (3064, 4), + (3065, 1), + (3066, 2), + (3068, 2), + (3069, 3), + (3072, 1), + (3073, 1), (3086, 1), (3092, 2), - (3093, 4), + (3093, 1), (3094, 1), - (3095, 4), - (3096, 1), - (3097, 2), - (3098, 3), - (3099, 3), - (3100, 5), - (3101, 6), - (3102, 7), - (3103, 2), - (3104, 3), - (3105, 4), + (3095, 3), + (3096, 5), + (3097, 5), + (3098, 2), + (3099, 9), + (3100, 4), + (3101, 7), + (3102, 6), + (3103, 4), + (3105, 3), + (3106, 1), (3110, 1), + (3111, 1), (3124, 6), - (3132, 4), - (3134, 3), - (3135, 1), - (3136, 5), - (3137, 3), - (3138, 5), - (3139, 8), - (3140, 7), - (3141, 6), - (3142, 9), - (3143, 1), - (3144, 2), + (3134, 2), + (3135, 5), + (3136, 4), + (3137, 2), + (3138, 4), + (3139, 7), + (3140, 9), + (3141, 1), + (3142, 1), + (3143, 5), + (3144, 1), (3145, 1), - (3147, 1), (3148, 2), - (3171, 2), - (3172, 1), - (3173, 2), - (3174, 3), - (3175, 4), - (3176, 4), - (3177, 4), - (3178, 5), - (3179, 2), - (3180, 8), - (3181, 4), - (3182, 2), - (3183, 3), + (3150, 1), + (3152, 1), + (3172, 3), + (3173, 1), + (3174, 2), + (3175, 3), + (3177, 3), + (3178, 3), + (3179, 7), + (3180, 5), + (3181, 5), + (3183, 1), (3184, 1), + (3185, 2), + (3186, 1), (3189, 1), (3194, 4), - (3210, 2), - (3212, 2), - (3213, 3), + (3212, 3), + (3213, 2), (3214, 7), - (3215, 7), - (3216, 4), + (3215, 5), + (3216, 2), (3217, 4), - (3218, 8), - (3219, 5), - (3220, 4), + (3218, 11), + (3219, 1), + (3220, 2), (3221, 1), - (3223, 1), - (3249, 2), - (3250, 2), + (3222, 1), + (3223, 2), + (3224, 1), + (3225, 2), + (3250, 6), (3251, 1), - (3252, 2), - (3253, 4), - (3254, 5), - (3255, 4), - (3256, 6), - (3257, 4), - (3258, 8), - (3259, 4), - (3260, 3), + (3252, 5), + (3253, 6), + (3254, 3), + (3255, 3), + (3256, 5), + (3257, 1), + (3258, 3), + (3259, 5), + (3260, 1), (3261, 2), - (3262, 1), - (3288, 3), - (3290, 3), - (3291, 2), - (3292, 4), - (3293, 2), + (3263, 2), + (3288, 1), + (3289, 6), + (3290, 1), + (3291, 3), + (3292, 2), + (3293, 5), (3294, 4), (3295, 5), - (3296, 11), - (3297, 10), - (3298, 2), - (3299, 4), + (3296, 6), + (3297, 7), + (3299, 2), (3300, 1), - (3301, 2), - (3303, 1), + (3301, 3), + (3302, 2), (3306, 1), - (3327, 1), - (3329, 2), - (3330, 6), - (3331, 5), - (3332, 2), - (3333, 1), + (3328, 6), + (3329, 3), + (3330, 4), + (3331, 2), + (3333, 10), (3334, 5), - (3335, 6), - (3336, 5), - (3337, 5), - (3338, 2), - (3340, 1), - (3342, 1), - (3366, 13), - (3368, 4), - (3369, 2), - (3370, 5), - (3371, 5), - (3372, 4), + (3335, 2), + (3336, 3), + (3337, 4), + (3338, 1), + (3339, 1), + (3344, 3), + (3366, 7), + (3367, 6), + (3368, 5), + (3369, 4), + (3370, 4), + (3371, 8), + (3372, 3), (3373, 3), - (3374, 7), - (3375, 5), - (3376, 2), + (3374, 6), + (3375, 4), + (3376, 4), (3377, 1), - (3378, 1), + (3378, 2), (3380, 1), - (3382, 1), + (3384, 1), + (3386, 1), (3389, 6), - (3394, 1), - (3405, 6), - (3406, 1), + (3405, 1), + (3406, 4), (3407, 2), - (3408, 3), - (3409, 5), - (3410, 2), - (3411, 3), - (3412, 4), - (3413, 5), - (3414, 6), - (3415, 5), - (3417, 2), - (3418, 1), - (3421, 1), - (3423, 1), - (3424, 1), - (3444, 3), - (3445, 1), - (3447, 3), - (3448, 1), - (3449, 2), - (3450, 4), - (3451, 5), - (3452, 6), - (3453, 8), - (3454, 6), - (3455, 2), - (3456, 4), + (3409, 3), + (3410, 6), + (3411, 6), + (3412, 1), + (3413, 4), + (3414, 2), + (3415, 3), + (3416, 4), + (3417, 1), + (3418, 2), + (3419, 1), + (3445, 2), + (3446, 1), + (3447, 2), + (3448, 2), + (3449, 3), + (3450, 6), + (3451, 2), + (3452, 7), + (3453, 5), + (3454, 5), + (3456, 1), + (3463, 1), (3477, 1), (3483, 1), - (3484, 4), - (3485, 5), - (3486, 2), - (3487, 3), - (3488, 3), - (3489, 6), - (3490, 8), - (3491, 6), - (3492, 8), - (3493, 5), - (3494, 2), + (3484, 8), + (3485, 2), + (3486, 1), + (3487, 5), + (3488, 1), + (3489, 5), + (3490, 4), + (3491, 2), + (3493, 2), + (3494, 3), + (3496, 1), (3499, 1), + (3501, 1), + (3502, 1), (3512, 4), (3522, 1), - (3523, 2), - (3524, 3), - (3525, 3), - (3526, 6), - (3527, 5), + (3524, 4), + (3525, 2), + (3526, 4), + (3527, 2), (3528, 3), - (3529, 10), - (3530, 10), - (3531, 7), - (3532, 4), + (3529, 2), + (3530, 3), + (3531, 5), + (3532, 2), (3533, 3), - (3534, 1), - (3535, 2), - (3561, 1), - (3562, 2), - (3563, 3), - (3564, 3), - (3565, 2), - (3566, 6), - (3567, 2), - (3568, 2), - (3569, 14), - (3570, 7), - (3571, 2), - (3572, 2), - (3573, 1), - (3574, 2), - (3575, 1), + (3534, 3), + (3540, 1), + (3554, 1), + (3562, 1), + (3563, 2), + (3564, 13), + (3565, 5), + (3566, 4), + (3567, 4), + (3568, 3), + (3569, 11), + (3570, 4), + (3571, 1), + (3573, 2), (3576, 1), - (3600, 4), - (3601, 3), - (3602, 5), - (3603, 3), + (3600, 1), + (3602, 4), + (3603, 6), (3604, 4), - (3605, 4), - (3606, 7), - (3607, 8), + (3605, 3), + (3606, 6), + (3607, 4), (3608, 5), - (3609, 3), - (3610, 3), - (3639, 3), + (3609, 6), + (3610, 4), + (3612, 2), + (3613, 1), + (3614, 1), + (3639, 1), (3640, 1), - (3641, 1), + (3641, 3), (3642, 5), (3643, 2), - (3644, 6), - (3645, 4), - (3646, 4), - (3647, 3), + (3644, 3), + (3645, 2), + (3646, 1), + (3647, 4), (3648, 2), - (3649, 1), - (3650, 2), + (3649, 4), + (3650, 5), (3651, 1), - (3678, 1), - (3680, 4), - (3681, 2), - (3682, 7), - (3683, 2), - (3684, 6), - (3685, 4), + (3652, 1), + (3657, 1), + (3658, 1), + (3679, 2), + (3680, 3), + (3681, 5), + (3682, 2), + (3683, 3), + (3684, 5), + (3685, 2), (3686, 4), - (3687, 4), + (3687, 2), (3688, 3), - (3690, 2), - (3691, 2), + (3689, 2), + (3690, 1), + (3691, 3), (3692, 1), - (3694, 1), - (3717, 1), - (3718, 1), - (3719, 3), + (3718, 2), + (3719, 5), (3720, 5), - (3721, 5), - (3722, 8), - (3723, 3), - (3724, 2), - (3725, 2), - (3726, 2), - (3727, 4), - (3728, 1), + (3721, 7), + (3722, 2), + (3723, 5), + (3724, 3), + (3725, 7), + (3726, 5), + (3727, 1), + (3728, 4), + (3729, 3), (3731, 1), - (3732, 2), - (3733, 1), - (3756, 4), - (3758, 13), - (3759, 2), - (3760, 7), - (3761, 3), - (3762, 4), - (3763, 2), - (3764, 6), - (3765, 1), + (3756, 2), + (3757, 2), + (3758, 11), + (3759, 3), + (3760, 5), + (3761, 2), + (3762, 2), + (3763, 3), + (3764, 1), + (3765, 4), (3766, 2), (3769, 1), + (3770, 1), (3795, 1), - (3797, 3), - (3798, 4), - (3799, 9), - (3800, 3), - (3801, 6), - (3802, 5), - (3803, 2), - (3804, 5), - (3805, 2), - (3807, 1), + (3796, 4), + (3797, 6), + (3798, 7), + (3799, 3), + (3800, 5), + (3801, 3), + (3802, 2), + (3803, 5), + (3804, 9), + (3805, 1), + (3806, 3), (3808, 1), - (3834, 1), - (3835, 1), + (3834, 2), (3836, 4), - (3837, 1), - (3838, 4), - (3839, 5), - (3840, 4), - (3841, 7), - (3842, 8), - (3843, 5), - (3844, 1), + (3837, 6), + (3838, 3), + (3839, 2), + (3840, 1), + (3841, 2), + (3842, 5), + (3843, 4), + (3844, 2), (3845, 3), (3846, 2), - (3847, 1), - (3874, 4), - (3875, 3), - (3876, 7), - (3877, 7), - (3878, 3), - (3879, 3), - (3880, 2), - (3881, 5), - (3882, 3), - (3883, 4), - (3884, 1), - (3885, 1), - (3886, 1), + (3850, 1), + (3874, 2), + (3875, 2), + (3876, 8), + (3877, 3), + (3878, 2), + (3879, 4), + (3880, 3), + (3881, 4), + (3882, 4), + (3883, 2), + (3884, 4), + (3885, 2), + (3912, 1), (3913, 1), - (3914, 3), + (3914, 4), (3915, 4), - (3916, 4), - (3917, 6), - (3920, 2), - (3921, 5), - (3922, 4), + (3916, 2), + (3917, 3), + (3918, 4), + (3919, 2), + (3920, 3), + (3921, 1), (3923, 1), - (3925, 1), - (3928, 1), + (3924, 1), (3929, 1), - (3951, 1), - (3952, 1), + (3931, 1), + (3952, 2), (3953, 3), (3954, 2), - (3955, 1), - (3956, 8), - (3957, 4), - (3958, 5), + (3955, 4), + (3956, 4), + (3957, 3), + (3958, 3), (3959, 3), - (3960, 5), - (3961, 3), + (3960, 1), + (3961, 2), (3962, 1), - (3963, 2), + (3963, 4), (3964, 1), - (3991, 3), - (3992, 4), - (3993, 2), - (3994, 5), - (3995, 3), - (3996, 6), - (3997, 8), - (3998, 4), - (3999, 4), - (4000, 1), - (4001, 3), - (4002, 1), + (3992, 3), + (3993, 6), + (3994, 6), + (3995, 1), + (3996, 3), + (3997, 2), + (3998, 2), + (3999, 1), + (4000, 2), (4003, 1), - (4031, 2), - (4032, 4), - (4033, 7), - (4034, 4), + (4029, 1), + (4030, 1), + (4031, 3), + (4032, 3), + (4033, 2), + (4034, 1), (4035, 3), - (4036, 3), - (4037, 1), - (4038, 3), - (4039, 5), - (4040, 4), - (4041, 1), + (4037, 3), + (4038, 4), + (4039, 2), + (4040, 3), + (4041, 3), (4069, 1), - (4070, 3), - (4071, 4), + (4070, 6), + (4071, 2), (4072, 1), (4073, 2), - (4074, 4), + (4074, 6), (4075, 1), - (4076, 2), - (4077, 5), + (4076, 4), + (4077, 2), (4078, 4), - (4079, 2), + (4080, 1), + (4081, 1), + (4082, 2), (4083, 1), - (4107, 1), (4108, 2), - (4109, 2), + (4109, 3), (4110, 3), - (4111, 4), - (4112, 4), - (4113, 6), - (4114, 1), + (4111, 2), + (4112, 1), + (4113, 5), + (4114, 2), (4115, 5), - (4116, 1), - (4117, 3), - (4119, 1), - (4120, 1), + (4116, 2), + (4118, 1), + (4119, 3), + (4121, 1), + (4123, 1), + (4126, 1), (4147, 2), - (4148, 4), - (4150, 3), + (4148, 3), + (4149, 6), + (4150, 5), (4151, 3), - (4152, 2), - (4153, 5), - (4154, 4), - (4155, 4), - (4156, 3), - (4157, 3), - (4158, 2), - (4161, 1), - (4185, 2), + (4152, 4), + (4154, 5), + (4155, 2), + (4156, 1), + (4157, 7), + (4159, 1), + (4160, 2), + (4162, 2), + (4186, 3), (4187, 2), - (4188, 7), - (4189, 5), - (4190, 2), - (4191, 1), - (4192, 5), - (4193, 2), + (4188, 6), + (4189, 3), + (4190, 5), + (4191, 4), + (4193, 4), (4194, 3), - (4195, 2), + (4195, 4), (4196, 2), (4197, 2), - (4198, 2), - (4224, 2), - (4225, 2), + (4198, 3), + (4199, 1), + (4224, 1), + (4225, 3), (4226, 1), - (4227, 2), - (4228, 4), - (4229, 4), + (4227, 3), + (4228, 3), (4230, 3), (4231, 3), (4232, 3), - (4233, 3), + (4233, 1), (4234, 3), - (4236, 1), + (4235, 5), + (4236, 3), + (4237, 1), (4259, 2), - (4263, 4), - (4264, 1), - (4265, 2), - (4266, 4), - (4267, 3), - (4268, 1), - (4269, 5), - (4270, 5), - (4271, 4), - (4272, 3), - (4273, 3), + (4263, 2), + (4264, 2), + (4265, 6), + (4266, 5), + (4267, 2), + (4268, 6), + (4269, 1), + (4270, 3), + (4271, 1), + (4272, 1), + (4273, 4), (4274, 2), + (4275, 3), + (4276, 2), (4277, 1), (4280, 5), + (4282, 1), (4300, 2), - (4302, 3), - (4303, 2), - (4304, 4), - (4305, 6), - (4306, 2), + (4302, 2), + (4303, 4), + (4304, 8), + (4305, 3), + (4306, 3), (4307, 3), - (4308, 2), - (4309, 4), - (4310, 7), + (4308, 1), + (4309, 1), + (4310, 3), (4311, 2), - (4312, 4), - (4313, 4), - (4314, 1), - (4342, 1), - (4343, 3), - (4344, 7), - (4345, 7), - (4346, 2), - (4347, 2), - (4348, 6), - (4349, 3), - (4350, 3), - (4351, 3), - (4352, 2), - (4353, 2), + (4312, 3), + (4313, 3), + (4314, 3), + (4341, 2), + (4343, 2), + (4344, 9), + (4345, 2), + (4346, 3), + (4347, 1), + (4348, 2), + (4349, 6), + (4350, 1), + (4351, 2), + (4352, 1), + (4353, 1), (4354, 1), (4356, 2), - (4380, 4), + (4380, 2), + (4381, 1), + (4382, 3), (4383, 8), - (4385, 3), - (4386, 8), - (4387, 3), - (4388, 5), - (4389, 1), - (4390, 1), - (4391, 2), - (4392, 2), - (4393, 2), - (4419, 4), - (4420, 2), - (4421, 3), - (4422, 5), - (4423, 7), - (4424, 3), + (4384, 3), + (4386, 2), + (4387, 5), + (4388, 1), + (4389, 3), + (4391, 1), + (4392, 1), + (4393, 1), + (4419, 2), + (4420, 3), + (4421, 1), + (4422, 4), + (4423, 5), (4425, 5), - (4426, 5), - (4427, 3), - (4428, 4), + (4426, 2), + (4427, 1), + (4428, 2), (4429, 1), - (4430, 3), - (4431, 1), + (4430, 2), + (4431, 3), (4432, 7), + (4433, 3), (4434, 1), - (4458, 5), - (4460, 3), - (4461, 2), - (4462, 6), - (4463, 3), - (4464, 3), - (4465, 3), - (4466, 10), - (4467, 3), - (4468, 2), - (4469, 2), - (4470, 1), - (4473, 1), - (4498, 2), + (4458, 2), + (4459, 6), + (4460, 5), + (4461, 4), + (4462, 9), + (4463, 2), + (4464, 1), + (4465, 1), + (4466, 1), + (4468, 7), + (4469, 3), + (4470, 2), + (4471, 2), + (4497, 1), + (4498, 1), + (4499, 9), (4500, 3), - (4501, 8), - (4502, 3), - (4503, 1), - (4504, 6), - (4505, 3), + (4501, 5), + (4502, 2), + (4503, 5), + (4505, 5), (4506, 3), - (4507, 1), - (4508, 2), - (4509, 2), - (4510, 2), + (4507, 2), + (4508, 1), + (4509, 1), (4511, 2), - (4536, 1), + (4536, 3), + (4537, 4), (4538, 3), - (4539, 5), - (4540, 3), - (4541, 6), + (4539, 3), + (4540, 2), + (4541, 3), (4542, 2), - (4543, 4), - (4544, 3), - (4545, 3), - (4546, 1), - (4547, 1), - (4550, 1), - (4575, 3), + (4543, 1), + (4546, 4), + (4547, 4), + (4575, 1), (4576, 1), - (4577, 5), - (4578, 3), - (4579, 8), - (4580, 3), - (4581, 4), - (4582, 4), - (4583, 4), - (4584, 5), - (4587, 3), - (4588, 2), + (4577, 2), + (4578, 1), + (4579, 2), + (4580, 1), + (4581, 6), + (4582, 3), + (4583, 5), + (4584, 1), + (4585, 4), + (4586, 2), + (4589, 1), (4614, 1), + (4615, 1), (4616, 1), - (4617, 4), - (4618, 4), - (4619, 1), - (4620, 3), - (4621, 3), + (4618, 7), + (4619, 2), + (4621, 2), (4622, 2), - (4623, 4), + (4623, 2), (4624, 3), - (4627, 2), - (4628, 2), - (4653, 2), - (4655, 3), + (4625, 1), + (4627, 1), + (4628, 3), + (4654, 5), + (4655, 1), (4656, 3), - (4657, 4), - (4658, 3), + (4657, 6), + (4658, 2), (4659, 4), - (4660, 3), - (4661, 2), - (4662, 7), - (4663, 7), + (4660, 2), + (4662, 1), + (4663, 3), (4664, 1), - (4665, 2), - (4666, 1), - (4693, 1), + (4668, 1), + (4669, 1), + (4692, 1), + (4693, 2), (4694, 2), - (4695, 2), - (4696, 5), - (4699, 1), - (4700, 4), - (4701, 3), + (4695, 3), + (4696, 2), + (4697, 1), + (4699, 3), + (4700, 1), + (4701, 1), (4702, 2), - (4703, 1), - (4704, 1), - (4731, 3), - (4733, 2), - (4734, 6), - (4735, 1), - (4736, 2), - (4737, 3), - (4738, 3), - (4739, 3), - (4740, 4), + (4704, 3), + (4706, 1), + (4707, 2), + (4731, 1), + (4733, 4), + (4734, 4), + (4735, 3), + (4736, 1), + (4738, 1), + (4740, 2), (4741, 2), (4742, 3), - (4743, 2), (4744, 2), - (4770, 1), - (4771, 3), - (4772, 2), + (4745, 3), + (4771, 4), + (4772, 4), (4773, 4), - (4774, 5), - (4775, 3), - (4776, 5), - (4777, 8), - (4778, 1), - (4779, 2), - (4780, 3), - (4781, 1), + (4774, 2), + (4777, 4), + (4778, 3), + (4779, 4), + (4781, 4), (4782, 1), (4785, 2), - (4809, 2), - (4811, 2), - (4812, 6), - (4813, 4), - (4814, 1), + (4811, 1), + (4812, 5), + (4813, 1), + (4814, 3), (4815, 2), - (4816, 2), - (4817, 1), + (4816, 3), + (4817, 4), (4818, 5), (4819, 2), - (4820, 1), - (4821, 2), + (4820, 2), + (4821, 1), + (4822, 1), + (4823, 2), (4834, 1), - (4848, 1), - (4850, 3), + (4849, 2), + (4850, 2), (4851, 2), - (4852, 4), - (4853, 1), - (4854, 1), - (4855, 3), - (4856, 8), + (4852, 3), + (4853, 3), + (4854, 4), + (4855, 2), + (4856, 5), (4857, 2), - (4858, 2), - (4859, 2), - (4860, 2), - (4862, 2), - (4887, 2), + (4858, 3), + (4860, 1), + (4861, 1), + (4862, 1), (4888, 1), + (4889, 1), (4890, 3), - (4891, 4), - (4893, 3), - (4894, 2), - (4895, 4), + (4892, 3), + (4893, 1), + (4894, 6), + (4895, 6), (4896, 6), - (4897, 3), + (4897, 2), + (4898, 1), (4899, 1), - (4900, 1), - (4926, 2), - (4927, 1), - (4928, 4), - (4929, 2), + (4900, 2), + (4901, 1), + (4928, 1), + (4929, 3), (4930, 2), - (4931, 2), (4932, 4), - (4933, 7), - (4934, 1), + (4933, 5), + (4934, 6), (4935, 3), + (4936, 2), (4937, 1), - (4938, 2), - (4939, 1), - (4942, 1), - (4964, 1), + (4938, 1), + (4939, 4), + (4940, 1), + (4941, 1), (4965, 1), - (4966, 1), - (4968, 1), - (4969, 5), - (4970, 5), - (4971, 3), - (4972, 1), - (4973, 7), - (4974, 1), - (4975, 2), - (4977, 1), + (4967, 2), + (4968, 2), + (4969, 1), + (4970, 2), + (4971, 2), + (4972, 5), + (4973, 1), + (4974, 2), + (4975, 1), + (4977, 2), (4978, 1), - (4979, 2), - (5004, 3), - (5005, 2), - (5006, 1), - (5007, 1), - (5008, 2), - (5009, 3), - (5010, 1), - (5011, 4), - (5012, 4), + (5006, 2), + (5007, 3), + (5009, 2), + (5010, 3), + (5012, 1), (5013, 1), (5014, 2), - (5015, 5), - (5016, 1), - (5018, 2), - (5019, 1), - (5043, 2), - (5046, 6), + (5015, 4), + (5016, 3), + (5018, 1), + (5019, 3), + (5021, 1), + (5042, 1), + (5044, 2), (5047, 1), - (5048, 1), - (5049, 1), - (5050, 1), + (5049, 3), + (5050, 2), (5051, 1), - (5052, 5), - (5053, 4), - (5054, 2), + (5052, 3), + (5053, 1), (5055, 1), - (5056, 1), - (5082, 1), (5083, 1), - (5084, 4), - (5085, 4), - (5086, 5), - (5087, 2), - (5089, 1), - (5090, 3), - (5091, 6), - (5092, 1), + (5084, 3), + (5085, 3), + (5088, 1), + (5089, 5), + (5090, 2), + (5091, 3), + (5092, 2), (5093, 1), - (5094, 4), - (5096, 1), - (5098, 2), - (5121, 2), - (5123, 3), - (5124, 4), + (5094, 1), + (5097, 1), + (5098, 1), + (5122, 1), + (5124, 2), (5125, 1), - (5126, 3), - (5127, 1), - (5128, 5), + (5126, 1), + (5127, 2), + (5128, 3), + (5129, 5), (5130, 2), - (5131, 1), + (5131, 6), (5132, 1), - (5133, 2), - (5134, 2), + (5133, 3), (5135, 1), (5136, 2), - (5137, 1), - (5160, 1), - (5162, 4), - (5163, 1), - (5164, 3), - (5166, 1), - (5167, 2), - (5168, 8), - (5169, 4), - (5170, 1), - (5173, 1), - (5198, 1), - (5201, 2), - (5202, 4), + (5138, 1), + (5162, 1), + (5163, 3), + (5164, 1), + (5165, 2), + (5167, 4), + (5168, 4), + (5169, 1), + (5170, 4), + (5171, 1), + (5172, 1), + (5200, 1), + (5202, 1), + (5203, 1), (5204, 1), (5205, 1), (5206, 1), - (5207, 3), - (5208, 1), + (5207, 1), + (5208, 3), (5209, 5), - (5210, 3), - (5211, 1), + (5210, 1), + (5211, 2), (5213, 2), (5215, 1), - (5238, 1), - (5239, 6), + (5216, 1), + (5239, 3), + (5240, 1), (5241, 1), (5242, 2), (5243, 2), - (5244, 2), - (5245, 2), + (5244, 3), + (5245, 1), (5246, 4), - (5247, 5), + (5247, 2), (5248, 3), - (5250, 2), - (5252, 2), - (5280, 3), - (5281, 1), - (5283, 4), - (5284, 2), - (5285, 2), + (5249, 2), + (5250, 1), + (5251, 2), + (5253, 2), + (5280, 1), + (5282, 2), + (5283, 2), + (5284, 3), + (5285, 3), (5286, 1), - (5288, 3), - (5289, 1), + (5287, 3), + (5288, 1), + (5289, 2), (5290, 1), - (5291, 1), + (5293, 1), (5317, 1), - (5318, 2), - (5319, 2), + (5318, 1), + (5320, 1), (5321, 3), - (5322, 2), - (5323, 6), - (5324, 1), - (5325, 1), - (5326, 2), + (5322, 3), + (5323, 2), + (5324, 3), + (5325, 4), + (5326, 3), (5327, 3), - (5328, 2), - (5329, 2), - (5330, 1), - (5331, 1), - (5356, 1), - (5357, 3), - (5358, 4), + (5330, 2), + (5356, 3), + (5357, 1), + (5358, 1), + (5359, 1), (5360, 1), - (5361, 1), - (5362, 2), - (5363, 1), - (5364, 1), - (5366, 2), + (5361, 5), + (5362, 3), + (5363, 4), + (5364, 3), + (5365, 3), + (5366, 1), (5367, 1), (5369, 1), - (5395, 2), - (5396, 2), - (5397, 2), - (5398, 2), + (5370, 1), + (5371, 1), + (5372, 1), + (5396, 1), + (5397, 1), + (5399, 1), (5400, 2), - (5401, 2), + (5401, 4), (5402, 4), - (5403, 3), - (5404, 1), + (5403, 2), + (5404, 3), (5405, 3), - (5406, 1), + (5406, 2), + (5407, 1), (5408, 1), - (5434, 1), - (5435, 2), - (5436, 2), + (5409, 2), + (5410, 2), + (5412, 1), + (5435, 1), (5437, 1), - (5438, 4), - (5439, 3), + (5438, 3), + (5439, 8), (5440, 3), - (5441, 5), - (5442, 1), - (5443, 1), + (5441, 3), + (5442, 6), + (5443, 2), (5445, 3), - (5474, 4), + (5448, 2), + (5450, 1), + (5473, 1), + (5474, 1), (5475, 1), - (5476, 3), + (5476, 1), (5477, 1), - (5478, 2), - (5479, 2), - (5480, 4), - (5481, 5), - (5482, 2), - (5485, 2), - (5486, 1), - (5512, 1), - (5513, 2), - (5514, 4), + (5478, 1), + (5479, 4), + (5480, 2), + (5481, 2), + (5483, 1), + (5485, 1), + (5486, 3), + (5487, 2), + (5508, 5), + (5512, 2), + (5514, 1), (5515, 4), - (5517, 2), - (5518, 2), - (5519, 2), - (5520, 4), - (5521, 2), + (5516, 3), + (5517, 1), + (5518, 5), + (5519, 1), + (5520, 7), + (5521, 1), + (5522, 3), (5523, 1), - (5524, 3), - (5525, 9), + (5524, 2), + (5525, 6), (5526, 1), (5542, 3), - (5551, 1), - (5552, 1), - (5553, 1), - (5554, 4), (5555, 4), - (5556, 1), - (5557, 5), - (5558, 3), - (5559, 1), - (5560, 2), + (5556, 3), + (5557, 1), + (5558, 2), + (5559, 5), + (5560, 4), + (5561, 5), + (5562, 2), (5563, 1), (5564, 1), - (5565, 2), (5566, 1), (5590, 1), - (5591, 3), - (5592, 5), - (5593, 4), + (5591, 2), + (5593, 1), (5594, 1), (5595, 1), - (5596, 1), + (5596, 5), (5597, 3), - (5598, 3), - (5599, 3), + (5598, 2), + (5599, 4), + (5600, 1), (5601, 2), - (5602, 2), - (5603, 1), - (5604, 2), + (5602, 1), + (5603, 3), + (5604, 1), + (5605, 1), + (5606, 1), (5620, 6), - (5628, 1), - (5629, 1), - (5630, 1), - (5631, 1), - (5632, 1), + (5632, 2), (5633, 3), - (5634, 2), - (5635, 2), - (5636, 2), - (5637, 2), - (5638, 4), - (5639, 3), - (5640, 1), - (5641, 1), - (5642, 1), - (5643, 2), + (5634, 5), + (5635, 3), + (5636, 5), + (5637, 3), + (5638, 5), + (5639, 2), + (5640, 5), + (5641, 5), + (5642, 2), + (5643, 1), (5668, 1), - (5669, 1), - (5670, 2), - (5671, 3), - (5672, 2), + (5669, 2), + (5671, 1), + (5672, 3), (5673, 2), - (5675, 1), - (5676, 2), - (5677, 2), - (5678, 1), - (5680, 2), - (5706, 1), + (5674, 6), + (5675, 3), + (5676, 4), + (5677, 5), + (5678, 3), + (5679, 3), + (5681, 2), + (5682, 2), + (5683, 2), + (5684, 2), (5707, 1), - (5709, 2), - (5710, 2), - (5712, 4), - (5713, 1), + (5710, 3), + (5711, 6), + (5712, 6), + (5713, 2), (5714, 3), (5715, 4), - (5718, 1), - (5719, 3), - (5721, 1), + (5716, 4), + (5717, 3), + (5718, 2), + (5719, 4), + (5720, 1), + (5721, 2), + (5722, 1), (5745, 5), - (5746, 2), - (5747, 2), - (5748, 2), - (5749, 2), - (5750, 3), - (5751, 3), - (5753, 2), - (5754, 1), + (5749, 1), + (5750, 6), + (5751, 8), + (5752, 3), + (5753, 3), + (5754, 4), (5755, 2), - (5756, 3), + (5756, 2), (5757, 1), + (5758, 3), (5759, 1), - (5785, 2), - (5786, 2), - (5787, 4), - (5788, 2), - (5789, 6), - (5790, 5), - (5791, 3), + (5760, 1), + (5761, 3), + (5787, 2), + (5789, 5), + (5790, 9), + (5791, 1), (5792, 3), - (5793, 2), - (5794, 1), - (5795, 1), - (5797, 2), - (5798, 2), + (5793, 4), + (5794, 5), + (5795, 2), + (5797, 3), + (5798, 6), (5799, 1), (5801, 1), - (5825, 3), - (5826, 1), - (5827, 3), - (5828, 3), - (5829, 5), - (5831, 3), - (5832, 5), - (5833, 2), + (5803, 1), + (5825, 2), + (5828, 2), + (5829, 9), + (5830, 3), + (5831, 1), + (5832, 7), + (5833, 4), (5834, 1), - (5835, 2), - (5839, 2), - (5862, 1), + (5835, 8), + (5837, 1), + (5838, 2), + (5840, 1), (5863, 1), - (5865, 3), - (5868, 1), - (5869, 3), - (5870, 2), - (5871, 4), - (5872, 2), - (5874, 2), - (5875, 3), - (5876, 3), - (5901, 1), - (5903, 2), - (5904, 1), - (5905, 1), - (5906, 1), - (5907, 3), + (5864, 1), + (5866, 1), + (5867, 2), + (5868, 3), + (5869, 6), + (5870, 4), + (5871, 6), + (5872, 4), + (5873, 1), + (5874, 7), + (5875, 4), + (5876, 2), + (5878, 4), + (5902, 2), + (5906, 2), + (5907, 6), (5908, 3), (5909, 1), - (5910, 2), + (5910, 1), (5911, 2), - (5912, 2), - (5914, 1), - (5915, 3), - (5917, 1), - (5941, 1), + (5912, 5), + (5913, 2), + (5914, 3), + (5915, 1), + (5916, 1), + (5940, 1), (5942, 2), - (5943, 2), - (5944, 2), + (5943, 1), (5945, 2), - (5946, 2), - (5947, 4), - (5948, 1), - (5949, 1), + (5946, 3), + (5947, 6), + (5948, 5), + (5949, 2), (5950, 2), - (5951, 2), - (5952, 2), - (5953, 2), - (5955, 2), - (5957, 2), - (5980, 1), - (5981, 2), - (5982, 4), + (5951, 1), + (5952, 1), + (5953, 4), + (5954, 4), + (5955, 1), + (5956, 2), + (5957, 1), + (5983, 1), (5984, 3), (5985, 2), - (5986, 2), - (5987, 3), + (5986, 3), + (5987, 5), + (5988, 1), (5989, 4), - (5991, 2), + (5990, 2), + (5991, 4), + (5992, 4), (5993, 2), (5994, 2), - (5995, 2), - (5996, 1), + (5995, 1), + (5996, 2), + (5997, 1), + (5998, 1), (6019, 1), - (6021, 2), - (6022, 1), - (6023, 1), - (6024, 5), + (6020, 1), + (6021, 1), + (6023, 2), + (6024, 4), (6025, 2), - (6026, 1), - (6027, 3), - (6028, 6), - (6030, 1), - (6031, 1), + (6026, 5), + (6027, 1), + (6028, 5), + (6029, 2), + (6030, 4), + (6031, 3), (6032, 1), + (6033, 1), (6034, 1), - (6059, 4), + (6035, 1), + (6058, 2), (6060, 2), (6061, 3), (6062, 1), - (6063, 1), + (6063, 4), + (6064, 3), (6065, 4), - (6066, 2), - (6067, 2), - (6068, 1), - (6069, 2), - (6070, 3), - (6071, 2), - (6073, 1), - (6074, 2), + (6066, 5), + (6067, 5), + (6068, 3), + (6069, 4), + (6070, 1), + (6071, 4), + (6072, 3), + (6073, 2), + (6097, 1), (6098, 1), (6099, 1), (6100, 1), - (6101, 1), - (6102, 3), + (6102, 4), (6103, 1), - (6104, 2), - (6105, 6), - (6106, 3), + (6104, 5), + (6105, 3), + (6106, 2), (6107, 1), - (6108, 2), + (6109, 1), (6111, 2), - (6112, 1), - (6114, 1), + (6113, 1), + (6114, 2), (6130, 1), - (6135, 1), - (6137, 1), - (6138, 2), + (6136, 1), + (6137, 2), (6139, 1), - (6141, 4), - (6142, 1), + (6140, 1), + (6141, 1), + (6142, 4), (6143, 2), - (6144, 1), - (6146, 1), - (6148, 2), - (6150, 2), - (6151, 1), - (6177, 3), - (6178, 2), - (6179, 2), - (6180, 2), - (6181, 2), - (6182, 1), - (6185, 1), + (6144, 2), + (6146, 5), + (6147, 3), + (6148, 4), + (6149, 3), + (6150, 1), + (6151, 4), + (6152, 2), + (6153, 1), + (6175, 1), + (6177, 4), + (6178, 1), + (6179, 4), + (6180, 3), + (6181, 4), + (6182, 7), + (6183, 3), + (6184, 4), + (6185, 5), (6186, 2), - (6187, 1), - (6188, 2), - (6189, 2), - (6190, 2), - (6215, 2), - (6216, 3), + (6187, 4), + (6188, 1), + (6189, 3), + (6190, 3), + (6191, 1), + (6215, 1), (6217, 3), - (6218, 1), - (6219, 3), - (6220, 3), - (6221, 6), + (6219, 2), + (6220, 1), + (6221, 5), (6222, 2), - (6223, 3), - (6224, 3), + (6223, 1), + (6224, 4), (6225, 1), - (6226, 2), - (6227, 1), - (6228, 1), - (6254, 1), - (6255, 1), + (6226, 3), + (6227, 2), + (6228, 2), + (6229, 4), + (6230, 2), + (6253, 1), (6256, 1), (6257, 1), - (6258, 1), - (6259, 3), - (6260, 3), - (6261, 2), - (6262, 2), - (6264, 2), - (6266, 1), - (6292, 1), - (6293, 1), - (6294, 1), - (6295, 1), - (6296, 3), + (6258, 3), + (6259, 4), + (6260, 6), + (6261, 4), + (6263, 3), + (6264, 3), + (6265, 4), + (6266, 5), + (6267, 1), + (6268, 2), + (6269, 2), + (6273, 1), + (6292, 2), + (6296, 2), (6298, 3), - (6299, 5), - (6300, 2), + (6299, 8), + (6300, 5), (6301, 2), - (6302, 2), - (6303, 3), - (6304, 1), - (6305, 2), - (6306, 2), - (6307, 1), - (6308, 2), + (6302, 5), + (6303, 2), + (6304, 3), + (6305, 3), + (6306, 4), + (6307, 5), + (6308, 3), + (6309, 1), (6324, 1), - (6330, 1), - (6331, 2), - (6332, 2), - (6333, 4), - (6334, 2), + (6332, 1), + (6333, 1), + (6334, 4), (6335, 1), - (6337, 3), - (6338, 1), - (6339, 1), - (6341, 2), - (6342, 2), - (6343, 1), - (6344, 2), + (6336, 1), + (6337, 6), + (6338, 5), + (6339, 4), + (6340, 1), + (6342, 4), + (6343, 4), + (6344, 1), (6345, 1), - (6347, 1), - (6372, 1), - (6374, 4), - (6375, 2), + (6346, 1), + (6348, 3), + (6349, 1), + (6369, 1), + (6370, 2), + (6371, 1), + (6374, 1), (6376, 2), + (6377, 3), (6378, 3), - (6379, 5), + (6379, 2), + (6380, 2), + (6381, 2), (6382, 1), - (6383, 3), + (6383, 2), (6384, 1), - (6386, 1), - (6402, 8), - (6408, 1), - (6410, 2), - (6413, 1), - (6414, 2), - (6415, 1), + (6385, 3), + (6386, 2), + (6409, 1), + (6413, 2), + (6414, 1), + (6415, 4), (6416, 2), - (6417, 3), - (6418, 3), - (6419, 3), - (6420, 1), - (6421, 1), - (6423, 2), - (6426, 1), + (6417, 2), + (6418, 4), + (6419, 2), + (6420, 3), + (6421, 2), + (6422, 3), + (6423, 6), + (6424, 3), + (6426, 3), (6430, 1), - (6447, 1), - (6448, 2), - (6451, 2), - (6452, 3), + (6450, 1), + (6451, 1), + (6452, 2), (6453, 2), (6454, 1), - (6455, 4), - (6456, 3), - (6457, 3), - (6459, 3), - (6461, 2), - (6462, 2), - (6463, 1), - (6486, 2), - (6490, 1), - (6492, 3), - (6493, 1), - (6494, 5), - (6495, 3), - (6496, 2), + (6455, 2), + (6456, 2), + (6457, 7), + (6458, 1), + (6459, 7), + (6460, 2), + (6461, 3), + (6463, 2), + (6464, 3), + (6466, 2), + (6489, 1), + (6493, 2), + (6494, 7), + (6495, 2), + (6496, 4), (6497, 2), - (6498, 4), - (6499, 2), - (6500, 1), - (6501, 3), - (6502, 1), - (6503, 3), - (6504, 1), + (6498, 8), + (6499, 1), + (6501, 4), + (6502, 2), + (6503, 4), (6505, 1), - (6527, 1), (6528, 2), - (6530, 2), - (6531, 4), - (6533, 2), - (6535, 1), - (6536, 2), + (6530, 4), + (6531, 1), + (6532, 2), + (6533, 1), + (6534, 4), + (6535, 4), (6537, 1), - (6538, 2), - (6541, 1), - (6564, 1), + (6538, 3), + (6539, 4), + (6540, 2), + (6541, 2), + (6542, 4), + (6543, 1), (6565, 1), (6566, 1), - (6567, 1), + (6568, 1), (6569, 3), (6570, 4), - (6571, 2), - (6572, 2), - (6573, 4), - (6574, 5), - (6575, 1), - (6576, 1), - (6577, 2), - (6578, 2), - (6579, 2), - (6580, 1), + (6571, 3), + (6572, 4), + (6573, 1), + (6574, 2), + (6575, 3), + (6576, 3), + (6577, 1), + (6578, 3), + (6579, 3), + (6580, 4), (6581, 1), - (6582, 1), - (6603, 2), - (6604, 2), - (6605, 1), + (6582, 2), + (6584, 1), (6606, 1), - (6607, 1), - (6608, 1), + (6607, 2), + (6608, 2), (6609, 3), - (6610, 3), - (6611, 1), - (6612, 2), - (6613, 1), - (6614, 2), + (6610, 2), + (6611, 4), + (6612, 4), + (6613, 2), + (6614, 1), (6615, 1), - (6617, 4), - (6618, 4), + (6616, 6), + (6617, 1), + (6618, 1), (6619, 1), - (6620, 4), - (6644, 1), - (6645, 1), - (6646, 1), - (6647, 1), + (6620, 1), + (6621, 2), + (6647, 3), (6648, 5), - (6649, 2), - (6650, 1), - (6651, 1), + (6649, 3), + (6650, 2), + (6651, 4), (6652, 3), - (6653, 2), - (6654, 3), - (6655, 1), - (6656, 2), - (6657, 2), - (6658, 2), - (6686, 1), - (6687, 4), - (6688, 5), - (6689, 4), - (6690, 1), - (6692, 1), - (6693, 1), - (6694, 3), + (6653, 3), + (6654, 1), + (6655, 5), + (6656, 3), + (6657, 1), + (6658, 3), + (6661, 1), + (6682, 1), + (6685, 4), + (6687, 1), + (6688, 3), + (6689, 5), + (6690, 5), + (6691, 1), + (6692, 2), + (6694, 5), (6695, 3), - (6696, 1), - (6697, 1), - (6722, 2), + (6696, 2), + (6697, 2), + (6698, 5), + (6720, 2), + (6722, 1), (6723, 1), - (6724, 1), + (6724, 2), (6725, 3), - (6726, 1), - (6727, 2), - (6728, 2), - (6729, 6), - (6731, 1), - (6734, 1), - (6735, 3), + (6726, 5), + (6727, 5), + (6729, 5), + (6731, 2), + (6732, 2), + (6733, 4), + (6734, 2), + (6735, 5), (6736, 3), - (6737, 1), - (6761, 2), + (6737, 2), + (6738, 1), + (6740, 1), + (6760, 1), (6762, 1), - (6763, 3), - (6764, 2), - (6765, 1), - (6766, 5), - (6767, 1), - (6769, 3), - (6770, 2), - (6771, 3), - (6772, 3), + (6765, 5), + (6766, 1), + (6767, 4), + (6768, 4), + (6769, 2), + (6770, 3), + (6771, 10), (6773, 3), (6774, 4), - (6775, 1), - (6777, 1), - (6798, 1), - (6800, 2), - (6801, 1), - (6802, 3), - (6803, 2), - (6804, 3), - (6805, 2), - (6806, 7), - (6807, 1), - (6808, 2), + (6775, 4), + (6776, 1), + (6778, 1), + (6803, 3), + (6805, 3), + (6806, 4), + (6807, 2), + (6808, 6), (6809, 2), - (6810, 4), - (6811, 2), + (6810, 5), + (6811, 3), (6812, 3), (6813, 2), - (6814, 1), + (6814, 3), (6815, 1), - (6816, 2), - (6837, 1), + (6816, 1), + (6820, 1), (6839, 1), - (6841, 5), - (6842, 3), + (6841, 2), + (6842, 1), (6843, 4), - (6844, 5), - (6845, 1), - (6847, 3), - (6848, 1), - (6849, 2), - (6850, 3), - (6851, 1), - (6852, 2), - (6853, 2), - (6855, 1), + (6844, 1), + (6845, 3), + (6846, 2), + (6847, 1), + (6848, 4), + (6849, 4), + (6850, 7), + (6851, 3), + (6852, 6), + (6853, 4), + (6854, 2), + (6855, 2), + (6856, 1), (6863, 6), - (6878, 1), - (6879, 2), - (6881, 2), - (6882, 3), - (6883, 2), - (6884, 4), - (6885, 4), - (6886, 2), - (6887, 3), - (6888, 3), - (6889, 3), + (6879, 1), + (6882, 4), + (6883, 3), + (6884, 2), + (6885, 3), + (6886, 4), + (6887, 2), + (6888, 2), + (6889, 2), (6890, 1), - (6891, 2), - (6892, 2), - (6896, 1), - (6915, 1), - (6916, 2), - (6917, 2), - (6918, 1), + (6891, 4), + (6892, 1), + (6893, 1), + (6894, 1), + (6916, 1), + (6917, 1), (6919, 1), - (6921, 1), - (6922, 2), - (6923, 8), - (6924, 3), - (6926, 7), + (6921, 3), + (6922, 3), + (6923, 3), + (6924, 8), + (6925, 2), + (6926, 2), (6927, 2), - (6928, 2), - (6929, 1), + (6928, 1), + (6929, 3), + (6930, 3), + (6931, 2), (6932, 1), + (6933, 1), + (6934, 1), (6952, 6), + (6954, 1), (6956, 1), - (6957, 4), - (6959, 5), + (6957, 1), + (6958, 1), + (6959, 3), (6960, 2), - (6961, 6), - (6962, 6), - (6963, 1), + (6961, 3), + (6962, 4), (6964, 2), - (6965, 5), - (6967, 4), - (6969, 1), - (6970, 3), - (6971, 1), - (6972, 1), + (6965, 3), + (6966, 3), + (6967, 3), + (6968, 1), + (6969, 6), + (6970, 1), + (6971, 2), + (6973, 1), (6993, 1), (6995, 2), (6996, 1), - (6997, 2), - (6998, 1), + (6997, 1), + (6998, 2), (6999, 1), - (7000, 5), - (7001, 2), - (7002, 4), - (7003, 3), + (7000, 1), + (7001, 3), + (7002, 6), + (7003, 1), (7004, 1), - (7005, 1), - (7007, 2), + (7005, 3), + (7006, 6), + (7007, 4), (7008, 2), - (7009, 1), - (7010, 1), - (7014, 1), - (7033, 1), - (7035, 2), - (7037, 1), - (7038, 3), - (7039, 2), - (7040, 8), + (7009, 5), + (7010, 2), + (7034, 1), + (7035, 1), + (7037, 3), + (7038, 1), + (7039, 1), + (7040, 5), (7041, 1), - (7042, 2), - (7043, 2), - (7044, 1), - (7045, 1), + (7042, 4), + (7043, 6), + (7044, 2), + (7045, 2), (7046, 2), - (7047, 1), + (7047, 4), (7048, 2), - (7070, 1), - (7073, 1), - (7075, 1), + (7050, 1), + (7074, 1), (7076, 1), - (7077, 1), - (7078, 3), - (7079, 5), - (7080, 4), - (7081, 4), - (7083, 1), - (7084, 2), - (7085, 4), - (7086, 2), - (7088, 2), - (7089, 3), + (7077, 4), + (7078, 4), + (7080, 6), + (7081, 2), + (7083, 5), + (7084, 3), + (7085, 1), + (7086, 1), + (7087, 2), + (7088, 1), + (7089, 1), + (7090, 1), (7098, 6), (7111, 1), (7113, 1), - (7114, 3), - (7115, 7), - (7117, 3), - (7118, 6), - (7119, 1), - (7120, 2), - (7121, 2), - (7122, 3), - (7123, 1), - (7125, 2), + (7114, 2), + (7115, 2), + (7116, 4), + (7117, 2), + (7118, 2), + (7119, 4), + (7120, 3), + (7121, 3), + (7122, 7), + (7123, 5), + (7124, 1), + (7125, 4), (7126, 2), - (7130, 1), + (7127, 1), + (7129, 3), + (7150, 2), + (7151, 1), (7153, 5), - (7155, 2), - (7156, 4), - (7157, 3), + (7154, 2), + (7155, 1), + (7156, 1), + (7157, 6), (7158, 2), - (7159, 1), - (7160, 2), + (7159, 2), + (7160, 3), (7161, 1), - (7162, 2), - (7163, 4), - (7164, 3), - (7167, 3), + (7162, 4), + (7164, 4), + (7165, 1), + (7167, 1), (7184, 2), - (7190, 1), (7192, 1), - (7194, 1), - (7196, 4), + (7194, 3), + (7195, 3), + (7196, 1), + (7197, 4), (7198, 1), - (7199, 2), - (7200, 4), - (7201, 4), - (7202, 2), + (7199, 5), + (7200, 6), + (7201, 2), + (7202, 6), (7203, 1), - (7204, 2), - (7230, 2), - (7231, 1), - (7232, 3), - (7233, 3), - (7234, 1), - (7235, 2), - (7236, 3), - (7238, 2), + (7204, 5), + (7205, 2), + (7232, 2), + (7233, 2), + (7234, 4), + (7235, 6), + (7236, 2), + (7238, 1), (7239, 4), - (7240, 1), - (7241, 3), + (7240, 2), + (7241, 4), (7242, 3), - (7243, 2), + (7243, 4), (7244, 1), - (7245, 1), - (7248, 1), + (7246, 3), + (7248, 2), (7266, 1), (7268, 1), - (7270, 2), - (7271, 4), - (7272, 1), - (7273, 2), - (7274, 6), - (7275, 2), - (7278, 3), - (7279, 4), - (7280, 2), - (7281, 1), - (7282, 2), - (7283, 1), + (7270, 1), + (7271, 3), + (7273, 4), + (7274, 4), + (7275, 1), + (7276, 3), + (7277, 2), + (7278, 2), + (7279, 2), + (7280, 4), + (7281, 2), + (7282, 3), + (7284, 1), (7289, 1), - (7306, 1), - (7307, 1), - (7308, 2), + (7308, 1), (7309, 1), - (7310, 2), - (7311, 2), - (7312, 3), + (7310, 3), + (7311, 1), + (7312, 5), (7313, 3), (7314, 1), - (7315, 4), + (7315, 6), (7316, 3), (7317, 2), - (7318, 4), - (7319, 1), - (7320, 2), - (7321, 1), - (7324, 1), - (7345, 1), - (7347, 2), - (7348, 6), + (7318, 3), + (7319, 3), + (7320, 4), + (7321, 3), + (7322, 1), + (7323, 1), + (7324, 3), + (7325, 1), + (7348, 2), (7349, 2), - (7350, 6), - (7351, 8), - (7352, 2), - (7353, 4), - (7358, 2), - (7359, 2), - (7360, 2), - (7361, 2), + (7350, 1), + (7351, 3), + (7352, 4), + (7353, 3), + (7354, 4), + (7355, 2), + (7356, 3), + (7358, 4), + (7359, 3), + (7360, 5), + (7361, 3), + (7362, 1), + (7363, 1), (7372, 6), - (7385, 1), - (7386, 3), + (7386, 1), (7387, 1), - (7388, 1), (7389, 3), - (7390, 3), - (7391, 1), + (7390, 7), + (7391, 2), (7392, 4), - (7394, 3), + (7393, 4), (7395, 3), - (7396, 4), - (7397, 2), - (7398, 4), + (7396, 3), + (7397, 3), + (7398, 5), (7399, 2), - (7401, 1), + (7400, 1), + (7401, 3), + (7402, 2), (7403, 1), + (7424, 2), (7425, 1), (7426, 2), - (7427, 5), - (7428, 4), - (7429, 5), - (7430, 4), - (7431, 1), - (7432, 1), - (7434, 1), - (7435, 2), - (7436, 7), - (7437, 1), - (7438, 1), + (7427, 7), + (7428, 6), + (7429, 2), + (7430, 3), + (7431, 4), + (7432, 3), + (7433, 1), + (7434, 2), + (7435, 3), + (7436, 1), + (7438, 4), (7439, 1), + (7440, 1), (7446, 1), + (7461, 1), (7464, 1), - (7466, 2), - (7467, 3), + (7467, 2), (7468, 2), - (7469, 5), - (7470, 3), - (7471, 2), - (7472, 1), - (7474, 1), - (7475, 4), - (7476, 4), + (7469, 2), + (7470, 5), + (7471, 4), + (7472, 2), + (7473, 1), + (7474, 2), + (7475, 8), + (7476, 3), + (7477, 6), + (7478, 4), + (7479, 1), + (7480, 1), + (7482, 1), (7489, 1), (7490, 6), + (7502, 2), (7503, 1), - (7504, 2), + (7504, 1), (7505, 3), (7506, 2), - (7507, 2), + (7507, 1), (7508, 2), - (7509, 1), - (7510, 2), + (7509, 4), + (7510, 3), (7511, 3), - (7512, 3), + (7512, 1), (7513, 5), - (7514, 1), - (7515, 4), - (7517, 1), - (7518, 1), - (7520, 1), - (7522, 1), - (7539, 1), - (7541, 2), - (7544, 6), - (7545, 3), - (7546, 2), - (7547, 5), - (7548, 3), + (7514, 7), + (7515, 5), + (7516, 7), + (7517, 2), + (7518, 4), + (7519, 1), + (7520, 2), + (7544, 4), + (7545, 4), + (7546, 3), + (7547, 3), + (7548, 6), (7549, 2), - (7550, 1), + (7550, 2), + (7551, 3), (7552, 1), - (7553, 5), - (7554, 2), - (7555, 2), + (7553, 2), + (7554, 4), + (7555, 3), (7556, 1), - (7558, 1), - (7559, 1), - (7583, 2), - (7584, 3), + (7557, 3), + (7558, 2), + (7559, 2), + (7578, 1), + (7584, 2), (7585, 5), - (7586, 3), - (7587, 2), - (7588, 5), - (7589, 1), - (7591, 2), - (7592, 3), - (7593, 4), - (7594, 1), - (7595, 2), - (7596, 2), - (7620, 1), - (7621, 3), - (7623, 5), + (7586, 4), + (7588, 3), + (7589, 2), + (7590, 2), + (7591, 4), + (7592, 6), + (7593, 3), + (7594, 3), + (7595, 4), + (7597, 1), + (7619, 1), + (7621, 1), + (7622, 2), + (7623, 1), (7624, 3), - (7625, 3), - (7626, 3), - (7627, 4), - (7628, 5), - (7629, 1), - (7630, 1), - (7631, 1), - (7632, 3), - (7633, 2), - (7634, 1), - (7635, 1), - (7639, 1), + (7625, 1), + (7626, 1), + (7628, 3), + (7630, 5), + (7631, 4), + (7632, 2), + (7633, 4), + (7634, 5), + (7635, 4), + (7636, 1), + (7637, 1), (7648, 6), (7655, 6), (7659, 2), - (7660, 2), - (7662, 2), - (7663, 1), - (7664, 3), - (7665, 6), - (7667, 1), - (7670, 3), + (7660, 1), + (7661, 3), + (7662, 4), + (7663, 3), + (7664, 2), + (7665, 3), + (7667, 2), + (7668, 2), + (7669, 2), + (7670, 4), (7671, 3), - (7672, 1), - (7673, 2), - (7674, 1), - (7675, 1), - (7676, 1), + (7672, 4), + (7673, 5), (7685, 1), - (7699, 2), - (7700, 2), - (7701, 5), - (7702, 3), - (7703, 5), - (7704, 3), - (7705, 1), - (7706, 2), - (7707, 5), - (7708, 4), - (7709, 2), - (7710, 1), - (7713, 1), - (7714, 1), - (7738, 2), + (7699, 1), + (7700, 1), + (7701, 2), + (7702, 6), + (7703, 3), + (7704, 2), + (7705, 4), + (7706, 1), + (7707, 4), + (7708, 3), + (7709, 3), + (7710, 3), + (7711, 4), (7739, 2), (7740, 3), (7741, 4), - (7742, 3), + (7742, 6), (7743, 2), - (7744, 4), - (7745, 3), - (7746, 1), - (7748, 2), - (7750, 3), - (7751, 1), - (7752, 2), - (7753, 1), + (7744, 6), + (7746, 4), + (7747, 2), + (7748, 4), + (7750, 2), + (7751, 2), + (7752, 1), + (7753, 2), + (7754, 1), (7776, 2), - (7777, 3), - (7778, 2), - (7779, 2), - (7780, 3), - (7781, 3), - (7782, 5), - (7783, 4), - (7784, 2), - (7786, 4), - (7787, 2), - (7788, 2), - (7789, 4), - (7794, 1), - (7812, 1), - (7816, 1), - (7817, 3), - (7818, 2), - (7819, 3), + (7777, 1), + (7779, 3), + (7780, 1), + (7781, 6), + (7782, 4), + (7783, 2), + (7784, 3), + (7787, 3), + (7788, 4), + (7789, 3), + (7790, 3), + (7791, 3), + (7792, 2), + (7813, 1), + (7817, 4), + (7818, 1), (7820, 3), - (7821, 8), - (7822, 3), - (7823, 3), - (7824, 3), + (7821, 2), + (7823, 1), + (7824, 4), (7825, 2), - (7827, 1), - (7828, 3), + (7826, 3), + (7827, 2), + (7828, 5), (7830, 2), - (7831, 1), + (7831, 2), + (7832, 1), (7836, 6), - (7851, 1), - (7853, 1), + (7852, 1), + (7853, 2), (7855, 1), - (7857, 1), + (7856, 1), + (7857, 4), (7858, 1), - (7859, 2), - (7860, 3), - (7861, 1), + (7859, 4), + (7860, 2), + (7862, 5), (7863, 1), - (7864, 6), - (7865, 4), - (7866, 4), - (7867, 4), + (7864, 2), + (7866, 1), + (7867, 2), (7868, 1), (7869, 1), + (7870, 1), (7871, 1), - (7894, 2), - (7895, 5), - (7896, 6), - (7897, 5), - (7898, 1), + (7894, 1), + (7895, 2), + (7896, 4), + (7897, 3), + (7898, 4), (7899, 1), - (7900, 1), - (7901, 3), + (7900, 3), + (7901, 6), (7902, 1), - (7903, 1), - (7904, 9), - (7905, 2), - (7906, 1), + (7903, 3), + (7904, 7), + (7906, 4), (7907, 2), + (7908, 2), (7909, 1), (7910, 1), - (7932, 3), - (7933, 9), - (7934, 1), - (7935, 4), - (7936, 3), - (7937, 7), + (7911, 1), + (7912, 1), + (7933, 6), + (7935, 2), + (7936, 5), + (7937, 3), (7938, 2), - (7939, 4), - (7940, 3), + (7939, 1), + (7940, 2), (7941, 1), (7942, 2), - (7943, 4), - (7944, 2), - (7945, 5), - (7946, 2), + (7943, 1), + (7944, 4), + (7945, 3), + (7946, 6), (7948, 1), (7949, 1), (7960, 6), (7967, 2), - (7970, 2), - (7972, 2), - (7973, 1), + (7971, 1), + (7973, 5), (7974, 2), - (7975, 1), - (7976, 3), - (7977, 2), + (7975, 4), + (7976, 2), (7978, 2), (7979, 1), - (7980, 5), + (7980, 3), (7981, 1), - (7982, 2), + (7982, 5), (7983, 3), - (7984, 3), (7985, 1), - (7986, 4), - (7987, 1), - (7988, 1), - (8011, 4), - (8012, 5), - (8013, 1), - (8014, 3), - (8015, 3), + (7986, 1), + (7987, 6), + (8002, 8), + (8010, 1), + (8011, 2), + (8012, 1), + (8013, 3), + (8014, 2), + (8015, 1), (8016, 1), - (8017, 5), - (8018, 1), - (8019, 3), - (8021, 1), - (8022, 6), - (8023, 4), - (8024, 1), - (8025, 1), - (8027, 1), + (8017, 3), + (8018, 2), + (8019, 1), + (8021, 2), + (8022, 3), + (8023, 3), (8028, 2), - (8029, 2), - (8050, 2), - (8051, 3), - (8052, 1), - (8053, 6), - (8054, 3), + (8051, 5), + (8053, 2), + (8054, 4), (8055, 1), - (8056, 2), - (8057, 4), - (8058, 2), - (8059, 4), - (8060, 3), - (8061, 3), - (8062, 2), - (8063, 1), + (8056, 1), + (8057, 3), + (8058, 1), + (8059, 8), + (8060, 5), + (8061, 4), + (8062, 5), + (8063, 2), (8064, 2), - (8065, 1), - (8066, 1), + (8065, 2), + (8066, 2), (8067, 1), (8079, 1), - (8088, 2), (8090, 2), - (8091, 5), - (8092, 3), - (8093, 4), + (8092, 4), + (8093, 2), (8094, 1), - (8095, 3), + (8095, 1), (8096, 2), - (8097, 3), - (8098, 2), (8099, 2), - (8100, 2), - (8101, 2), - (8103, 6), - (8104, 1), - (8106, 1), - (8108, 1), - (8128, 2), - (8129, 3), - (8130, 13), - (8131, 4), - (8132, 2), - (8133, 2), - (8134, 3), - (8136, 2), - (8137, 2), - (8139, 7), - (8140, 7), - (8141, 3), + (8100, 4), + (8101, 4), + (8102, 2), + (8105, 2), + (8107, 1), + (8128, 1), + (8129, 2), + (8130, 11), + (8131, 2), + (8133, 4), + (8134, 1), + (8136, 3), + (8137, 3), + (8138, 4), + (8139, 3), + (8140, 3), + (8141, 2), (8142, 1), - (8143, 2), + (8144, 1), (8145, 1), - (8167, 1), - (8168, 1), - (8169, 5), - (8171, 6), - (8172, 2), - (8173, 1), + (8166, 1), + (8167, 2), + (8169, 3), + (8171, 3), + (8172, 1), (8174, 2), - (8175, 1), + (8175, 2), (8176, 1), - (8177, 7), + (8177, 1), + (8178, 3), + (8179, 1), (8180, 2), (8182, 1), - (8206, 1), - (8207, 6), + (8183, 1), + (8207, 2), (8208, 4), - (8209, 5), + (8209, 2), (8210, 3), - (8211, 7), - (8212, 4), - (8213, 3), + (8211, 1), + (8212, 1), + (8213, 2), (8214, 4), (8215, 2), - (8216, 4), - (8217, 2), + (8216, 3), + (8217, 4), (8218, 4), - (8219, 3), - (8220, 2), + (8219, 1), (8221, 1), - (8222, 1), (8240, 6), - (8244, 2), - (8245, 1), + (8244, 1), (8246, 2), - (8247, 5), - (8248, 6), - (8249, 1), - (8250, 1), - (8251, 2), - (8252, 5), - (8253, 1), - (8254, 7), - (8255, 4), - (8256, 2), - (8257, 3), - (8258, 4), - (8259, 2), - (8260, 3), - (8261, 1), - (8282, 1), - (8284, 2), - (8285, 3), + (8247, 4), + (8248, 3), + (8249, 3), + (8250, 2), + (8251, 1), + (8254, 3), + (8255, 2), + (8256, 4), + (8257, 5), + (8258, 2), + (8259, 1), + (8260, 1), + (8284, 1), + (8285, 4), (8286, 4), - (8287, 5), - (8288, 1), - (8289, 3), - (8290, 4), - (8291, 3), - (8292, 2), - (8294, 1), - (8295, 1), - (8296, 3), - (8297, 3), - (8298, 2), - (8299, 2), + (8287, 2), + (8288, 3), + (8289, 2), + (8290, 2), + (8291, 5), + (8292, 1), + (8293, 2), + (8295, 3), + (8296, 2), + (8297, 1), + (8299, 1), (8302, 1), (8314, 1), - (8320, 1), - (8321, 1), + (8319, 1), (8322, 1), - (8323, 1), - (8324, 2), - (8325, 2), - (8326, 2), + (8324, 3), + (8325, 4), + (8326, 3), (8327, 2), - (8328, 4), - (8329, 2), - (8330, 1), - (8331, 1), - (8332, 4), + (8328, 1), + (8329, 1), + (8330, 2), + (8331, 3), (8333, 3), - (8334, 3), + (8334, 4), (8335, 3), - (8336, 1), - (8337, 1), - (8339, 2), + (8336, 3), (8340, 1), (8342, 6), (8360, 1), (8362, 1), - (8363, 5), - (8364, 6), - (8365, 3), - (8366, 2), - (8367, 6), - (8368, 2), - (8369, 2), - (8370, 3), - (8372, 5), + (8364, 8), + (8365, 1), + (8366, 1), + (8367, 1), + (8368, 1), + (8369, 3), + (8371, 3), + (8372, 2), (8373, 2), - (8374, 7), - (8375, 3), - (8377, 2), - (8398, 1), - (8400, 2), - (8402, 2), - (8403, 4), - (8404, 1), - (8405, 2), - (8406, 2), - (8407, 2), - (8408, 4), - (8409, 3), + (8374, 4), + (8375, 5), + (8376, 2), + (8378, 1), + (8379, 1), + (8401, 3), + (8404, 2), + (8405, 1), + (8406, 1), + (8407, 1), + (8408, 2), + (8409, 1), (8410, 4), - (8411, 3), - (8412, 2), - (8413, 2), - (8414, 5), - (8415, 2), + (8411, 4), + (8412, 4), + (8413, 1), + (8414, 3), (8416, 1), + (8417, 1), (8439, 2), - (8440, 1), - (8441, 3), (8442, 4), (8443, 2), - (8444, 5), - (8445, 2), - (8446, 1), - (8447, 3), + (8445, 1), + (8446, 3), + (8447, 2), (8448, 1), - (8449, 4), + (8449, 2), (8450, 3), - (8451, 6), + (8451, 7), (8452, 2), - (8453, 3), - (8455, 3), - (8456, 2), + (8453, 2), + (8455, 2), + (8456, 3), + (8458, 1), (8465, 1), - (8480, 4), - (8481, 5), - (8482, 7), - (8483, 4), - (8484, 2), + (8475, 1), + (8479, 2), + (8480, 2), + (8481, 3), + (8482, 9), + (8483, 5), + (8484, 4), (8485, 3), - (8487, 1), - (8488, 3), - (8489, 3), - (8490, 6), - (8491, 4), - (8492, 5), + (8486, 1), + (8487, 3), + (8488, 4), + (8489, 1), + (8490, 2), + (8491, 2), + (8492, 2), + (8494, 1), (8495, 1), - (8518, 2), (8519, 1), - (8520, 3), - (8521, 1), - (8522, 4), - (8523, 2), - (8524, 1), + (8520, 1), + (8521, 6), + (8522, 5), + (8523, 1), + (8524, 2), (8525, 1), - (8526, 2), - (8527, 5), + (8526, 4), + (8527, 2), (8528, 1), - (8529, 2), - (8530, 5), - (8531, 4), + (8529, 1), + (8530, 4), + (8531, 2), (8532, 3), - (8533, 3), - (8534, 1), - (8536, 1), - (8557, 4), - (8558, 4), - (8559, 3), - (8561, 3), - (8562, 1), - (8563, 1), - (8564, 1), - (8566, 1), - (8567, 1), - (8568, 4), - (8569, 2), - (8570, 6), - (8571, 4), - (8572, 4), - (8573, 3), - (8574, 1), + (8535, 1), + (8557, 1), + (8558, 1), + (8559, 1), + (8560, 1), + (8564, 2), + (8565, 1), + (8566, 3), + (8567, 2), + (8569, 3), + (8570, 3), + (8571, 3), + (8572, 2), + (8573, 1), (8575, 1), (8576, 6), (8583, 1), (8587, 4), - (8596, 1), - (8597, 3), - (8598, 1), - (8599, 3), - (8600, 2), - (8601, 2), + (8595, 1), + (8599, 4), + (8600, 5), + (8601, 1), (8602, 2), (8603, 2), - (8604, 1), - (8605, 2), - (8606, 2), - (8607, 2), - (8608, 1), + (8604, 3), + (8605, 1), + (8606, 1), + (8607, 1), + (8608, 4), (8609, 2), (8610, 2), (8611, 2), - (8612, 2), + (8613, 1), (8633, 1), - (8634, 8), - (8635, 3), - (8636, 1), - (8637, 3), - (8638, 3), - (8639, 1), - (8640, 2), - (8641, 1), - (8642, 2), - (8643, 2), - (8645, 4), - (8646, 2), - (8647, 8), - (8648, 5), - (8649, 1), - (8650, 3), + (8634, 6), + (8636, 2), + (8637, 1), + (8638, 1), + (8639, 2), + (8640, 1), + (8643, 1), + (8645, 1), + (8646, 3), + (8647, 1), + (8649, 3), + (8650, 4), + (8651, 1), (8653, 5), - (8673, 1), - (8675, 1), - (8676, 1), - (8677, 5), + (8675, 2), + (8676, 2), + (8677, 2), (8678, 4), - (8679, 4), - (8680, 2), - (8681, 3), - (8682, 3), - (8683, 3), + (8679, 3), + (8681, 1), + (8682, 4), + (8683, 2), (8684, 2), (8685, 2), - (8686, 2), - (8687, 1), - (8688, 3), + (8686, 1), + (8687, 2), + (8688, 5), (8689, 2), (8701, 6), (8705, 6), (8710, 1), - (8712, 1), - (8713, 1), - (8714, 1), + (8714, 3), (8716, 1), - (8717, 6), (8718, 2), - (8719, 2), - (8721, 1), - (8723, 6), - (8724, 1), - (8725, 1), - (8726, 2), - (8727, 1), - (8728, 1), - (8731, 1), - (8753, 1), - (8754, 3), - (8755, 2), + (8719, 1), + (8720, 1), + (8721, 2), + (8722, 1), + (8723, 2), + (8724, 3), + (8725, 2), + (8727, 2), + (8728, 2), + (8751, 1), + (8752, 1), + (8754, 2), + (8755, 3), (8756, 1), (8757, 1), (8759, 6), - (8760, 1), - (8762, 2), - (8763, 3), - (8764, 3), - (8765, 2), + (8761, 2), + (8762, 1), + (8763, 1), + (8764, 4), + (8766, 1), + (8767, 1), (8768, 2), - (8770, 2), - (8791, 2), - (8793, 1), + (8791, 1), + (8793, 3), (8794, 2), - (8795, 1), (8796, 1), (8797, 1), + (8798, 2), (8799, 1), - (8800, 3), - (8801, 3), - (8802, 2), - (8803, 4), - (8804, 6), + (8800, 6), + (8801, 4), + (8802, 1), + (8803, 2), + (8804, 2), (8805, 3), - (8809, 1), + (8806, 1), (8816, 1), - (8827, 1), - (8829, 1), - (8830, 1), - (8832, 2), - (8833, 5), - (8834, 3), - (8835, 2), + (8832, 3), + (8834, 1), + (8835, 3), (8836, 1), - (8837, 3), - (8838, 2), - (8839, 1), - (8840, 3), + (8837, 1), + (8838, 1), + (8839, 2), + (8840, 1), (8841, 3), - (8842, 2), + (8842, 3), (8843, 2), + (8844, 2), (8845, 1), - (8869, 2), - (8870, 6), + (8847, 2), + (8870, 3), (8871, 1), (8872, 6), - (8875, 5), + (8873, 3), + (8874, 1), + (8875, 2), (8876, 4), - (8877, 1), - (8878, 5), - (8879, 2), - (8880, 3), + (8878, 1), + (8879, 4), + (8880, 4), + (8881, 1), (8882, 1), - (8884, 3), - (8885, 1), - (8886, 1), + (8883, 4), + (8884, 4), + (8885, 2), (8887, 6), - (8888, 1), - (8909, 1), (8910, 1), - (8911, 2), - (8912, 2), - (8914, 3), - (8917, 5), - (8918, 1), - (8919, 6), - (8920, 3), + (8912, 3), + (8913, 1), + (8915, 1), + (8916, 1), + (8917, 2), + (8919, 1), + (8920, 2), (8921, 4), - (8922, 6), + (8922, 3), (8923, 1), - (8928, 1), - (8946, 1), - (8948, 1), + (8944, 1), (8949, 2), - (8950, 9), - (8951, 2), - (8952, 2), - (8953, 2), - (8954, 2), - (8956, 2), - (8957, 1), - (8958, 3), - (8959, 5), + (8950, 8), + (8953, 3), + (8957, 7), + (8958, 1), + (8959, 2), (8960, 1), - (8961, 4), - (8962, 2), - (8985, 1), + (8961, 1), + (8963, 1), + (8964, 1), + (8986, 1), (8987, 1), - (8990, 2), - (8991, 3), - (8992, 2), - (8993, 2), - (8994, 1), - (8995, 1), - (8997, 6), - (8998, 3), + (8988, 1), + (8989, 4), + (8991, 2), + (8993, 3), + (8995, 2), + (8996, 4), + (8998, 2), (8999, 1), + (9000, 2), (9001, 1), - (9002, 1), (9003, 1), (9004, 5), (9007, 5), (9026, 1), - (9027, 2), - (9028, 3), - (9029, 2), - (9030, 2), + (9028, 2), + (9029, 1), (9031, 1), - (9034, 1), - (9035, 3), - (9036, 2), - (9037, 4), - (9038, 5), - (9039, 2), - (9064, 2), - (9065, 1), + (9033, 3), + (9034, 2), + (9035, 1), + (9036, 4), + (9038, 1), + (9040, 3), + (9041, 2), + (9064, 1), + (9065, 2), (9066, 2), (9067, 4), - (9069, 3), - (9070, 2), - (9071, 3), - (9072, 2), - (9074, 2), - (9075, 3), - (9076, 1), + (9070, 1), + (9071, 1), + (9073, 1), + (9075, 2), + (9076, 3), + (9077, 4), (9078, 3), (9079, 2), - (9080, 1), + (9080, 2), (9087, 1), - (9104, 1), - (9106, 1), - (9107, 2), + (9103, 1), + (9106, 2), + (9107, 3), (9108, 1), (9109, 1), (9110, 1), - (9111, 2), - (9112, 1), - (9113, 2), - (9114, 3), - (9115, 1), - (9116, 2), - (9117, 3), + (9111, 1), + (9112, 2), + (9113, 1), + (9114, 5), + (9115, 4), + (9116, 1), + (9117, 5), + (9118, 1), + (9119, 4), (9120, 1), - (9139, 1), - (9145, 3), + (9142, 1), + (9143, 1), + (9144, 1), + (9145, 1), (9146, 1), - (9147, 5), + (9147, 1), (9148, 1), - (9149, 3), - (9150, 3), - (9151, 3), - (9152, 2), - (9153, 9), - (9154, 1), - (9155, 2), + (9149, 1), + (9150, 2), + (9152, 3), + (9153, 6), + (9154, 3), + (9155, 5), (9156, 1), - (9157, 1), - (9181, 1), - (9183, 4), + (9159, 1), + (9182, 1), (9184, 7), - (9185, 1), - (9186, 1), + (9186, 2), (9187, 1), - (9189, 2), - (9190, 1), - (9191, 1), - (9192, 4), - (9193, 3), + (9189, 1), + (9191, 2), + (9192, 2), + (9193, 1), (9194, 1), - (9195, 2), - (9196, 1), - (9197, 2), - (9198, 1), (9204, 6), (9219, 1), - (9221, 3), - (9222, 2), - (9223, 3), + (9222, 4), + (9223, 1), (9224, 1), - (9227, 2), - (9228, 1), + (9227, 3), (9229, 2), (9230, 3), - (9232, 1), - (9233, 2), + (9231, 1), + (9232, 2), + (9233, 3), + (9234, 1), (9235, 1), - (9259, 1), - (9260, 1), + (9236, 1), + (9260, 2), (9261, 1), - (9262, 2), - (9264, 2), + (9262, 3), + (9263, 1), + (9264, 1), (9265, 1), - (9268, 1), - (9269, 2), + (9266, 1), + (9269, 3), (9270, 2), - (9271, 1), - (9272, 6), - (9273, 2), - (9274, 1), - (9298, 1), - (9299, 2), - (9301, 2), - (9302, 3), - (9303, 2), - (9305, 1), + (9271, 4), + (9272, 2), + (9274, 2), + (9276, 1), + (9299, 1), + (9301, 3), + (9302, 1), (9306, 1), - (9307, 3), + (9307, 1), (9308, 1), - (9309, 1), - (9310, 3), - (9311, 2), - (9312, 3), - (9313, 2), + (9310, 2), + (9311, 1), + (9313, 1), + (9314, 1), (9334, 3), (9339, 1), (9340, 2), + (9341, 1), (9342, 1), - (9343, 1), - (9346, 2), - (9347, 4), - (9348, 3), - (9350, 2), - (9351, 4), + (9344, 2), + (9346, 1), + (9347, 1), + (9348, 4), + (9349, 2), + (9351, 3), (9352, 2), - (9353, 1), - (9376, 1), - (9377, 2), - (9378, 2), - (9379, 3), - (9380, 1), - (9381, 2), - (9382, 3), - (9384, 3), + (9377, 4), + (9378, 1), + (9379, 2), + (9380, 2), + (9384, 1), (9386, 3), - (9387, 2), - (9388, 3), + (9387, 6), + (9388, 2), (9389, 8), - (9390, 1), - (9391, 1), - (9415, 2), - (9419, 1), - (9420, 3), - (9421, 2), - (9422, 2), - (9425, 3), - (9426, 6), - (9427, 3), - (9428, 1), - (9429, 3), - (9430, 1), - (9431, 1), - (9455, 2), + (9392, 2), + (9414, 1), + (9415, 1), + (9416, 1), + (9417, 1), + (9418, 3), + (9424, 1), + (9425, 1), + (9426, 3), + (9427, 1), + (9429, 1), + (9430, 3), (9456, 1), (9457, 2), - (9458, 1), + (9458, 4), (9459, 1), - (9460, 1), - (9461, 1), - (9462, 2), - (9463, 3), - (9464, 2), - (9465, 3), + (9460, 2), + (9461, 3), + (9463, 1), + (9464, 1), (9466, 2), - (9467, 2), - (9468, 4), - (9474, 1), - (9491, 1), - (9494, 3), - (9496, 1), - (9497, 2), - (9498, 1), - (9501, 2), - (9503, 2), - (9504, 3), + (9469, 7), + (9470, 1), + (9471, 1), + (9494, 1), + (9495, 1), + (9496, 3), + (9497, 3), + (9498, 2), + (9500, 1), + (9501, 1), + (9503, 1), + (9504, 2), (9505, 3), - (9506, 10), - (9507, 3), - (9508, 4), - (9509, 2), + (9506, 6), + (9508, 2), + (9509, 1), (9510, 1), - (9533, 2), - (9534, 6), - (9535, 1), - (9536, 1), - (9537, 1), + (9531, 1), + (9533, 1), + (9534, 5), + (9535, 2), + (9537, 2), (9538, 1), - (9539, 1), - (9541, 1), - (9542, 1), - (9543, 1), - (9544, 2), - (9545, 3), - (9546, 3), + (9539, 2), + (9540, 3), + (9542, 3), + (9543, 2), + (9544, 3), + (9546, 1), (9547, 2), (9562, 6), - (9570, 1), - (9571, 1), - (9572, 2), + (9569, 1), (9573, 1), (9574, 1), - (9576, 4), - (9577, 1), - (9581, 3), - (9582, 8), - (9584, 2), - (9585, 1), + (9579, 1), + (9581, 1), + (9582, 2), + (9583, 3), + (9584, 1), + (9585, 3), (9586, 3), - (9609, 1), - (9611, 1), - (9612, 5), + (9588, 1), + (9608, 1), + (9610, 2), (9613, 1), - (9614, 1), - (9616, 2), + (9614, 2), + (9615, 1), (9618, 2), (9619, 1), + (9620, 1), (9621, 3), (9622, 1), - (9623, 2), - (9624, 3), + (9623, 3), (9625, 4), - (9626, 1), - (9628, 1), - (9650, 2), + (9649, 1), + (9651, 2), + (9652, 1), (9653, 2), - (9656, 1), - (9657, 2), + (9654, 1), + (9656, 2), + (9657, 1), (9658, 1), (9659, 2), - (9660, 1), - (9661, 4), - (9662, 2), - (9666, 2), - (9668, 1), + (9661, 2), + (9662, 1), + (9663, 2), + (9664, 2), + (9665, 2), (9689, 1), (9690, 1), - (9693, 1), - (9694, 2), - (9695, 1), - (9696, 1), - (9698, 2), - (9699, 3), + (9691, 1), + (9694, 1), + (9695, 3), + (9696, 2), + (9697, 2), + (9698, 4), + (9699, 2), (9700, 1), - (9701, 4), - (9703, 1), + (9701, 5), + (9702, 2), + (9703, 3), + (9704, 1), (9705, 1), - (9727, 1), - (9729, 1), + (9730, 1), (9731, 1), - (9732, 1), - (9733, 1), - (9734, 3), + (9733, 3), (9735, 1), (9736, 1), - (9737, 1), (9738, 1), (9739, 1), - (9740, 3), - (9742, 1), - (9743, 2), - (9744, 1), - (9767, 1), - (9769, 2), - (9770, 1), - (9771, 3), - (9772, 3), - (9773, 2), - (9776, 3), - (9777, 5), - (9778, 1), - (9779, 3), - (9780, 1), + (9740, 1), + (9741, 1), + (9742, 2), + (9766, 1), + (9768, 1), + (9770, 2), + (9771, 1), + (9773, 1), + (9777, 2), + (9778, 2), + (9779, 5), + (9780, 3), + (9782, 1), (9783, 1), - (9808, 1), + (9807, 2), (9809, 1), - (9811, 2), - (9814, 1), - (9815, 4), - (9816, 3), - (9817, 2), + (9810, 2), + (9811, 1), + (9813, 2), + (9815, 3), + (9816, 1), (9818, 2), - (9819, 1), - (9820, 2), - (9821, 2), + (9819, 2), + (9820, 1), (9824, 1), (9840, 3), - (9847, 3), + (9845, 2), + (9846, 2), + (9847, 1), + (9848, 2), (9849, 8), - (9852, 1), + (9850, 1), + (9851, 1), + (9852, 2), (9853, 1), - (9854, 4), - (9855, 5), - (9856, 1), - (9857, 3), + (9854, 1), + (9855, 1), (9858, 2), - (9859, 1), - (9884, 5), - (9886, 2), - (9888, 1), - (9889, 1), - (9891, 2), - (9892, 1), - (9893, 1), - (9895, 2), - (9896, 3), - (9897, 4), - (9903, 1), - (9923, 2), - (9924, 2), - (9925, 3), + (9884, 1), + (9885, 1), + (9887, 3), + (9892, 2), + (9895, 5), + (9896, 1), + (9897, 3), + (9898, 2), + (9899, 1), + (9923, 1), + (9925, 1), (9927, 1), - (9928, 2), - (9929, 1), - (9932, 2), + (9928, 3), + (9932, 1), (9933, 1), - (9935, 4), - (9936, 2), - (9937, 3), - (9939, 1), - (9940, 1), - (9964, 4), - (9966, 1), - (9967, 1), - (9970, 1), - (9971, 1), - (9972, 1), - (9973, 2), - (9974, 5), - (9975, 1), - (9976, 2), - (9977, 3), + (9935, 2), + (9937, 1), + (9938, 1), + (9961, 1), + (9963, 1), + (9964, 2), + (9965, 3), + (9969, 2), + (9970, 3), + (9973, 1), + (9974, 7), + (9975, 2), + (9976, 3), + (9979, 1), + (9981, 1), (9996, 1), - (9999, 1), - (10002, 1), + (10000, 1), + (10001, 2), + (10002, 2), (10003, 2), (10004, 2), - (10005, 2), + (10005, 1), + (10007, 1), (10011, 4), - (10012, 2), - (10013, 2), + (10012, 1), + (10013, 1), + (10014, 1), (10015, 1), (10016, 1), - (10040, 1), - (10042, 1), - (10043, 4), - (10044, 3), + (10017, 1), + (10041, 2), + (10042, 3), + (10044, 1), (10048, 1), (10049, 1), - (10050, 1), + (10050, 2), (10051, 1), (10052, 2), (10053, 2), (10054, 2), - (10081, 2), - (10082, 1), - (10084, 1), + (10055, 1), + (10080, 1), + (10081, 1), + (10083, 1), (10085, 1), (10086, 1), - (10087, 2), - (10089, 2), - (10090, 2), - (10092, 2), - (10093, 2), + (10088, 1), + (10089, 1), + (10091, 1), + (10093, 1), (10094, 1), (10096, 6), - (10117, 5), - (10118, 3), - (10119, 2), - (10121, 1), - (10122, 2), - (10123, 5), - (10124, 3), - (10125, 1), - (10126, 3), + (10117, 6), + (10120, 1), + (10121, 2), + (10123, 4), + (10126, 2), (10127, 1), - (10129, 4), - (10130, 2), - (10131, 1), - (10132, 2), - (10134, 1), + (10128, 1), + (10129, 1), + (10131, 2), (10139, 6), - (10155, 1), - (10157, 2), + (10156, 1), + (10157, 1), (10158, 2), - (10161, 2), - (10163, 1), - (10165, 2), - (10168, 1), - (10169, 1), - (10170, 2), - (10171, 2), - (10172, 1), - (10197, 1), + (10159, 2), + (10160, 1), + (10161, 1), + (10165, 1), + (10166, 2), + (10167, 2), + (10170, 1), + (10171, 1), + (10195, 2), (10198, 1), (10202, 1), - (10205, 1), - (10206, 1), - (10207, 1), - (10208, 2), - (10210, 2), + (10205, 2), + (10206, 2), + (10208, 1), + (10209, 1), (10211, 1), - (10232, 1), - (10234, 1), - (10236, 1), - (10237, 1), + (10235, 1), + (10236, 2), (10238, 1), (10239, 2), - (10240, 1), (10242, 1), - (10243, 2), - (10244, 2), - (10245, 2), - (10246, 4), - (10247, 3), - (10248, 1), + (10245, 3), + (10247, 1), (10251, 1), (10259, 1), - (10278, 1), - (10279, 1), - (10280, 2), + (10280, 1), (10282, 1), (10283, 1), - (10285, 3), + (10285, 1), (10286, 1), - (10287, 3), - (10289, 1), - (10312, 1), - (10313, 1), - (10314, 1), - (10315, 1), - (10317, 3), - (10319, 1), + (10287, 1), + (10289, 3), + (10314, 2), + (10315, 2), + (10316, 1), + (10317, 1), + (10318, 1), + (10320, 1), + (10321, 1), (10322, 2), - (10323, 1), + (10323, 2), (10324, 1), - (10325, 2), - (10326, 1), - (10327, 1), - (10329, 2), - (10350, 1), - (10353, 1), - (10355, 3), - (10356, 1), + (10327, 2), (10358, 1), + (10359, 1), (10360, 1), - (10362, 1), + (10361, 1), + (10362, 3), (10363, 1), - (10364, 2), - (10365, 1), - (10366, 4), + (10364, 1), + (10365, 2), + (10367, 1), (10391, 1), - (10393, 1), - (10394, 2), - (10395, 3), - (10400, 4), - (10404, 3), + (10392, 2), + (10394, 3), + (10396, 2), + (10397, 1), + (10400, 2), + (10401, 1), + (10404, 1), (10405, 1), - (10407, 1), (10416, 6), - (10430, 2), - (10431, 1), - (10432, 1), - (10434, 3), - (10435, 1), - (10437, 1), - (10438, 2), + (10429, 1), + (10432, 2), + (10434, 1), + (10435, 2), + (10438, 3), (10439, 2), - (10440, 2), (10441, 1), - (10442, 1), - (10445, 2), - (10446, 2), - (10469, 2), - (10470, 1), + (10442, 2), + (10443, 1), + (10468, 1), (10471, 1), - (10472, 1), - (10473, 2), - (10474, 1), - (10476, 1), - (10477, 1), - (10481, 1), + (10473, 1), + (10476, 2), + (10477, 3), + (10478, 1), + (10480, 3), + (10481, 3), (10482, 1), - (10483, 3), + (10483, 2), (10485, 1), (10487, 1), (10488, 1), (10510, 1), - (10511, 2), - (10512, 1), - (10514, 1), - (10515, 1), - (10518, 2), + (10511, 1), + (10512, 3), + (10516, 2), (10519, 1), - (10520, 1), - (10522, 2), - (10548, 2), - (10549, 2), - (10550, 3), - (10553, 1), - (10554, 1), + (10520, 2), + (10548, 1), + (10549, 1), + (10550, 4), + (10552, 1), + (10553, 2), (10555, 2), (10556, 1), - (10557, 3), - (10559, 1), - (10563, 1), - (10586, 1), + (10557, 2), + (10559, 3), + (10561, 2), (10587, 2), - (10589, 3), - (10590, 2), - (10591, 1), + (10589, 1), + (10590, 1), (10592, 1), (10593, 2), (10594, 2), + (10595, 3), + (10596, 1), (10597, 1), - (10598, 2), - (10599, 2), - (10602, 1), - (10603, 1), - (10604, 2), - (10625, 2), - (10626, 2), - (10627, 3), - (10629, 6), - (10630, 2), + (10598, 1), + (10600, 1), + (10601, 2), + (10604, 1), + (10622, 1), + (10624, 2), + (10626, 3), + (10627, 2), + (10629, 7), (10631, 1), - (10636, 1), + (10633, 2), + (10636, 3), + (10637, 1), (10638, 1), - (10639, 1), - (10640, 1), - (10662, 6), + (10662, 11), (10664, 2), + (10665, 1), (10667, 1), - (10672, 1), - (10673, 2), - (10674, 1), + (10668, 1), + (10671, 1), + (10673, 1), (10675, 1), - (10679, 1), - (10698, 77), - (10703, 2), - (10704, 1), - (10705, 1), + (10678, 1), + (10680, 1), + (10698, 72), + (10703, 1), + (10705, 2), (10707, 5), (10708, 1), - (10711, 1), + (10710, 1), + (10711, 2), (10712, 1), - (10714, 1), - (10716, 3), - (10717, 1), - (10718, 1), - (10720, 1), - (10742, 2), - (10744, 1), - (10746, 1), - (10747, 1), - (10752, 1), - (10753, 1), + (10713, 3), + (10714, 2), + (10742, 1), + (10752, 3), + (10753, 4), (10754, 3), - (10755, 1), - (10757, 1), + (10756, 1), + (10781, 1), + (10785, 1), + (10786, 1), (10788, 1), - (10789, 1), - (10790, 1), - (10791, 6), - (10793, 2), + (10790, 2), + (10791, 8), + (10792, 3), (10794, 2), (10795, 2), - (10798, 1), - (10818, 1), - (10821, 1), + (10820, 1), (10826, 1), (10830, 1), + (10831, 1), (10832, 1), + (10833, 3), (10834, 1), - (10835, 1), - (10837, 1), - (10857, 1), - (10861, 2), - (10862, 1), - (10864, 1), + (10861, 1), (10865, 1), - (10868, 4), - (10869, 1), - (10870, 2), - (10871, 4), - (10872, 1), - (10875, 1), - (10898, 3), - (10899, 1), - (10903, 1), - (10904, 1), - (10905, 1), - (10907, 4), - (10908, 1), - (10909, 2), - (10911, 2), - (10912, 1), - (10913, 1), - (10916, 1), + (10867, 2), + (10868, 1), + (10869, 4), + (10872, 2), + (10873, 2), + (10902, 1), + (10904, 3), + (10906, 1), + (10907, 3), + (10911, 1), + (10915, 2), (10931, 5), (10933, 1), - (10937, 1), (10938, 1), - (10939, 1), - (10943, 1), + (10939, 2), + (10941, 1), + (10942, 1), (10945, 1), - (10946, 3), - (10947, 1), + (10946, 1), + (10947, 2), (10948, 1), - (10949, 3), - (10952, 1), - (10977, 1), + (10949, 2), + (10950, 5), + (10951, 1), (10978, 1), (10979, 1), - (10980, 1), (10981, 1), - (10982, 1), - (10984, 1), (10985, 2), (10986, 1), - (10987, 1), - (10988, 1), - (10991, 2), - (10992, 1), + (10987, 2), + (11012, 1), (11014, 1), - (11016, 1), - (11018, 2), + (11018, 1), (11019, 1), (11020, 4), + (11021, 1), (11022, 1), - (11023, 1), (11025, 1), (11026, 1), - (11028, 4), + (11027, 1), + (11028, 2), (11029, 2), - (11052, 1), - (11056, 1), - (11057, 1), - (11062, 3), + (11059, 2), + (11060, 3), + (11061, 1), + (11062, 1), (11063, 2), - (11064, 2), - (11065, 1), - (11067, 1), - (11069, 1), - (11070, 1), + (11064, 1), + (11066, 1), + (11067, 2), + (11068, 1), (11084, 1), - (11093, 1), - (11103, 1), - (11104, 2), - (11105, 3), - (11106, 2), + (11098, 1), + (11099, 3), + (11100, 1), + (11101, 1), + (11102, 2), + (11105, 1), + (11106, 1), (11107, 1), (11132, 1), (11133, 1), - (11134, 1), - (11135, 3), - (11136, 1), + (11135, 1), + (11136, 2), (11139, 1), + (11140, 1), (11141, 1), - (11144, 2), - (11146, 1), - (11147, 1), - (11148, 1), - (11171, 1), - (11173, 1), + (11144, 4), + (11145, 2), + (11172, 1), (11174, 1), - (11176, 1), - (11180, 1), + (11175, 2), + (11176, 2), + (11177, 2), + (11178, 1), + (11180, 3), + (11181, 5), + (11182, 1), (11183, 1), - (11186, 1), - (11210, 1), - (11212, 1), + (11184, 3), + (11209, 1), + (11216, 1), + (11217, 1), + (11218, 2), (11219, 1), - (11220, 2), - (11222, 3), - (11223, 2), - (11224, 1), + (11220, 1), + (11222, 1), (11225, 1), - (11226, 1), + (11230, 1), (11231, 1), (11249, 1), (11250, 1), - (11253, 1), - (11254, 5), - (11257, 1), - (11258, 3), - (11259, 3), - (11261, 1), - (11264, 2), - (11287, 1), - (11289, 1), - (11290, 2), - (11291, 1), + (11254, 6), + (11255, 3), + (11258, 1), + (11259, 2), + (11260, 4), + (11261, 3), + (11262, 1), + (11292, 1), (11293, 1), - (11296, 1), - (11300, 1), + (11294, 2), + (11297, 3), + (11298, 1), (11301, 1), - (11302, 1), - (11326, 1), (11328, 5), - (11329, 1), - (11335, 1), - (11336, 2), - (11337, 1), - (11338, 1), + (11331, 1), + (11332, 1), + (11334, 3), + (11336, 1), + (11337, 3), + (11338, 2), (11339, 1), - (11340, 1), - (11366, 3), - (11368, 1), + (11340, 2), + (11341, 1), + (11342, 1), + (11366, 2), + (11367, 1), (11369, 2), - (11370, 1), - (11374, 2), - (11375, 1), - (11378, 2), + (11372, 1), + (11373, 1), + (11375, 2), + (11377, 1), (11379, 1), - (11404, 2), - (11407, 1), - (11409, 2), - (11410, 2), - (11411, 1), + (11380, 1), + (11406, 1), + (11410, 1), + (11412, 1), + (11413, 2), (11414, 1), - (11415, 3), (11417, 1), + (11418, 2), (11422, 1), - (11443, 1), - (11446, 1), + (11444, 1), + (11445, 1), + (11447, 1), + (11448, 1), (11450, 1), (11454, 1), - (11455, 2), + (11456, 1), + (11457, 1), + (11459, 1), (11481, 6), - (11485, 1), (11487, 1), - (11488, 1), - (11492, 1), - (11493, 1), - (11494, 1), + (11490, 1), + (11492, 3), + (11493, 2), + (11494, 2), (11495, 1), - (11498, 3), - (11499, 1), - (11521, 1), - (11522, 1), - (11524, 2), + (11497, 1), + (11524, 1), (11525, 2), - (11526, 1), - (11528, 1), - (11532, 1), - (11564, 1), - (11565, 2), - (11572, 1), - (11576, 1), - (11577, 1), + (11530, 2), + (11533, 2), + (11536, 1), + (11561, 1), + (11565, 1), + (11569, 1), + (11572, 3), + (11574, 1), + (11575, 3), (11599, 1), - (11601, 1), - (11602, 2), - (11603, 1), + (11601, 2), + (11606, 1), (11607, 1), (11609, 1), + (11611, 2), (11614, 1), - (11616, 1), + (11615, 2), (11631, 1), + (11637, 1), + (11639, 1), (11640, 2), - (11641, 1), - (11642, 1), - (11643, 4), - (11651, 3), - (11653, 2), - (11654, 1), + (11642, 2), + (11645, 1), + (11647, 2), + (11648, 2), + (11649, 1), + (11651, 2), + (11652, 2), + (11653, 1), (11655, 1), - (11679, 2), + (11681, 1), (11682, 5), + (11685, 1), (11686, 1), (11687, 1), - (11689, 1), - (11690, 3), - (11691, 1), - (11693, 1), - (11717, 2), - (11719, 3), - (11720, 4), + (11688, 2), + (11690, 1), + (11720, 3), (11721, 6), - (11726, 1), - (11727, 1), - (11728, 1), + (11723, 1), + (11724, 1), + (11725, 1), + (11726, 2), + (11729, 2), + (11730, 2), + (11731, 1), + (11732, 1), (11750, 6), (11755, 3), - (11756, 2), - (11757, 2), - (11759, 1), + (11757, 1), + (11761, 2), (11762, 1), - (11763, 1), (11764, 1), - (11765, 3), - (11766, 1), - (11768, 1), - (11769, 1), - (11770, 2), - (11796, 2), - (11797, 2), - (11798, 1), - (11801, 1), + (11766, 3), + (11767, 1), + (11803, 2), (11804, 1), - (11806, 1), - (11807, 3), + (11806, 2), + (11807, 2), (11808, 1), - (11810, 1), - (11811, 1), - (11813, 1), - (11837, 2), + (11833, 1), + (11836, 1), + (11838, 1), (11841, 2), - (11843, 2), - (11844, 1), - (11845, 1), - (11846, 1), - (11871, 1), - (11876, 2), + (11842, 4), + (11845, 3), + (11848, 2), + (11849, 1), + (11870, 1), + (11875, 2), + (11876, 1), (11877, 1), - (11878, 1), - (11880, 1), + (11878, 2), + (11879, 1), (11881, 2), - (11882, 4), - (11883, 5), - (11884, 3), - (11885, 1), - (11888, 1), - (11912, 2), - (11913, 1), - (11923, 1), - (11926, 1), - (11927, 1), - (11928, 1), + (11882, 2), + (11883, 7), + (11884, 1), + (11885, 3), + (11886, 2), + (11887, 2), + (11912, 1), + (11914, 1), + (11916, 1), + (11917, 1), + (11924, 1), + (11925, 1), + (11950, 1), (11951, 1), - (11953, 2), - (11955, 1), - (11956, 2), + (11953, 1), (11959, 2), + (11960, 3), (11961, 1), - (11962, 1), + (11963, 1), (11964, 1), - (11966, 2), + (11966, 1), (11990, 1), - (11992, 3), - (12003, 2), - (12028, 1), - (12031, 1), + (11993, 1), + (11997, 1), + (11998, 2), + (11999, 2), + (12000, 1), + (12001, 1), (12033, 1), - (12035, 1), - (12037, 1), - (12038, 1), + (12037, 2), + (12038, 2), (12039, 2), (12040, 1), - (12041, 1), - (12043, 2), - (12072, 4), - (12077, 2), - (12078, 3), - (12079, 2), - (12080, 1), + (12041, 2), + (12043, 3), + (12044, 1), + (12068, 1), + (12072, 3), + (12074, 2), + (12075, 1), + (12076, 1), + (12077, 4), + (12078, 4), + (12079, 6), + (12080, 2), (12108, 2), - (12109, 2), - (12112, 1), (12114, 1), (12115, 2), - (12116, 1), - (12117, 2), - (12118, 1), - (12123, 2), - (12145, 1), - (12146, 1), - (12147, 3), + (12116, 3), + (12117, 1), + (12118, 2), + (12119, 1), + (12120, 2), (12148, 1), - (12151, 1), + (12149, 1), + (12152, 1), + (12153, 2), + (12154, 1), + (12155, 1), (12156, 1), + (12157, 2), (12158, 2), - (12183, 1), - (12190, 1), - (12192, 1), - (12194, 2), - (12195, 1), - (12196, 2), + (12159, 1), + (12191, 1), + (12193, 1), + (12194, 1), + (12195, 2), + (12196, 1), (12197, 3), - (12198, 3), - (12201, 1), - (12224, 1), + (12198, 1), + (12199, 2), + (12200, 1), (12225, 1), - (12226, 1), (12230, 1), - (12231, 1), - (12234, 1), + (12233, 1), + (12234, 3), + (12235, 3), (12236, 1), - (12237, 3), - (12263, 1), - (12265, 1), - (12266, 1), - (12267, 1), + (12237, 4), + (12264, 1), (12269, 1), - (12272, 1), - (12273, 2), + (12270, 1), + (12271, 3), + (12272, 2), + (12273, 1), (12274, 2), - (12276, 2), - (12277, 1), - (12279, 1), - (12280, 1), - (12300, 1), + (12276, 1), + (12277, 4), + (12278, 1), (12303, 1), - (12305, 1), + (12304, 1), + (12305, 2), (12307, 2), - (12309, 1), + (12308, 1), + (12309, 4), (12310, 2), - (12311, 1), - (12315, 2), - (12321, 1), - (12341, 1), - (12344, 2), - (12350, 2), - (12351, 1), - (12352, 1), - (12353, 1), - (12383, 1), - (12389, 2), + (12312, 1), + (12313, 1), + (12314, 3), + (12315, 1), + (12317, 1), + (12344, 1), + (12350, 6), + (12351, 2), + (12352, 3), + (12353, 2), + (12354, 1), + (12385, 1), + (12387, 1), + (12388, 1), + (12389, 1), (12390, 1), (12391, 1), - (12392, 4), - (12395, 1), + (12392, 1), (12421, 3), - (12423, 1), + (12425, 1), + (12427, 2), (12428, 1), (12429, 1), - (12430, 1), - (12457, 1), - (12461, 1), - (12463, 1), - (12468, 1), - (12471, 1), - (12473, 1), + (12430, 2), + (12431, 2), + (12432, 3), + (12462, 1), + (12464, 1), + (12466, 1), + (12468, 3), + (12469, 2), + (12470, 4), + (12471, 3), + (12472, 1), (12498, 5), - (12499, 2), - (12502, 1), - (12503, 1), + (12503, 2), (12505, 1), - (12506, 1), - (12508, 2), + (12507, 1), + (12508, 3), (12509, 1), (12510, 1), (12511, 1), - (12513, 1), - (12535, 1), - (12536, 1), - (12537, 1), - (12538, 1), (12539, 1), - (12540, 1), - (12542, 1), - (12545, 1), + (12540, 2), + (12542, 2), + (12543, 1), + (12544, 2), + (12546, 1), (12547, 2), - (12548, 1), + (12548, 3), + (12549, 1), (12550, 1), (12577, 1), + (12578, 1), (12581, 1), - (12583, 1), - (12585, 1), - (12586, 3), - (12618, 1), - (12624, 1), + (12582, 2), + (12584, 1), + (12585, 2), + (12586, 1), + (12587, 1), + (12620, 1), + (12621, 1), + (12625, 2), (12626, 1), - (12655, 1), + (12627, 2), + (12628, 2), + (12629, 1), + (12630, 1), + (12653, 1), + (12656, 1), (12657, 3), - (12658, 1), - (12663, 1), - (12664, 3), - (12665, 2), - (12667, 1), + (12658, 2), + (12659, 1), + (12661, 3), + (12662, 2), + (12663, 2), + (12664, 1), + (12666, 1), + (12668, 1), (12682, 1), - (12693, 1), - (12697, 1), + (12694, 1), + (12696, 2), + (12698, 1), (12699, 1), - (12701, 1), (12702, 1), - (12705, 2), - (12706, 1), - (12730, 1), - (12732, 2), - (12733, 2), - (12737, 1), - (12739, 1), - (12740, 1), - (12742, 3), - (12771, 1), + (12703, 2), + (12704, 1), + (12705, 1), + (12706, 2), + (12732, 1), + (12741, 1), + (12742, 4), + (12743, 1), + (12744, 1), (12773, 1), - (12780, 1), - (12781, 3), + (12774, 1), + (12778, 2), + (12780, 3), + (12781, 1), (12782, 1), - (12809, 1), - (12811, 1), - (12812, 1), - (12819, 1), - (12821, 1), - (12822, 1), - (12824, 1), - (12826, 1), - (12848, 1), - (12851, 2), - (12853, 1), - (12860, 3), + (12785, 1), + (12813, 1), + (12816, 1), + (12817, 1), + (12819, 3), + (12821, 2), + (12823, 2), + (12824, 2), + (12825, 1), + (12854, 1), + (12856, 2), + (12857, 1), + (12858, 1), + (12859, 5), + (12860, 2), (12861, 1), - (12862, 1), - (12863, 1), - (12889, 1), (12890, 1), - (12896, 1), + (12894, 3), + (12897, 3), (12899, 1), - (12928, 1), - (12929, 2), - (12930, 1), + (12900, 1), + (12901, 1), + (12903, 1), + (12927, 1), + (12928, 2), + (12933, 1), + (12934, 2), + (12935, 1), (12936, 1), - (12937, 3), - (12938, 1), + (12938, 2), + (12939, 1), (12941, 1), (12964, 1), - (12969, 1), - (12971, 1), + (12966, 1), + (12972, 1), (12973, 1), - (12976, 1), - (12977, 2), - (13005, 1), + (12974, 1), + (12975, 2), + (12976, 2), + (12977, 1), + (12979, 1), + (12980, 1), + (12982, 1), (13006, 1), - (13008, 1), - (13010, 1), - (13013, 2), - (13015, 2), - (13018, 1), - (13046, 1), - (13047, 1), - (13053, 2), - (13055, 2), - (13081, 1), - (13083, 1), - (13085, 4), - (13086, 1), - (13091, 2), - (13092, 2), + (13013, 3), + (13014, 2), + (13016, 1), + (13020, 1), + (13050, 2), + (13052, 1), + (13053, 1), + (13054, 1), + (13055, 3), + (13058, 1), + (13085, 1), + (13088, 1), + (13090, 2), + (13091, 1), (13094, 2), (13095, 1), (13096, 1), - (13097, 1), - (13123, 2), - (13127, 1), + (13123, 1), + (13124, 1), + (13128, 1), (13130, 1), (13131, 1), - (13132, 1), + (13132, 2), + (13133, 1), (13134, 1), (13136, 1), - (13159, 1), - (13161, 2), (13162, 1), - (13167, 2), - (13168, 1), - (13172, 1), - (13174, 1), - (13175, 1), - (13176, 1), + (13168, 3), + (13169, 1), + (13171, 2), + (13172, 2), (13206, 1), - (13207, 1), + (13207, 2), (13209, 2), (13212, 1), - (13213, 2), - (13239, 2), - (13242, 1), - (13247, 1), - (13249, 2), - (13252, 1), - (13279, 1), - (13280, 2), + (13239, 1), + (13240, 1), + (13243, 1), + (13245, 1), + (13246, 1), + (13248, 2), + (13250, 1), + (13251, 1), + (13277, 1), (13282, 5), (13284, 1), + (13285, 1), (13286, 1), - (13288, 1), - (13289, 1), - (13290, 1), + (13287, 3), + (13288, 2), (13291, 1), - (13317, 1), - (13318, 1), - (13319, 1), - (13320, 1), + (13321, 1), + (13324, 2), (13325, 1), - (13326, 1), - (13328, 2), - (13330, 2), + (13326, 3), + (13328, 1), (13354, 2), - (13356, 6), - (13360, 2), - (13362, 1), - (13363, 2), - (13364, 3), - (13367, 2), + (13356, 5), + (13357, 1), + (13359, 1), + (13360, 1), + (13363, 1), + (13364, 2), + (13366, 1), (13368, 3), + (13369, 1), (13370, 1), - (13393, 1), - (13397, 2), - (13406, 1), + (13397, 1), + (13399, 1), + (13401, 3), + (13403, 1), + (13404, 1), + (13406, 2), (13408, 1), - (13435, 1), - (13436, 1), - (13438, 1), - (13440, 2), - (13442, 1), + (13409, 1), + (13410, 1), + (13411, 2), + (13434, 1), + (13436, 2), + (13439, 2), + (13440, 1), + (13441, 1), + (13442, 2), (13443, 1), - (13444, 1), (13445, 1), - (13449, 1), - (13473, 2), + (13447, 1), (13474, 1), (13475, 1), - (13479, 2), - (13481, 2), - (13482, 1), + (13479, 3), + (13481, 1), + (13482, 3), (13484, 1), - (13485, 1), - (13491, 1), - (13511, 1), - (13520, 1), - (13521, 2), + (13486, 1), + (13487, 1), + (13514, 1), + (13517, 1), + (13520, 2), + (13521, 1), (13522, 1), - (13527, 1), - (13550, 1), - (13551, 1), - (13552, 3), + (13523, 1), + (13524, 1), + (13525, 1), + (13550, 2), (13555, 1), - (13557, 1), + (13556, 1), + (13557, 2), (13559, 2), - (13562, 2), - (13564, 1), - (13590, 1), - (13592, 1), + (13560, 2), + (13562, 1), + (13591, 1), (13596, 1), - (13600, 2), - (13602, 1), - (13603, 1), - (13630, 1), + (13597, 1), + (13598, 1), + (13601, 2), + (13631, 1), (13633, 1), - (13634, 1), - (13637, 1), - (13640, 1), - (13643, 1), - (13668, 1), - (13669, 2), - (13670, 2), - (13674, 1), - (13676, 1), + (13638, 2), + (13642, 1), (13677, 1), - (13678, 4), - (13679, 1), - (13680, 1), + (13712, 1), (13713, 1), (13714, 1), - (13716, 6), - (13717, 2), - (13745, 1), + (13716, 1), + (13717, 1), + (13721, 1), (13752, 2), (13753, 1), - (13754, 1), (13755, 1), (13757, 1), (13758, 1), - (13791, 1), - (13795, 1), - (13796, 2), - (13823, 2), + (13761, 1), + (13787, 1), + (13790, 1), + (13792, 1), + (13794, 1), + (13799, 1), + (13823, 1), + (13825, 2), (13831, 1), - (13834, 1), - (13836, 1), + (13832, 3), (13837, 1), - (13862, 1), - (13863, 1), - (13864, 1), - (13867, 1), - (13875, 1), - (13876, 1), + (13868, 1), + (13872, 2), + (13874, 2), + (13876, 2), (13877, 1), - (13878, 1), + (13879, 1), (13906, 1), - (13910, 2), - (13911, 1), - (13912, 2), + (13911, 2), + (13912, 1), + (13913, 1), (13914, 2), - (13942, 1), - (13947, 2), - (13948, 2), - (13950, 3), - (13951, 1), - (13952, 1), - (13953, 1), - (13954, 1), - (13980, 1), + (13917, 1), + (13946, 1), + (13947, 3), + (13950, 1), + (13953, 2), + (13956, 1), (13985, 1), - (13987, 1), - (13988, 1), - (13989, 1), - (14016, 1), - (14018, 7), - (14020, 2), - (14021, 1), - (14022, 1), - (14023, 1), + (13987, 3), + (13989, 3), + (13992, 1), + (13993, 1), + (13996, 1), + (14018, 6), (14024, 1), - (14026, 1), - (14027, 1), - (14030, 1), - (14061, 1), - (14063, 6), - (14064, 1), - (14068, 1), - (14074, 1), - (14098, 1), - (14099, 2), + (14025, 1), + (14027, 2), + (14029, 2), + (14031, 1), + (14033, 2), + (14034, 1), + (14056, 1), + (14058, 1), + (14063, 5), + (14064, 2), + (14066, 1), + (14067, 1), (14102, 5), (14104, 2), - (14108, 1), - (14136, 1), - (14140, 1), + (14106, 1), + (14107, 2), + (14110, 1), + (14111, 1), (14143, 1), - (14145, 1), - (14146, 1), + (14144, 1), (14148, 1), - (14174, 2), - (14176, 1), - (14177, 1), - (14186, 1), - (14188, 1), - (14189, 1), - (14190, 1), + (14180, 2), + (14181, 1), + (14183, 1), + (14185, 2), (14213, 1), (14216, 1), - (14225, 1), - (14226, 1), - (14253, 1), + (14218, 1), + (14221, 1), + (14222, 1), + (14223, 1), (14257, 1), - (14258, 1), - (14261, 2), - (14264, 1), - (14265, 1), + (14264, 2), (14266, 1), - (14292, 1), - (14293, 1), - (14294, 1), - (14303, 1), - (14328, 1), + (14297, 3), + (14298, 1), + (14304, 1), (14336, 1), (14337, 1), + (14339, 1), (14340, 1), - (14341, 1), + (14341, 2), (14342, 1), - (14370, 1), - (14371, 1), (14373, 5), - (14375, 1), - (14378, 1), - (14382, 2), - (14409, 1), - (14410, 1), - (14412, 1), + (14376, 1), + (14379, 1), + (14381, 1), + (14414, 2), + (14416, 1), (14417, 1), - (14420, 4), - (14421, 1), - (14424, 1), + (14418, 1), + (14419, 1), + (14420, 1), + (14447, 1), (14448, 5), - (14449, 2), + (14449, 1), + (14453, 2), (14455, 1), - (14459, 1), - (14460, 1), - (14491, 1), + (14456, 1), + (14458, 2), + (14459, 2), + (14488, 1), (14492, 1), - (14494, 1), + (14493, 1), (14495, 1), + (14496, 2), + (14497, 2), + (14498, 1), (14500, 1), - (14522, 1), (14530, 2), - (14532, 3), + (14532, 2), (14534, 1), - (14537, 2), - (14563, 1), - (14565, 1), - (14567, 1), - (14575, 1), - (14576, 1), - (14578, 2), - (14606, 2), - (14607, 2), + (14535, 1), + (14537, 1), + (14538, 2), + (14541, 1), + (14568, 1), + (14571, 1), + (14572, 1), + (14573, 1), + (14574, 2), + (14605, 1), (14608, 1), + (14609, 1), (14610, 1), (14611, 1), - (14614, 1), - (14618, 2), - (14645, 2), - (14648, 1), - (14651, 1), - (14652, 1), + (14615, 1), + (14616, 2), + (14646, 1), + (14648, 2), + (14649, 1), + (14650, 1), (14653, 1), - (14655, 1), + (14655, 2), + (14656, 1), (14685, 1), - (14687, 1), - (14688, 1), - (14689, 1), + (14688, 2), (14691, 4), (14692, 1), - (14694, 1), - (14695, 1), - (14720, 1), - (14722, 1), - (14723, 1), - (14724, 1), (14725, 1), (14727, 1), (14728, 1), - (14730, 2), - (14731, 1), - (14732, 2), - (14735, 2), - (14757, 1), - (14763, 1), - (14765, 1), - (14767, 1), (14769, 2), - (14797, 1), - (14798, 1), - (14801, 1), - (14806, 2), + (14770, 2), + (14804, 1), + (14806, 1), + (14808, 1), (14810, 2), - (14811, 1), - (14813, 2), - (14842, 1), - (14847, 2), - (14849, 2), - (14875, 1), - (14881, 1), - (14884, 1), - (14885, 2), + (14846, 1), + (14848, 2), + (14849, 1), + (14854, 1), + (14877, 1), + (14879, 1), + (14882, 1), + (14885, 1), (14886, 2), - (14889, 2), + (14887, 1), + (14889, 1), + (14915, 1), (14917, 1), - (14919, 1), - (14921, 2), - (14923, 1), + (14918, 1), + (14921, 1), (14924, 1), - (14926, 1), - (14927, 1), - (14928, 1), - (14956, 2), - (14957, 1), - (14958, 1), - (14961, 1), - (14963, 3), + (14925, 1), + (14956, 1), + (14958, 2), + (14960, 2), + (14962, 1), + (14963, 1), + (14964, 1), + (14965, 1), + (14967, 1), (14968, 1), - (15003, 2), - (15007, 1), - (15034, 1), - (15041, 2), + (15000, 2), + (15001, 1), + (15002, 2), + (15033, 1), + (15035, 1), + (15036, 2), + (15038, 1), + (15039, 1), (15043, 1), - (15044, 1), (15045, 1), - (15076, 1), + (15074, 2), + (15075, 1), (15080, 1), - (15081, 1), - (15082, 1), (15083, 1), - (15085, 1), - (15112, 1), + (15086, 1), + (15087, 1), (15114, 1), - (15117, 1), (15118, 1), - (15120, 2), - (15123, 1), - (15124, 1), + (15119, 1), + (15121, 1), (15155, 1), - (15156, 1), - (15165, 1), - (15186, 1), - (15196, 1), + (15158, 1), + (15160, 1), + (15161, 1), (15197, 1), - (15199, 1), - (15200, 1), + (15200, 2), (15231, 1), - (15232, 2), (15233, 1), - (15235, 3), - (15237, 2), + (15235, 1), + (15237, 1), (15238, 1), - (15266, 1), + (15239, 1), + (15242, 1), + (15268, 1), (15270, 1), + (15272, 1), + (15274, 1), (15275, 2), - (15276, 1), - (15280, 1), + (15279, 2), (15309, 1), + (15312, 1), + (15313, 2), (15314, 1), - (15345, 1), - (15352, 1), - (15353, 2), + (15346, 1), + (15348, 1), + (15349, 1), + (15350, 2), + (15353, 3), + (15354, 2), (15355, 2), - (15356, 1), (15384, 1), - (15385, 1), - (15386, 1), - (15388, 1), - (15396, 1), - (15421, 1), - (15422, 1), - (15425, 1), - (15434, 1), - (15435, 1), - (15436, 1), - (15461, 1), - (15462, 1), - (15463, 1), + (15392, 2), + (15393, 1), + (15428, 1), + (15430, 1), + (15431, 2), + (15432, 1), (15469, 1), (15474, 1), - (15475, 1), - (15500, 1), - (15504, 1), - (15505, 1), - (15507, 1), - (15508, 1), - (15509, 1), - (15512, 1), - (15513, 1), - (15539, 1), - (15542, 1), - (15544, 1), - (15548, 2), + (15503, 1), + (15508, 2), + (15509, 2), + (15510, 1), + (15545, 1), + (15549, 1), (15550, 1), - (15551, 1), + (15552, 1), (15580, 1), - (15586, 1), - (15587, 1), - (15589, 1), - (15590, 1), - (15618, 1), - (15620, 1), + (15582, 1), + (15588, 2), + (15594, 1), + (15621, 1), + (15623, 1), (15624, 1), - (15626, 1), - (15659, 2), - (15662, 1), + (15659, 1), (15665, 1), - (15667, 1), - (15668, 1), - (15695, 1), + (15669, 1), (15697, 1), - (15698, 1), + (15699, 1), (15701, 1), - (15702, 1), - (15704, 1), - (15709, 2), + (15705, 3), + (15736, 1), + (15737, 2), + (15738, 1), (15740, 1), - (15741, 1), - (15742, 1), - (15743, 1), - (15746, 1), + (15744, 2), + (15777, 1), (15778, 1), - (15779, 1), - (15782, 1), - (15784, 1), - (15786, 1), - (15825, 1), - (15849, 1), - (15853, 1), - (15857, 1), + (15780, 1), + (15782, 4), + (15783, 1), + (15818, 1), + (15819, 1), + (15820, 1), + (15821, 2), + (15823, 1), + (15825, 2), + (15827, 1), + (15855, 3), (15860, 1), - (15864, 1), - (15891, 1), - (15893, 2), - (15895, 1), + (15863, 1), + (15865, 1), + (15891, 2), + (15893, 1), (15896, 1), - (15898, 1), - (15900, 1), - (15932, 1), - (15937, 1), - (15938, 1), - (15967, 1), - (15973, 1), - (15977, 1), - (15980, 1), - (16007, 1), - (16010, 1), - (16012, 1), - (16014, 1), - (16016, 1), + (15897, 1), + (15901, 1), + (15930, 1), + (15941, 1), + (15972, 2), + (15974, 1), + (16009, 1), + (16011, 1), (16018, 1), - (16019, 1), + (16052, 1), (16053, 1), - (16058, 1), - (16086, 1), - (16091, 1), - (16093, 1), + (16094, 1), + (16096, 2), (16098, 1), - (16137, 1), - (16162, 1), - (16163, 1), + (16100, 1), + (16130, 1), + (16134, 1), + (16136, 1), + (16138, 2), + (16166, 1), (16167, 1), - (16168, 2), - (16171, 1), (16172, 2), - (16202, 1), - (16206, 1), - (16210, 2), - (16212, 1), - (16213, 1), - (16215, 1), + (16173, 2), (16245, 1), (16249, 1), - (16280, 1), - (16283, 1), - (16284, 1), (16288, 1), - (16319, 1), + (16296, 1), (16322, 2), - (16326, 1), - (16327, 3), - (16329, 1), - (16331, 1), + (16330, 1), + (16364, 1), + (16369, 1), (16370, 1), + (16371, 1), + (16398, 1), + (16399, 1), + (16400, 1), (16403, 1), - (16404, 1), - (16406, 1), - (16409, 1), - (16410, 1), - (16411, 1), - (16434, 1), + (16437, 1), (16440, 1), - (16441, 1), - (16443, 2), (16444, 1), - (16445, 1), - (16460, 1), - (16475, 1), - (16479, 1), - (16482, 1), - (16483, 2), - (16488, 1), - (16521, 2), - (16523, 2), - (16524, 1), - (16525, 2), - (16551, 1), - (16552, 1), - (16553, 2), - (16558, 1), - (16563, 1), - (16565, 1), - (16567, 1), - (16593, 1), - (16595, 1), - (16596, 1), + (16447, 1), + (16483, 1), + (16485, 1), + (16486, 1), + (16491, 1), + (16518, 1), + (16521, 1), + (16523, 1), + (16525, 1), + (16526, 1), + (16559, 1), + (16597, 1), (16600, 1), - (16639, 2), - (16644, 1), - (16673, 2), - (16674, 1), + (16601, 1), + (16604, 1), + (16634, 1), + (16636, 1), + (16639, 1), + (16670, 1), (16678, 1), - (16712, 1), + (16680, 1), + (16711, 1), (16714, 1), - (16717, 1), (16718, 1), - (16750, 1), - (16751, 1), - (16753, 1), - (16756, 1), - (16792, 1), - (16796, 1), - (16798, 2), - (16827, 1), - (16875, 1), - (16906, 1), - (16909, 1), - (16910, 1), - (16911, 2), - (16941, 1), - (16943, 1), - (16948, 1), + (16721, 1), + (16752, 1), + (16754, 1), + (16757, 1), + (16758, 2), + (16759, 1), + (16761, 2), + (16791, 1), + (16794, 1), + (16797, 1), + (16798, 1), + (16802, 1), + (16833, 1), + (16835, 1), + (16836, 2), + (16838, 2), + (16839, 1), + (16874, 1), + (16911, 1), + (16914, 1), (16949, 1), - (16954, 1), - (16957, 1), + (16952, 2), + (16953, 2), + (16956, 2), (16985, 1), - (16993, 1), - (17022, 2), - (17024, 1), - (17028, 1), - (17032, 1), + (17030, 1), + (17031, 1), + (17033, 1), + (17061, 1), + (17065, 1), (17066, 2), - (17103, 1), - (17104, 2), + (17069, 1), + (17071, 1), + (17073, 1), + (17104, 1), (17106, 1), - (17109, 1), - (17139, 1), + (17108, 1), + (17110, 1), (17143, 1), - (17179, 1), - (17183, 2), + (17144, 1), + (17147, 2), + (17148, 1), (17187, 1), - (17189, 1), - (17217, 1), - (17223, 2), - (17255, 1), + (17190, 1), + (17221, 1), + (17224, 1), + (17227, 1), (17262, 1), + (17263, 1), (17265, 1), (17278, 1), - (17298, 1), - (17302, 2), + (17303, 1), + (17304, 1), + (17307, 1), (17334, 1), - (17338, 1), - (17371, 2), - (17378, 1), - (17381, 1), + (17340, 1), + (17341, 2), + (17379, 1), (17415, 1), - (17416, 1), - (17457, 1), + (17419, 1), (17458, 1), - (17490, 1), - (17499, 1), + (17461, 1), + (17463, 1), + (17495, 2), + (17496, 1), + (17499, 2), + (17500, 1), + (17535, 1), (17536, 1), - (17539, 1), - (17568, 1), - (17571, 1), - (17572, 1), - (17616, 1), - (17617, 1), - (17619, 1), + (17538, 1), + (17540, 1), + (17572, 2), + (17580, 1), + (17610, 1), + (17613, 1), + (17614, 2), + (17615, 1), (17682, 5), - (17687, 1), - (17729, 1), - (17731, 1), - (17763, 1), + (17727, 1), (17769, 1), - (17803, 1), - (17806, 1), + (17776, 1), + (17809, 1), + (17810, 1), + (17811, 1), (17812, 1), - (17841, 1), - (17887, 1), - (17889, 1), - (17920, 1), + (17846, 2), + (17850, 1), + (17853, 1), + (17884, 2), (17922, 1), (17925, 1), - (17961, 1), - (17965, 1), - (17967, 1), - (18004, 1), + (17931, 1), + (17963, 1), + (17968, 1), + (17972, 1), + (18002, 1), + (18010, 1), (18030, 1), - (18040, 2), - (18042, 1), - (18043, 1), - (18044, 1), - (18045, 1), + (18040, 1), (18078, 1), - (18157, 1), - (18167, 1), + (18080, 1), + (18083, 1), + (18086, 1), + (18118, 1), + (18120, 2), + (18124, 2), + (18159, 1), + (18162, 1), + (18164, 1), + (18198, 1), + (18201, 1), + (18203, 1), + (18234, 1), (18236, 1), - (18239, 1), - (18270, 1), - (18314, 1), + (18238, 1), + (18239, 2), + (18241, 1), + (18243, 2), + (18279, 1), + (18318, 1), + (18354, 1), (18355, 1), + (18356, 1), + (18357, 1), + (18358, 2), + (18392, 2), (18394, 1), - (18396, 1), + (18396, 3), + (18398, 1), + (18429, 1), (18436, 1), - (18465, 1), - (18469, 1), - (18505, 1), - (18542, 2), - (18547, 1), - (18550, 1), - (18584, 1), - (18587, 1), - (18588, 1), - (18667, 1), + (18470, 1), + (18475, 1), + (18508, 1), + (18514, 1), + (18545, 1), + (18554, 1), + (18591, 1), + (18592, 2), + (18626, 2), + (18630, 1), + (18664, 1), (18668, 1), - (18702, 1), - (18741, 1), - (18742, 1), - (18783, 1), - (18784, 1), + (18743, 1), + (18746, 1), + (18747, 1), + (18748, 1), + (18783, 2), + (18790, 1), (18818, 1), - (18855, 1), - (18900, 1), + (18825, 1), + (18826, 1), + (18859, 2), + (18860, 1), + (18861, 1), + (18863, 1), + (18864, 1), + (18866, 1), (18904, 1), (18939, 1), - (18943, 1), - (18977, 1), - (19013, 1), - (19019, 1), - (19021, 1), - (19048, 1), - (19053, 1), - (19056, 1), - (19133, 2), - (19172, 1), - (19176, 2), + (18940, 1), + (18976, 1), + (18980, 2), + (18981, 1), + (19015, 1), + (19019, 2), + (19054, 1), + (19058, 2), + (19061, 1), + (19095, 1), + (19099, 1), + (19131, 1), + (19133, 1), + (19139, 1), + (19171, 1), + (19177, 1), + (19178, 1), (19201, 5), - (19211, 1), - (19248, 1), - (19249, 1), + (19209, 1), + (19215, 1), + (19216, 1), + (19253, 1), (19280, 1), - (19288, 1), - (19295, 1), - (19325, 1), - (19327, 1), - (19328, 2), - (19330, 2), + (19292, 1), + (19296, 1), + (19328, 1), + (19329, 1), + (19330, 1), + (19331, 2), + (19332, 1), (19337, 6), - (19365, 1), - (19406, 1), - (19407, 1), - (19450, 1), - (19487, 1), - (19526, 1), - (19561, 2), + (19371, 1), + (19408, 1), + (19410, 2), + (19444, 1), + (19450, 2), + (19486, 2), + (19487, 2), + (19528, 1), + (19560, 1), (19564, 1), - (19600, 1), - (19605, 1), - (19640, 1), + (19603, 2), + (19606, 1), + (19643, 1), + (19644, 1), + (19679, 1), (19680, 1), - (19720, 1), + (19681, 1), + (19682, 2), + (19683, 1), + (19684, 1), + (19718, 1), + (19722, 1), + (19755, 1), (19758, 1), - (19800, 1), - (19952, 2), + (19759, 2), + (19837, 1), + (19838, 1), + (19877, 1), + (19878, 1), + (19914, 1), + (19916, 3), (19954, 1), - (19955, 1), - (19956, 1), - (19988, 1), - (19989, 26), - (19990, 21), - (19991, 30), - (19992, 21), - (19993, 13), - (19994, 12), - (19995, 9), - (19996, 6), - (20000, 1), - (20010, 1), - (20030, 1), - (20031, 1), - (20066, 1), + (19989, 1), + (19991, 6), + (19992, 27), + (19993, 18), + (19994, 9), + (19995, 3), + (19996, 4), + (19997, 3), + (20024, 1), + (20029, 2), + (20031, 2), + (20033, 1), + (20068, 1), (20069, 1), - (20070, 1), - (20073, 1), - (20109, 1), - (20111, 1), - (20132, 1), - (20150, 1), - (20186, 1), - (20266, 1), - (20267, 1), - (20268, 1), - (20302, 1), + (20187, 1), + (20188, 1), + (20228, 1), (20303, 1), + (20304, 1), + (20342, 1), + (20344, 2), + (20347, 1), + (20381, 1), (20423, 1), (20424, 1), - (20540, 1), + (20457, 1), + (20461, 1), + (20542, 1), + (20543, 1), (20577, 1), - (20616, 1), - (20654, 1), - (20655, 2), + (20578, 1), + (20618, 1), + (20656, 1), + (20657, 1), + (20658, 1), (20693, 1), - (20696, 1), - (20732, 2), - (20773, 2), + (20733, 1), + (20773, 1), + (20813, 1), + (20850, 1), + (20851, 1), (20883, 1), - (20888, 1), - (20892, 1), - (20925, 1), - (20928, 1), + (20888, 2), + (20890, 1), + (20929, 1), + (20967, 2), + (21044, 1), (21045, 1), - (21047, 1), - (21083, 2), - (21126, 1), - (21165, 1), - (21201, 1), - (21202, 1), - (21276, 1), - (21315, 1), - (21357, 1), - (21399, 2), - (21439, 1), - (21476, 1), - (21510, 1), - (21513, 1), - (21550, 1), + (21128, 1), + (21162, 1), + (21280, 1), + (21318, 1), + (21358, 1), + (21359, 1), + (21395, 1), + (21434, 1), + (21435, 1), + (21473, 1), + (21514, 1), (21551, 1), - (21593, 1), - (21633, 1), - (21665, 1), - (21666, 1), - (21669, 1), - (21751, 1), - (21826, 1), - (21921, 1), - (21939, 1), - (21943, 1), - (21977, 1), - (21980, 2), - (21981, 1), - (22017, 1), - (22018, 1), - (22133, 1), - (22134, 1), - (22135, 2), - (22172, 1), - (22211, 1), - (22212, 1), - (22213, 1), - (22251, 1), - (22254, 1), - (22256, 1), - (22290, 1), - (22371, 1), - (22406, 1), - (22408, 1), - (22410, 1), - (22451, 1), - (22485, 1), - (22486, 2), - (22525, 1), - (22526, 1), - (22562, 1), - (22563, 3), - (22564, 1), - (22607, 1), - (22644, 1), - (22680, 1), - (22758, 1), - (22759, 1), - (22798, 2), - (22837, 2), - (22838, 1), - (22875, 1), - (22877, 1), - (22914, 1), - (22916, 1), - (22918, 1), - (22993, 1), - (23031, 1), - (23033, 2), - (23070, 1), - (23109, 1), - (23111, 1), - (23148, 1), - (23151, 1), - (23188, 1), - (23189, 1), - (23226, 1), - (23227, 1), - (23304, 1), - (23305, 1), + (21552, 1), + (21629, 2), + (21668, 1), + (21708, 1), + (21712, 1), + (21747, 1), + (21983, 1), + (22020, 1), + (22097, 1), + (22529, 1), (23381, 5), - (23384, 2), - (23388, 1), - (23424, 1), - (23462, 1), - (23498, 1), - (23542, 1), - (23579, 1), - (23580, 1), - (23654, 1), - (23657, 1), - (23820, 1), - (24019, 7), - (24047, 1), - (24204, 1), - (24390, 1), (27166, 6), + (27623, 7), (31645, 5), (37476, 6), - (50442, 1), (66530, 1), (236741, 1), (266960, 1), @@ -5683,61 +7385,58 @@ pub const VALUE_LENGTH_HISTOGRAM: &[(u32, u32)] = &[ (533889, 1), (534391, 1), (537072, 1), - (537491, 1), (546820, 1), (554056, 1), (562513, 1), (570304, 1), (571882, 1), (580008, 1), - (582755, 1), (586561, 1), (589436, 1), (593061, 2), - (618859, 1), - (619082, 1), (625907, 1), (633533, 1), + (637743, 1), (644603, 1), (646180, 1), (655481, 1), - (693987, 1), (701633, 1), (728784, 1), - (745886, 1), - (752140, 1), - (771376, 1), - (848764, 1), + (741162, 1), + (751759, 1), + (782221, 1), + (785912, 1), + (901532, 1), (902834, 1), (952321, 1), (964030, 1), - (974008, 1), (977740, 1), (992978, 1), - (1019553, 1), - (1057259, 1), + (1024668, 1), + (1052088, 1), (1094674, 1), - (1105518, 1), - (1116659, 1), - (1121314, 1), - (1135487, 1), - (1151345, 1), - (1173415, 1), - (1189567, 1), + (1123764, 1), + (1145006, 1), + (1149240, 1), + (1162664, 1), + (1181063, 1), + (1237621, 1), (1238079, 1), - (1282021, 1), - (1290980, 1), - (1293007, 1), + (1304137, 1), (1318405, 1), - (1328926, 1), (1338999, 1), - (1373382, 1), - (1402596, 1), - (1422519, 1), - (1446480, 1), - (1460046, 1), - (1475924, 1), - (1478227, 1), + (1346855, 1), + (1379530, 1), + (1381203, 1), + (1430590, 1), + (1448224, 1), + (1455881, 1), + (1473348, 1), (1482046, 1), - (1597051, 1), + (1487730, 1), + (1492627, 1), + (1514540, 1), + (1534484, 1), + (1684302, 1), + (1910865, 1), ]; diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index df3e94f3..c6f67f3f 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -30,6 +30,9 @@ static QUERIES: AtomicUsize = AtomicUsize::new(0); static ITERATIONS: AtomicUsize = AtomicUsize::new(0); static EXPECTED_NUM_ENTRIES: AtomicUsize = AtomicUsize::new(0); +static NUM_PATHS: AtomicUsize = AtomicUsize::new(0); +static NUM_PATHS_SUCCESS: AtomicUsize = AtomicUsize::new(0); + const TREE_COLUMN: u8 = 0; const INFO_COLUMN: u8 = 1; @@ -202,19 +205,21 @@ pub enum NodeSpec { struct ChainGenerator { depth_child_count_histograms: Vec, - age_histogram: Histogram, + depth_age_histograms: Vec, value_length_histogram: Histogram, seed: u64, compressable: bool, + pruning: u64, } impl ChainGenerator { fn new( depth_child_count_histogram: &[(u32, [u32; 17])], - age_histogram: &[(u32, u32)], + depth_age_histogram: &[(u32, &[(u32, u32)])], value_length_histogram: &[(u32, u32)], seed: u64, compressable: bool, + pruning: u64, ) -> ChainGenerator { let mut depth_child_count_histograms = Vec::default(); for (depth, histogram_data) in depth_child_count_histogram { @@ -227,16 +232,24 @@ impl ChainGenerator { depth_child_count_histograms.push(histogram); } - let age_histogram = Histogram::new(age_histogram); + let mut depth_age_histograms = Vec::default(); + for (depth, histogram_data) in depth_age_histogram { + assert_eq!(*depth, depth_age_histograms.len() as u32); + + let histogram = Histogram::new(histogram_data); + + depth_age_histograms.push(histogram); + } let value_length_histogram = Histogram::new(value_length_histogram); ChainGenerator { depth_child_count_histograms, - age_histogram, + depth_age_histograms, value_length_histogram, seed, compressable, + pruning, } } @@ -256,6 +269,18 @@ impl ChainGenerator { key } + fn num_node_children(&self, _tree_index: u64, depth: u32, seed: u64) -> u32 { + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); + + let num_children = if depth < self.depth_child_count_histograms.len() as u32 { + self.depth_child_count_histograms[depth as usize].sample(rng.next_u64()) + } else { + 0 + }; + + num_children + } + /// Returns tuple of node data and child specs. When only_direct_children is true node data will /// be empty and non direct children will be NodeSpec::UnresolvedPath. fn generate_node( @@ -272,12 +297,21 @@ impl ChainGenerator { } else { 0 }; - let mut children = Vec::default(); + let mut children = Vec::with_capacity(num_children as usize); for _i in 0..num_children { - let age = self.age_histogram.sample(rng.next_u64()) as u64; + let age = if depth < self.depth_age_histograms.len() as u32 { + self.depth_age_histograms[depth as usize].sample(rng.next_u64()) as u64 + } else { + // No age data for this depth. This implies the age is larger than was used when + // sampling. Hence use the oldest tree we can. + tree_index + }; + + // Restrict to within the pruning window + let age = if self.pruning > 0 { std::cmp::min(age, self.pruning) } else { age }; - let child_tree_index = if age > tree_index { tree_index } else { tree_index - age }; + let child_tree_index = if age > tree_index { 0 } else { tree_index - age }; if child_tree_index == tree_index { children.push(NodeSpec::Direct(tree_index, depth + 1, rng.next_u64())); @@ -290,56 +324,111 @@ impl ChainGenerator { } else { // Generate path to node in child_tree_index let mut path_rng = rand::rngs::SmallRng::seed_from_u64(path_seed); - let mut path = Vec::default(); let mut path_node: Option = None; let target_depth = depth + 1; - let mut other_tree_index = child_tree_index; - let mut other_depth = 0; - let mut other_seed = self.root_seed(child_tree_index); - while other_depth < target_depth { - let (_other_node_data, other_children) = - self.generate_node(other_tree_index, other_depth, other_seed, true); - - let mut direct_children = - other_children.iter().enumerate().filter(|(_, x)| { - if let NodeSpec::Direct(..) = x { - true + for _ in 0..2 { + let mut other_tree_index = child_tree_index; + let mut other_depth = 0; + let mut other_seed = self.root_seed(child_tree_index); + let mut path = Vec::default(); + while other_depth < target_depth { + let (_other_node_data, other_children) = + self.generate_node(other_tree_index, other_depth, other_seed, true); + + let direct_children = + other_children.iter().enumerate().filter(|(_, x)| { + if let NodeSpec::Direct(..) = x { + true + } else { + false + } + }); + + let num_direct_children = direct_children.clone().count(); + + if num_direct_children == 0 { + break + } + + // Try to select a child that has more children itself so the path has a + // higher chance of success. + let mut num_grandchildren: Vec = + Vec::with_capacity(num_direct_children); + let mut min_grandchildren = u32::MAX; + let mut max_grandchildren = 0; + for (_index, node) in direct_children.clone() { + let num = if let NodeSpec::Direct(new_index, new_depth, new_seed) = + node + { + self.num_node_children(*new_index, *new_depth, *new_seed) + as usize } else { - false - } - }); - let num_direct_children = direct_children.clone().count(); + 0 + }; + min_grandchildren = std::cmp::min(min_grandchildren, num as u32); + max_grandchildren = std::cmp::max(max_grandchildren, num as u32); + num_grandchildren.push(num); + } + let direct_children: Vec<(usize, &NodeSpec)> = + if min_grandchildren < max_grandchildren { + // Can remove some + let diff = max_grandchildren - min_grandchildren; + let threshold = if diff > 1 { + min_grandchildren + diff / 2 + } else { + min_grandchildren + }; + direct_children + .enumerate() + .filter(|(index, _)| { + num_grandchildren[*index] as u32 > threshold + }) + .map(|(_, val)| val) + .collect::>() + } else { + direct_children.collect::>() + }; - if num_direct_children == 0 { - break - } + let num_direct_children = direct_children.len(); + + if num_direct_children == 0 { + break + } - let child_index = path_rng.next_u64() % num_direct_children as u64; + let child_index = path_rng.next_u64() % num_direct_children as u64; - let child = direct_children.nth(child_index as usize).unwrap(); - if let NodeSpec::Direct(new_index, new_depth, new_seed) = child.1 { - path.push(child.0 as u32); + let child = direct_children[child_index as usize]; + if let NodeSpec::Direct(new_index, new_depth, new_seed) = child.1 { + path.push(child.0 as u32); - // Chose a direct node so should be same tree, one depth down. - assert_eq!(*new_index, other_tree_index); - assert_eq!(*new_depth, other_depth + 1); + // Chose a direct node so should be same tree, one depth down. + assert_eq!(*new_index, other_tree_index); + assert_eq!(*new_depth, other_depth + 1); - other_tree_index = *new_index; - other_depth = *new_depth; - other_seed = *new_seed; + other_tree_index = *new_index; + other_depth = *new_depth; + other_seed = *new_seed; - if other_depth == target_depth { - path_node = Some(NodeSpec::Path(child_tree_index, path.clone())); + if other_depth == target_depth { + path_node = + Some(NodeSpec::Path(child_tree_index, path.clone())); + } + } else { + assert!(false); + break } - } else { + } + if path_node.is_some() { break } } + NUM_PATHS.fetch_add(1, Ordering::SeqCst); match path_node { Some(node) => { + NUM_PATHS_SUCCESS.fetch_add(1, Ordering::SeqCst); children.push(node); }, None => { @@ -364,8 +453,11 @@ impl ChainGenerator { return (Vec::new(), children) } + // Polkadot doesn't store actual values in branch nodes, only in leaf nodes. Hence the value + // stored in the db will only be for the nibble path. let mut size = 4; if num_children == 0 { + // Leaf node, so simulate an actual value using the size histogram. size = self.value_length_histogram.sample(rng.next_u64()) as usize; if FORCE_NO_MULTIPART_VALUES { size = std::cmp::min(size, 32760 - 64); @@ -421,9 +513,13 @@ fn informant( num_expected_entries = new_num_expected_entries; num_entries = new_num_entries; + let num_paths = NUM_PATHS.load(Ordering::Relaxed); + let num_paths_success = NUM_PATHS_SUCCESS.load(Ordering::Relaxed); + let existing_ratio = num_paths_success as f32 / num_paths as f32; + output_helper.write().print_fixed(format!( - "Entries, Created: {}, ValueTables: {}", - num_expected_entries, num_entries + "Entries, Created: {}, ValueTables: {}, Path success ratio: {}", + num_expected_entries, num_entries, existing_ratio )); if num_entries == 0 { @@ -491,16 +587,16 @@ fn build_commit_tree<'s, 'd: 's>( let mut final_child_address: Option = None; if let Some(tree_guard) = tree_guards.get(&key) { - if let Some((db_node_data, db_children)) = tree_guard.get_root().unwrap() { + if let Some((_db_node_data, db_children)) = tree_guard.get_root().unwrap() { // Note: We don't actually have to generate any nodes here; we could just // traverse down the database nodes. Only generating them to verify data. - let (gen_node_data, gen_children) = + /* let (gen_node_data, gen_children) = chain_generator.generate_node(tree_index, 0, root_seed, false); assert_eq!(gen_node_data, db_node_data); assert_eq!(gen_children.len(), db_children.len()); - let mut generated_children = gen_children; + let mut generated_children = gen_children; */ let mut database_children = db_children; for index in 0..path.len() { @@ -513,7 +609,7 @@ fn build_commit_tree<'s, 'd: 's>( break } - let (child_tree_index, child_depth, child_seed) = + /* let (child_tree_index, child_depth, child_seed) = match &generated_children[child_index as usize] { NodeSpec::Direct(child_tree_index, child_depth, child_seed) => (*child_tree_index, *child_depth, *child_seed), @@ -528,14 +624,14 @@ fn build_commit_tree<'s, 'd: 's>( child_depth, child_seed, false, - ); + ); */ match tree_guard.get_node(child_address).unwrap() { - Some((db_node_data, db_children)) => { - assert_eq!(gen_node_data, db_node_data); + Some((_db_node_data, db_children)) => { + /* assert_eq!(gen_node_data, db_node_data); assert_eq!(gen_children.len(), db_children.len()); - generated_children = gen_children; + generated_children = gen_children; */ database_children = db_children; }, None => return Err("Child address not in database".to_string()), @@ -707,7 +803,7 @@ fn writer( start_commit: usize, output_helper: Arc>, ) -> Result<(), String> { - let seed = args.seed.unwrap_or(0); + //let seed = args.seed.unwrap_or(0); let mut commit = Vec::new(); loop { @@ -771,8 +867,8 @@ fn writer( commit.clear(); // Immediately read and check a random value from the tree - let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); - read_value(tree_index, &mut rng, &db, &chain_generator)?; + /* let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); + read_value(tree_index, &mut rng, &db, &chain_generator)?; */ if args.pruning > 0 && !THREAD_PRUNING { try_prune(&db, &args, &chain_generator, &mut commit, &output_helper)?; @@ -1019,18 +1115,20 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { 0 }; - let total_num_expected_tree_nodes: u32 = - data::DEPTH_CHILD_COUNT_HISTOGRAMS.iter().map(|x| x.1.iter().sum::()).sum(); output_helper .write() - .println(format!("Expected average num tree nodes: {}", total_num_expected_tree_nodes)); + .println(format!("Expected average num tree nodes: {}", data::NUM_NODES)); + output_helper + .write() + .println(format!("Expected average num new nodes: {}", data::AVERAGE_NUM_NEW_NODES)); let chain_generator = ChainGenerator::new( data::DEPTH_CHILD_COUNT_HISTOGRAMS, - data::AGE_HISTOGRAM, + data::DEPTH_AGE_HISTOGRAMS, data::VALUE_LENGTH_HISTOGRAM, args.seed.unwrap_or(0), args.compress, + args.pruning, ); let chain_generator = Arc::new(chain_generator); From 7365866b3ee1ee4544044e19a9c6c3f1e8404cf1 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 3 Aug 2023 14:38:58 +0100 Subject: [PATCH 17/53] Prepare for using claim_contiguous_entries --- src/column.rs | 141 +++++++++++++++++++++++++++++++++++++++---------- src/options.rs | 4 ++ src/table.rs | 14 +++-- 3 files changed, 127 insertions(+), 32 deletions(-) diff --git a/src/column.rs b/src/column.rs index 8997f5f5..db3fa148 100644 --- a/src/column.rs +++ b/src/column.rs @@ -20,7 +20,7 @@ use crate::{ Key, }; use std::{ - collections::VecDeque, + collections::{HashMap, VecDeque}, path::PathBuf, sync::{ atomic::{AtomicU64, Ordering}, @@ -379,6 +379,10 @@ impl Column { } } +pub fn packed_node_size(data: &Vec, num_children: u8) -> usize { + 1 + data.len() + num_children as usize * 8 +} + pub fn pack_node_data(data: Vec, child_data: Vec, num_children: u8) -> Vec { [vec![num_children], data, child_data].concat() } @@ -708,19 +712,80 @@ impl HashColumn { Ok((outcome, tables, reindex)) } + fn prepare_children( + &self, + children: &Vec, + tables: TablesRef, + tier_count: &mut HashMap, + ) -> Result<()> { + for child in children { + match child { + NodeRef::New(node) => self.prepare_node(node, tables, tier_count)?, + NodeRef::Existing(_address) => {}, + }; + } + Ok(()) + } + + fn prepare_node( + &self, + node: &NewNode, + tables: TablesRef, + tier_count: &mut HashMap, + ) -> Result<()> { + let data_size = packed_node_size(&node.data, node.children.len() as u8); + + let table_key = TableKey::NoHash; + + /* let (cval, target_tier) = + Column::compress(tables.compression, &table_key, data.as_ref(), tables.tables); + let (cval, compressed) = cval + .as_ref() + .map(|cval| (cval.as_slice(), true)) + .unwrap_or((data.as_ref(), false)); + + let cval: RcValue = cval.to_vec().into(); + let val = if compressed { data.into() } else { cval.clone() }; */ + + let target_tier = tables + .tables + .iter() + .position(|t| t.value_size(&table_key).map_or(false, |s| data_size <= s as usize)); + let target_tier = target_tier.unwrap_or_else(|| tables.tables.len() - 1); + + // Check it isn't multipart + //assert!(target_tier < (SIZE_TIERS - 1)); + + match tier_count.entry(target_tier) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + *entry.get_mut() += 1; + }, + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(1); + }, + } + + self.prepare_children(&node.children, tables, tier_count)?; + + Ok(()) + } + fn claim_children( &self, - children: Vec, + children: &Vec, tables: TablesRef, + tier_addresses: &HashMap>, + tier_index: &mut HashMap, node_values: &mut Vec, ) -> Result> { let mut data = Vec::new(); for child in children { let address = match child { - NodeRef::New(node) => self.claim_node(node, tables, node_values)?, + NodeRef::New(node) => + self.claim_node(node, tables, tier_addresses, tier_index, node_values)?, NodeRef::Existing(address) => { - node_values.push(NodeChange::IncrementReference(address)); - address + node_values.push(NodeChange::IncrementReference(*address)); + *address }, }; let mut data_buf = [0u8; 8]; @@ -732,39 +797,40 @@ impl HashColumn { fn claim_node( &self, - node: NewNode, + node: &NewNode, tables: TablesRef, + tier_addresses: &HashMap>, + tier_index: &mut HashMap, node_values: &mut Vec, ) -> Result { let num_children = node.children.len(); - let data = pack_node_data( - node.data, - self.claim_children(node.children, tables, node_values)?, - num_children as u8, - ); + + let data_size = packed_node_size(&node.data, num_children as u8); let table_key = TableKey::NoHash; - let (cval, target_tier) = - Column::compress(tables.compression, &table_key, data.as_ref(), tables.tables); - let (cval, compressed) = cval - .as_ref() - .map(|cval| (cval.as_slice(), true)) - .unwrap_or((data.as_ref(), false)); + let target_tier = tables + .tables + .iter() + .position(|t| t.value_size(&table_key).map_or(false, |s| data_size <= s as usize)); + let target_tier = target_tier.unwrap_or_else(|| tables.tables.len() - 1); - let cval: RcValue = cval.to_vec().into(); - let val = if compressed { data.into() } else { cval.clone() }; + let index = *tier_index.get(&target_tier).unwrap(); + tier_index.insert(target_tier, index + 1); - assert!( - (target_tier >= (SIZE_TIERS - 1)) || - cval.value().len() <= - tables.tables[target_tier].value_size(&table_key).unwrap() as usize + let offset = tier_addresses.get(&target_tier).unwrap()[index]; + + let data = pack_node_data( + node.data.clone(), + self.claim_children(&node.children, tables, tier_addresses, tier_index, node_values)?, + num_children as u8, ); - // Check it isn't multipart - //assert!(target_tier < (SIZE_TIERS - 1)); + // Can't support compression as we need to know the size earlier to get the tier. + let val: RcValue = data.into(); + let cval = val.clone(); + let compressed = false; - let offset = tables.tables[target_tier].claim_next_free()?; let address = Address::new(offset, target_tier as u8); node_values.push(NodeChange::NewValue(address.as_u64(), val, cval, compressed)); @@ -781,14 +847,29 @@ impl HashColumn { Operation::InsertTree(_key, node) => { let tables = self.tables.upgradable_read(); + let values = self.as_ref(&tables.value); + + let mut tier_count: HashMap = Default::default(); + self.prepare_children(&node.children, values, &mut tier_count)?; + + let mut tier_addresses: HashMap> = Default::default(); + let mut tier_index: HashMap = Default::default(); + for (tier, count) in tier_count { + let offsets = values.tables[tier].claim_contiguous_entries(count, 8)?; + tier_addresses.insert(tier, offsets); + tier_index.insert(tier, 0); + } + let mut node_values: Vec = Default::default(); let num_children = node.children.len(); let data = pack_node_data( node.data.clone(), self.claim_children( - node.children.clone(), - self.as_ref(&tables.value), + &node.children, + values, + &tier_addresses, + &mut tier_index, &mut node_values, )?, num_children as u8, @@ -797,7 +878,9 @@ impl HashColumn { return Ok((data, node_values)) }, Operation::RemoveTree(_key) => - return Err(Error::InvalidInput(format!("RemoveTree not implemented yet"))), + return Err(Error::InvalidInput(format!( + "claim_tree_values should not be called with RemoveTree" + ))), _ => return Err(Error::InvalidInput(format!( "Invalid operation for column {}", diff --git a/src/options.rs b/src/options.rs index 5f22b55d..830f2c21 100644 --- a/src/options.rs +++ b/src/options.rs @@ -99,6 +99,10 @@ impl ColumnOptions { log::error!(target: "parity-db", "Using `ref_counted` option without `preimage` enabled is not supported"); return false } + if self.multitree && self.compression != CompressionType::NoCompression { + log::error!(target: "parity-db", "Compression is not currently supported with multitree columns"); + return false + } true } diff --git a/src/table.rs b/src/table.rs index acc59ad3..52d1e0e7 100644 --- a/src/table.rs +++ b/src/table.rs @@ -762,9 +762,17 @@ impl ValueTable { } } - /* pub fn claim_contiguous_entries(&self, num: u64, min_span_length: u64) -> Vec { - Vec::new() - } */ + pub fn claim_contiguous_entries( + &self, + num: usize, + _min_span_length: usize, + ) -> Result> { + let mut entries: Vec = Default::default(); + for _i in 0..num { + entries.push(self.claim_next_free()?); + } + Ok(entries) + } fn overwrite_chain( &self, From 5703cc21ceda7636fd1c34f98faa25e66d841240 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 7 Aug 2023 09:13:50 +0200 Subject: [PATCH 18/53] Append-only mode --- admin/src/lib.rs | 8 ++++---- src/column.rs | 6 +++++- src/db.rs | 25 ++++++++++++++----------- src/options.rs | 8 +++++++- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index 0a5b94f4..2d97e50a 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -115,12 +115,12 @@ pub fn run() -> Result<(), String> { let mut db_options = options.clone(); if args.compress { - for mut c in &mut db_options.columns { + for c in &mut db_options.columns { c.compression = parity_db::CompressionType::Lz4; } } if args.uniform { - for mut c in &mut db_options.columns { + for c in &mut db_options.columns { c.uniform = true; } } @@ -139,12 +139,12 @@ pub fn run() -> Result<(), String> { let mut db_options = options.clone(); - for mut c in &mut db_options.columns { + for c in &mut db_options.columns { c.multitree = true; } if args.compress { - for mut c in &mut db_options.columns { + for c in &mut db_options.columns { c.compression = parity_db::CompressionType::Lz4; } } diff --git a/src/column.rs b/src/column.rs index db3fa148..5ec2c8cc 100644 --- a/src/column.rs +++ b/src/column.rs @@ -101,6 +101,7 @@ pub struct HashColumn { uniform_keys: bool, collect_stats: bool, ref_counted: bool, + append_only: bool, salt: Salt, stats: ColumnStats, compression: Compress, @@ -428,6 +429,7 @@ impl HashColumn { preimage: col_options.preimage, uniform_keys: col_options.uniform, ref_counted: col_options.ref_counted, + append_only: col_options.append_only, collect_stats, salt: metadata.salt, stats, @@ -784,7 +786,9 @@ impl HashColumn { NodeRef::New(node) => self.claim_node(node, tables, tier_addresses, tier_index, node_values)?, NodeRef::Existing(address) => { - node_values.push(NodeChange::IncrementReference(*address)); + if !self.append_only { + node_values.push(NodeChange::IncrementReference(*address)); + } *address }, }; diff --git a/src/db.rs b/src/db.rs index 698a1d36..b74fc0ca 100644 --- a/src/db.rs +++ b/src/db.rs @@ -298,18 +298,13 @@ impl DbInner { } } - /* fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { - match &self.columns[col as usize] { - Column::Hash(column) => { - let value = self.get(col, key)?; - if let Some(data) = value { - return Ok(Some(unpack_node_data(data)?)) - } - Ok(None) - }, - Column::Tree(_) => Err(Error::InvalidConfiguration("Not a HashColumn.".to_string())), + fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { + let value = self.get(col, key)?; + if let Some(data) = value { + return Ok(Some(unpack_node_data(data)?)) } - } */ + Ok(None) + } fn get_node( &self, @@ -1149,6 +1144,14 @@ impl Db { self.inner.get_tree(&self.inner, col, key, true) } + pub fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { + self.inner.get_root(col, key) + } + + pub fn get_node(&self, col: ColId, node_address: NodeAddress) -> Result, Children)>> { + self.inner.get_node(col, node_address) + } + /// Commit a set of changes to the database. pub fn commit(&self, tx: I) -> Result<()> where diff --git a/src/options.rs b/src/options.rs index 830f2c21..00427302 100644 --- a/src/options.rs +++ b/src/options.rs @@ -68,6 +68,8 @@ pub struct ColumnOptions { /// Column supports Multitree operations. This allows committing and querying of tree /// structures. pub multitree: bool, + /// Column is append-only. Delete operations are ignored. + pub append_only: bool, } /// Database metadata. @@ -84,13 +86,14 @@ pub struct Metadata { impl ColumnOptions { fn as_string(&self) -> String { format!( - "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}, multitree: {}", + "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}, multitree: {}, append_only: {}", self.preimage, self.uniform, self.ref_counted, self.compression as u8, self.btree_index, self.multitree, + self.append_only, ) } @@ -124,6 +127,7 @@ impl ColumnOptions { let compression: u8 = vals.get("compression").and_then(|c| c.parse().ok()).unwrap_or(0); let btree_index = vals.get("ordered").and_then(|c| c.parse().ok()).unwrap_or(false); let multitree = vals.get("multitree").and_then(|c| c.parse().ok()).unwrap_or(false); + let append_only = vals.get("append_only").and_then(|c| c.parse().ok()).unwrap_or(false); Some(ColumnOptions { preimage, @@ -132,6 +136,7 @@ impl ColumnOptions { compression: compression.into(), btree_index, multitree, + append_only, }) } } @@ -145,6 +150,7 @@ impl Default for ColumnOptions { compression: CompressionType::NoCompression, btree_index: false, multitree: false, + append_only: false, } } } From 6cdf863e0e111616f64c86c5593d965a4fb252f6 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 7 Aug 2023 13:25:48 +0200 Subject: [PATCH 19/53] Check RC on dereferencing root --- src/btree/btree.rs | 2 +- src/btree/mod.rs | 6 ++--- src/column.rs | 22 ++++++++-------- src/db.rs | 62 +++++++++++++++++++++++++--------------------- 4 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/btree/btree.rs b/src/btree/btree.rs index 746ba9a8..c1434de1 100644 --- a/src/btree/btree.rs +++ b/src/btree/btree.rs @@ -96,7 +96,7 @@ impl BTree { if let Some(address) = root.get(key, values, log)? { let key_query = TableKeyQuery::Fetch(None); let r = Column::get_value(key_query, address, values, log)?; - Ok(r.map(|r| r.1)) + Ok(r.map(|r| r.2)) } else { Ok(None) } diff --git a/src/btree/mod.rs b/src/btree/mod.rs index 25ccfff2..c113d915 100644 --- a/src/btree/mod.rs +++ b/src/btree/mod.rs @@ -169,7 +169,7 @@ impl BTreeTable { let mut depth = 0; let key_query = TableKeyQuery::Fetch(None); if let Some(encoded) = Column::get_value(key_query, HEADER_ADDRESS, values, log)? { - let mut buf: ValueTableEntry> = ValueTableEntry::new(encoded.1); + let mut buf: ValueTableEntry> = ValueTableEntry::new(encoded.2); buf.check_remaining_len(8 + 4, || Error::Corruption("Invalid header length.".into()))?; root = Address::from_u64(buf.read_u64()); depth = buf.read_u32(); @@ -185,7 +185,7 @@ impl BTreeTable { ) -> Result> { let tables = self.tables.read(); let btree = self.locked(&tables); - Column::get_value(key, address, btree, log) + Ok(Column::get_value(key, address, btree, log)?.map(|(tier, _rc, value)| (tier, value))) } pub fn flush(&self) -> Result<()> { @@ -209,7 +209,7 @@ impl BTreeTable { fn get_encoded_entry(at: Address, log: &impl LogQuery, tables: TablesRef) -> Result> { let key_query = TableKeyQuery::Check(&TableKey::NoHash); - if let Some((_tier, value)) = Column::get_value(key_query, at, tables, log)? { + if let Some((_tier, _rc, value)) = Column::get_value(key_query, at, tables, log)? { Ok(value) } else { Err(Error::Corruption(format!("Missing btree entry at {at}"))) diff --git a/src/column.rs b/src/column.rs index 5ec2c8cc..44724596 100644 --- a/src/column.rs +++ b/src/column.rs @@ -201,21 +201,21 @@ pub struct ReindexBatch { } impl HashColumn { - pub fn get(&self, key: &Key, log: &impl LogQuery) -> Result> { + pub fn get(&self, key: &Key, log: &impl LogQuery) -> Result> { let tables = self.tables.read(); let values = self.as_ref(&tables.value); - if let Some((tier, value)) = self.get_in_index(key, &tables.index, values, log)? { + if let Some((tier, rc, value)) = self.get_in_index(key, &tables.index, values, log)? { if self.collect_stats { self.stats.query_hit(tier); } - return Ok(Some(value)) + return Ok(Some((value, rc))) } for r in &self.reindex.read().queue { - if let Some((tier, value)) = self.get_in_index(key, r, values, log)? { + if let Some((tier, rc, value)) = self.get_in_index(key, r, values, log)? { if self.collect_stats { self.stats.query_hit(tier); } - return Ok(Some(value)) + return Ok(Some((value, rc))) } } if self.collect_stats { @@ -225,13 +225,13 @@ impl HashColumn { } pub fn get_size(&self, key: &Key, log: &RwLock) -> Result> { - self.get(key, log).map(|v| v.map(|v| v.len() as u32)) + Ok(self.get(key, log)?.map(|(v, _rc)| v.len() as u32)) } pub fn get_value(&self, address: Address, log: &impl LogQuery) -> Result> { let tables = self.tables.read(); let values = self.as_ref(&tables.value); - if let Some((tier, value)) = + if let Some((tier, _rc, value)) = Column::get_value(TableKeyQuery::Check(&TableKey::NoHash), address, values, log)? { if self.collect_stats { @@ -251,7 +251,7 @@ impl HashColumn { index: &IndexTable, tables: TablesRef, log: &impl LogQuery, - ) -> Result> { + ) -> Result> { let (mut entry, mut sub_index) = index.get(key, 0, log)?; while !entry.is_empty() { let address = entry.address(index.id.index_bits()); @@ -290,13 +290,13 @@ impl Column { address: Address, tables: TablesRef, log: &impl LogQuery, - ) -> Result> { + ) -> Result> { let size_tier = address.size_tier() as usize; - if let Some((value, compressed, _rc)) = + if let Some((value, compressed, rc)) = tables.tables[size_tier].query(&mut key, address.offset(), log)? { let value = if compressed { tables.compression.decompress(&value)? } else { value }; - return Ok(Some((size_tier as u8, value))) + return Ok(Some((size_tier as u8, rc, value))) } Ok(None) } diff --git a/src/db.rs b/src/db.rs index b74fc0ca..a5f44cbe 100644 --- a/src/db.rs +++ b/src/db.rs @@ -259,7 +259,7 @@ impl DbInner { } // Go into tables and log overlay. let log = self.log.overlays(); - column.get(&key, log) + Ok(column.get(&key, log)?.map(|(v, _rc)| v)) }, Column::Tree(column) => { let overlay = self.commit_overlay.read(); @@ -421,12 +421,17 @@ impl DbInner { } else if self.options.columns[col as usize].multitree { match &self.columns[col as usize] { Column::Hash(column) => match change { - Operation::Set(..) | - Operation::Dereference(..) | - Operation::Reference(..) => + Operation::Set(..) => return Err(Error::InvalidConfiguration( "Invalid operation for multitree column".to_string(), )), + Operation::Reference(..) => { + commit.indexed.entry(col).or_insert_with(|| IndexedChangeSet::new(col)).push( + change, + &self.options, + self.db_version, + )? + } Operation::InsertTree(..) => { let (root_data, node_values) = column.claim_tree_values(&change)?; @@ -445,18 +450,13 @@ impl DbInner { .push_node_change(node_change); } }, - Operation::RemoveTree(key) => { - let root_operation = Operation::Dereference(&key); - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push(root_operation, &self.options, self.db_version)?; - + Operation::RemoveTree(key) | Operation::Dereference(key) => { let value = self.get(col, &key)?; if let Some(data) = value { let root_data = unpack_node_data(data)?; let children = root_data.1; + let salt = self.options.salt.unwrap_or_default(); + let key = hash_key(&key, &salt, self.options.columns[col as usize].uniform, self.db_version); let node_change = NodeChange::DereferenceChildren(key, children); @@ -1459,7 +1459,7 @@ impl TreeReader for DbTreeReader { } else { // Go into tables and log overlay. let log = self.db.log.overlays(); - column.get(&self.key, log) + Ok(column.get(&self.key, log)?.map(|(v, _rc)| v)) }?; if let Some(data) = value { @@ -1655,7 +1655,7 @@ pub enum NodeChange { /// (address) IncrementReference(u64), /// Dereference and remove any of the children in the tree - DereferenceChildren(Vec, Children), + DereferenceChildren(Key, Children), } #[derive(Debug, Default)] @@ -1790,20 +1790,26 @@ impl IndexedChangeSet { column.write_address_inc_ref_plan(*address, writer)?; }, NodeChange::DereferenceChildren(key, children) => { - let tree = db.get_tree(db, col, key, false).unwrap(); - if let Some(tree) = tree { - //println!("Locking tree {:?}", &key[0..3]); - let guard = tree.write(); - let mut num_removed = 0; - //println!("Dereferencing tree {:?}", &key[0..3]); - self.write_dereference_children_plan( - column, - &guard, - children, - &mut num_removed, - writer, - )?; - //println!("Dereferenced tree {:?}, removed {}", &key[0..3], num_removed); + if let Some((_root, rc)) = column.get(key, writer)? { + column.write_plan(&Operation::Dereference(*key), writer)?; + log::debug!(target: "parity-db", "Dereferencing root, rc={}", rc); + if rc == 1 { + let tree = db.get_tree(db, col, key, false).unwrap(); + if let Some(tree) = tree { + //println!("Locking tree {:?}", &key[0..3]); + let guard = tree.write(); + let mut num_removed = 0; + //println!("Dereferencing tree {:?}", &key[0..3]); + self.write_dereference_children_plan( + column, + &guard, + children, + &mut num_removed, + writer, + )?; + log::debug!(target: "parity-db", "Dereferenced tree {:?}, removed {}", &key[0..3], num_removed); + } + } } // TODO: Remove TreeReader from Db. }, From 634a314e42fc25fbd724d550c8537e961e929821 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 11 Aug 2023 15:10:48 +0100 Subject: [PATCH 20/53] Correctly use full key or hash --- src/db.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/db.rs b/src/db.rs index a5f44cbe..af784b84 100644 --- a/src/db.rs +++ b/src/db.rs @@ -456,9 +456,9 @@ impl DbInner { let root_data = unpack_node_data(data)?; let children = root_data.1; let salt = self.options.salt.unwrap_or_default(); - let key = hash_key(&key, &salt, self.options.columns[col as usize].uniform, self.db_version); + let hash = hash_key(&key, &salt, self.options.columns[col as usize].uniform, self.db_version); - let node_change = NodeChange::DereferenceChildren(key, children); + let node_change = NodeChange::DereferenceChildren(key, hash, children); commit .indexed @@ -1655,7 +1655,7 @@ pub enum NodeChange { /// (address) IncrementReference(u64), /// Dereference and remove any of the children in the tree - DereferenceChildren(Key, Children), + DereferenceChildren(Vec, Key, Children), } #[derive(Debug, Default)] @@ -1789,9 +1789,9 @@ impl IndexedChangeSet { NodeChange::IncrementReference(address) => { column.write_address_inc_ref_plan(*address, writer)?; }, - NodeChange::DereferenceChildren(key, children) => { - if let Some((_root, rc)) = column.get(key, writer)? { - column.write_plan(&Operation::Dereference(*key), writer)?; + NodeChange::DereferenceChildren(key, hash, children) => { + if let Some((_root, rc)) = column.get(hash, writer)? { + column.write_plan(&Operation::Dereference(*hash), writer)?; log::debug!(target: "parity-db", "Dereferencing root, rc={}", rc); if rc == 1 { let tree = db.get_tree(db, col, key, false).unwrap(); From ee11d9f8720a726cf1de347dd3b4724f3b9c2694 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Sat, 19 Aug 2023 22:29:23 +0100 Subject: [PATCH 21/53] Safer entry claiming. Deal with tree removal while a commit is being built using that tree by deferring the removal. --- admin/src/lib.rs | 6 + admin/src/multitree_bench/mod.rs | 81 +++++++---- src/column.rs | 4 +- src/db.rs | 229 ++++++++++++++++++++++++++++--- src/options.rs | 4 + src/table.rs | 41 ++++-- 6 files changed, 310 insertions(+), 55 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index 2d97e50a..04f1da0e 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -141,6 +141,12 @@ pub fn run() -> Result<(), String> { for c in &mut db_options.columns { c.multitree = true; + if args.pruning > 0 { + c.ref_counted = true; + c.preimage = true; + } else { + c.append_only = true; + } } if args.compress { diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index c6f67f3f..7be75035 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -692,6 +692,7 @@ fn read_value( tree_index: u64, rng: &mut rand::rngs::SmallRng, db: &Db, + args: &Args, chain_generator: &ChainGenerator, ) -> Result<(), String> { let mut depth = 0; @@ -746,26 +747,35 @@ fn read_value( generated_children = gen_children; database_children = db_children; }, - None => return Err("Child address not in database".to_string()), + None => panic!("Child address not in database"), } } QUERIES.fetch_add(1, Ordering::SeqCst); }, None => { - // Is this expected? - let num_removed = NUM_REMOVED.load(Ordering::Relaxed); - if tree_index >= num_removed as u64 { - return Err("Tree root not in database".to_string()) + // Is this expected? If there are multiple writers then commits might happen out + // of order so this path can happen even when the tree hasn't been pruned. + if args.writers == 1 { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + panic!("Tree root not in database"); + } } }, } }, None => { - // Is this expected? - let num_removed = NUM_REMOVED.load(Ordering::Relaxed); - if tree_index >= num_removed as u64 { - return Err("Tree not in database".to_string()) + // Is this expected? If there are multiple writers then commits might happen out of + // order so this path can happen even when the tree hasn't been pruned. + if args.writers == 1 { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + panic!( + "Tree not in database during read (index: {}, removed: {})", + tree_index, num_removed + ); + } } }, } @@ -849,11 +859,6 @@ fn writer( if let NodeRef::New(node) = root_node_ref { let key: [u8; 32] = chain_generator.key(root_seed); - output_helper.write().println(format!( - "Commit tree {}, new: {}, existing: {}", - tree_index, num_new_nodes, num_existing_nodes - )); - commit.push((TREE_COLUMN, Operation::InsertTree(key.to_vec(), node))); commit.push(( @@ -862,13 +867,19 @@ fn writer( )); db.commit_changes(commit.drain(..)).unwrap(); - COMMITS.fetch_add(1, Ordering::Relaxed); - EXPECTED_NUM_ENTRIES.fetch_add(num_new_nodes as usize, Ordering::Relaxed); + + output_helper.write().println(format!( + "Commit tree {}, new: {}, existing: {}", + tree_index, num_new_nodes, num_existing_nodes + )); + + COMMITS.fetch_add(1, Ordering::SeqCst); + EXPECTED_NUM_ENTRIES.fetch_add(num_new_nodes as usize, Ordering::SeqCst); commit.clear(); // Immediately read and check a random value from the tree /* let mut rng = rand::rngs::SmallRng::seed_from_u64(seed + n as u64); - read_value(tree_index, &mut rng, &db, &chain_generator)?; */ + read_value(tree_index, &mut rng, &db, &args, &chain_generator)?; */ if args.pruning > 0 && !THREAD_PRUNING { try_prune(&db, &args, &chain_generator, &mut commit, &output_helper)?; @@ -921,7 +932,7 @@ fn try_prune( ), )); - NUM_REMOVED.fetch_add(1, Ordering::Relaxed); + NUM_REMOVED.fetch_add(1, Ordering::SeqCst); db.commit_changes(commit.drain(..)).unwrap(); commit.clear(); } @@ -966,7 +977,7 @@ fn reader( //let tree_index = rng.next_u64() % commits; let tree_index = (rng.next_u64() % (commits - num_removed)) + num_removed; - read_value(tree_index, &mut rng, &db, &chain_generator)?; + read_value(tree_index, &mut rng, &db, &args, &chain_generator)?; } Ok(()) @@ -1011,7 +1022,7 @@ fn iter_children<'a>( chain_generator, )?; }, - None => return Err("Child address not in database".to_string()), + None => panic!("Child address not in database"), } } @@ -1069,19 +1080,29 @@ fn iter( ITERATIONS.fetch_add(1, Ordering::SeqCst); }, None => { - // Is this expected? - let num_removed = NUM_REMOVED.load(Ordering::Relaxed); - if tree_index >= num_removed as u64 { - return Err("Tree root not in database".to_string()) + // Is this expected? If there are multiple writers then commits might happen + // out of order so this path can happen even when the tree hasn't been + // pruned. + if args.writers == 1 { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + panic!("Tree root not in database"); + } } }, } }, None => { - // Is this expected? - let num_removed = NUM_REMOVED.load(Ordering::Relaxed); - if tree_index >= num_removed as u64 { - return Err("Tree not in database".to_string()) + // Is this expected? If there are multiple writers then commits might happen out of + // order so this path can happen even when the tree hasn't been pruned. + if args.writers == 1 { + let num_removed = NUM_REMOVED.load(Ordering::Relaxed); + if tree_index >= num_removed as u64 { + panic!( + "Tree not in database during iterator (index: {}, removed: {})", + tree_index, num_removed + ); + } } }, } @@ -1231,7 +1252,7 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { iterations )); - if args.empty_on_shutdown { + if args.empty_on_shutdown && args.pruning > 0 { // Continue removing trees until they are all gone. TARGET_NUM_REMOVED.store(args.commits, Ordering::SeqCst); while NUM_REMOVED.load(Ordering::Relaxed) < args.commits { @@ -1250,7 +1271,7 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { t.join().unwrap()?; } - if args.empty_on_shutdown { + if args.empty_on_shutdown && args.pruning > 0 { output_helper.write().println_final(format!("Removed all entries")); } diff --git a/src/column.rs b/src/column.rs index 44724596..86c70331 100644 --- a/src/column.rs +++ b/src/column.rs @@ -932,7 +932,9 @@ impl HashColumn { let address = Address::from_u64(address); let target_tier = address.size_tier(); let offset = address.offset(); - tables.tables[target_tier as usize].write_inc_ref(offset, log)?; + + let exists = tables.tables[target_tier as usize].change_ref(offset, 1, log)?; + assert!(exists); let stats = self.collect_stats.then_some(&self.stats); if let Some(stats) = stats { diff --git a/src/db.rs b/src/db.rs index af784b84..c30ff736 100644 --- a/src/db.rs +++ b/src/db.rs @@ -30,14 +30,16 @@ use crate::{ log::{Log, LogAction}, multitree::{Children, NewNode, NodeAddress}, options::{Options, CURRENT_VERSION}, - parking_lot::{Condvar, Mutex, RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, + parking_lot::{ + Condvar, Mutex, MutexGuard, RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard, + }, stats::StatSummary, ColumnOptions, Key, }; use fs2::FileExt; use std::{ borrow::Borrow, - collections::{BTreeMap, HashMap, VecDeque}, + collections::{BTreeMap, HashMap, HashSet, VecDeque}, ops::Bound, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, @@ -137,6 +139,8 @@ struct CommitQueue { #[derive(Debug)] struct Trees { readers: HashMap>, IdentityBuildHasher>, + /// Number of queued dereferences for each tree + to_dereference: HashMap, } #[derive(Debug)] @@ -363,8 +367,10 @@ impl DbInner { let mut trees = RwLockUpgradableReadGuard::upgrade(trees); - let column_trees = - trees.entry(col).or_insert_with(|| Trees { readers: Default::default() }); + let column_trees = trees.entry(col).or_insert_with(|| Trees { + readers: Default::default(), + to_dereference: Default::default(), + }); let reader = Arc::new(RwLock::new(DbTreeReader { db: db.clone(), col, key: hash_key })); @@ -425,16 +431,41 @@ impl DbInner { return Err(Error::InvalidConfiguration( "Invalid operation for multitree column".to_string(), )), - Operation::Reference(..) => { - commit.indexed.entry(col).or_insert_with(|| IndexedChangeSet::new(col)).push( - change, - &self.options, - self.db_version, - )? - } + Operation::Reference(..) => commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(change, &self.options, self.db_version)?, Operation::InsertTree(..) => { let (root_data, node_values) = column.claim_tree_values(&change)?; + let trees = self.trees.read(); + if let Some(column_trees) = trees.get(&col) { + for (hash, count) in &column_trees.to_dereference { + assert!(*count > 0); + + // Check if TreeReader is active for this tree + let mut tree_active = false; + if let Some(reader) = column_trees.readers.get(hash) { + let reader = reader.upgrade(); + if let Some(reader) = reader { + if reader.is_locked() { + tree_active = true; + } + } + } + if tree_active { + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .used_trees + .insert(*hash); + } + } + } + drop(trees); + let root_operation = Operation::Set(change.key(), root_data); commit .indexed @@ -456,9 +487,25 @@ impl DbInner { let root_data = unpack_node_data(data)?; let children = root_data.1; let salt = self.options.salt.unwrap_or_default(); - let hash = hash_key(&key, &salt, self.options.columns[col as usize].uniform, self.db_version); + let hash = hash_key( + &key, + &salt, + self.options.columns[col as usize].uniform, + self.db_version, + ); + + let mut trees = self.trees.write(); + if let Some(column_trees) = trees.get_mut(&col) { + let count = + column_trees.to_dereference.get(&hash).unwrap_or(&0) + 1; + column_trees.to_dereference.insert(hash, count); + } + drop(trees); - let node_change = NodeChange::DereferenceChildren(key, hash, children); + commit.check_for_deferral = true; + + let node_change = + NodeChange::DereferenceChildren(key, hash, children); commit .indexed @@ -509,7 +556,7 @@ impl DbInner { let mut overlay = self.commit_overlay.write(); queue.record_id += 1; - let record_id = queue.record_id + 1; + let record_id = queue.record_id; let mut bytes = 0; for (c, indexed) in &commit.indexed { @@ -544,6 +591,72 @@ impl DbInner { Ok(()) } + fn defer_commit( + &self, + mut queue: MutexGuard, + mut commit: CommitChangeSet, + old_bytes: usize, + old_id: u64, + new_id: Option, + ) -> Result<()> { + let record_id = if let Some(id) = new_id { + id + } else { + queue.record_id += 1; + queue.record_id + }; + + let bytes = if record_id != old_id { + let mut overlay = self.commit_overlay.write(); + + let mut bytes = 0; + + for (c, indexed) in &commit.indexed { + indexed.copy_to_overlay( + &mut overlay[*c as usize], + record_id, + &mut bytes, + &self.options, + )?; + } + + for (c, iterset) in &commit.btree_indexed { + iterset.copy_to_overlay( + &mut overlay[*c as usize].btree_indexed, + record_id, + &mut bytes, + &self.options, + )?; + } + + { + // Cleanup the commit overlay with old id. + for (c, key_values) in commit.indexed.iter() { + key_values.clean_overlay(&mut overlay[*c as usize], old_id); + } + for (c, iterset) in commit.btree_indexed.iter_mut() { + iterset.clean_overlay(&mut overlay[*c as usize].btree_indexed, old_id); + } + } + + bytes + } else { + old_bytes + }; + + let commit = Commit { id: record_id, changeset: commit, bytes }; + + log::debug!( + target: "parity-db", + "Deferred commit, old id: {}, new id: {}", + old_id, + record_id, + ); + queue.commits.push_back(commit); + queue.bytes += bytes; + Ok(()) + } + fn process_commits(&self, db: &Arc) -> Result { #[cfg(any(test, feature = "instrumentation"))] let might_wait_because_the_queue_is_full = self.options.with_background_thread; @@ -584,6 +697,79 @@ impl DbInner { }; if let Some(mut commit) = commit { + if commit.changeset.check_for_deferral { + let mut defer = false; + 'outer: for (col, key_values) in commit.changeset.indexed.iter() { + for change in &key_values.node_changes { + if let NodeChange::DereferenceChildren(_key, hash, _children) = change { + // Check if there are currently any locks on the tree. Will need to + // defer if there are. + let trees = self.trees.read(); + if let Some(column_trees) = trees.get(&col) { + let mut tree_active = false; + if let Some(reader) = column_trees.readers.get(hash) { + let reader = reader.upgrade(); + if let Some(reader) = reader { + if reader.is_locked() { + tree_active = true; + } + } + } + if tree_active { + defer = true; + break 'outer + } + } + drop(trees); + + // Also check if there are any later commits in the queue that use this + // tree. Will need to defer if there are. + let queue = self.commit_queue.lock(); + for commit in &queue.commits { + for (_col, change_set) in &commit.changeset.indexed { + for tree in &change_set.used_trees { + if tree == hash { + defer = true; + break 'outer + } + } + } + } + } + } + } + if defer { + let queue = self.commit_queue.lock(); + let new_id = if queue.commits.len() > 0 { + // Generate a new id + None + } else { + // Nothing else in the queue so can reuse same id + Some(commit.id) + }; + self.defer_commit(queue, commit.changeset, commit.bytes, commit.id, new_id)?; + + return Ok(true) + } else { + for (col, key_values) in commit.changeset.indexed.iter() { + for change in &key_values.node_changes { + if let NodeChange::DereferenceChildren(_key, hash, _children) = change { + let mut trees = self.trees.write(); + if let Some(column_trees) = trees.get_mut(&col) { + let count = column_trees.to_dereference.get(hash).unwrap_or(&0); + assert!(*count > 0); + if *count == 1 { + column_trees.to_dereference.remove(hash); + } else { + column_trees.to_dereference.insert(*hash, count - 1); + } + } + } + } + } + } + } + let mut reindex = false; let mut writer = self.log.begin_record(); log::debug!( @@ -1148,7 +1334,11 @@ impl Db { self.inner.get_root(col, key) } - pub fn get_node(&self, col: ColId, node_address: NodeAddress) -> Result, Children)>> { + pub fn get_node( + &self, + col: ColId, + node_address: NodeAddress, + ) -> Result, Children)>> { self.inner.get_node(col, node_address) } @@ -1662,6 +1852,7 @@ pub enum NodeChange { pub struct CommitChangeSet { pub indexed: HashMap, pub btree_indexed: HashMap, + pub check_for_deferral: bool, } #[derive(Debug)] @@ -1669,11 +1860,17 @@ pub struct IndexedChangeSet { pub col: ColId, pub changes: Vec>, pub node_changes: Vec, + pub used_trees: HashSet, } impl IndexedChangeSet { pub fn new(col: ColId) -> Self { - IndexedChangeSet { col, changes: Default::default(), node_changes: Default::default() } + IndexedChangeSet { + col, + changes: Default::default(), + node_changes: Default::default(), + used_trees: Default::default(), + } } fn push>( diff --git a/src/options.rs b/src/options.rs index 00427302..de534e4d 100644 --- a/src/options.rs +++ b/src/options.rs @@ -102,6 +102,10 @@ impl ColumnOptions { log::error!(target: "parity-db", "Using `ref_counted` option without `preimage` enabled is not supported"); return false } + if self.ref_counted && self.append_only { + log::error!(target: "parity-db", "`ref_counted` option is redundant when `append_only` is enabled"); + return false + } if self.multitree && self.compression != CompressionType::NoCompression { log::error!(target: "parity-db", "Compression is not currently supported with multitree columns"); return false diff --git a/src/table.rs b/src/table.rs index 52d1e0e7..a8995267 100644 --- a/src/table.rs +++ b/src/table.rs @@ -447,7 +447,7 @@ impl ValueTable { dirty_header: AtomicBool::new(false), free_entries, multipart, - ref_counted: options.ref_counted || options.multitree, + ref_counted: options.ref_counted || (options.multitree && !options.append_only), db_version, }) } @@ -700,6 +700,12 @@ impl ValueTable { } pub fn next_free(&self, log: &mut LogWriter) -> Result { + let free_entries_guard = if let Some(free_entries) = &self.free_entries { + Some(free_entries.write()) + } else { + None + }; + let filled = self.filled.load(Ordering::Relaxed); let last_removed = self.last_removed.load(Ordering::Relaxed); let index = if last_removed != 0 { @@ -711,8 +717,7 @@ impl ValueTable { last_removed, ); self.last_removed.store(next_removed, Ordering::Relaxed); - if let Some(free_entries) = &self.free_entries { - let mut free_entries = free_entries.write(); + if let Some(mut free_entries) = free_entries_guard { let last = free_entries.stack.pop().unwrap(); assert_eq!(last, last_removed); free_entries.ordered.remove(&last_removed); @@ -735,11 +740,11 @@ impl ValueTable { pub fn claim_next_free(&self) -> Result { match &self.free_entries { Some(free_entries) => { + let mut free_entries = free_entries.write(); + let filled = self.filled.load(Ordering::Relaxed); let last_removed = self.last_removed.load(Ordering::Relaxed); let index = if last_removed != 0 { - let mut free_entries = free_entries.write(); - let last = free_entries.stack.pop().unwrap(); assert_eq!(last, last_removed); free_entries.ordered.remove(&last_removed); @@ -877,6 +882,12 @@ impl ValueTable { } fn clear_slot(&self, index: u64, log: &mut LogWriter) -> Result<()> { + let free_entries_guard = if let Some(free_entries) = &self.free_entries { + Some(free_entries.write()) + } else { + None + }; + let last_removed = self.last_removed.load(Ordering::Relaxed); log::trace!( target: "parity-db", @@ -893,8 +904,7 @@ impl ValueTable { self.last_removed.store(index, Ordering::Relaxed); self.dirty_header.store(true, Ordering::Relaxed); - if let Some(free_entries) = &self.free_entries { - let mut free_entries = free_entries.write(); + if let Some(mut free_entries) = free_entries_guard { free_entries.stack.push(index); free_entries.ordered.insert(index); } @@ -1066,6 +1076,11 @@ impl ValueTable { if self.file.file.read().is_none() { return Ok(()) } + let _free_entries_guard = if let Some(free_entries) = &self.free_entries { + Some(free_entries.write()) + } else { + None + }; let mut header = Header::default(); self.file.read_at(&mut header.0, 0)?; let last_removed = header.last_removed(); @@ -1079,6 +1094,11 @@ impl ValueTable { } pub fn complete_plan(&self, log: &mut LogWriter) -> Result<()> { + let _free_entries_guard = if let Some(free_entries) = &self.free_entries { + Some(free_entries.write()) + } else { + None + }; if let Ok(true) = self.dirty_header .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) @@ -1167,6 +1187,11 @@ impl ValueTable { /// Validate free records sequence. pub fn check_free_refs(&self) -> Result { + let _free_entries_guard = if let Some(free_entries) = &self.free_entries { + Some(free_entries.read()) + } else { + None + }; let filled = self.filled.load(Ordering::Relaxed); let mut next = self.last_removed.load(Ordering::Relaxed); let mut len = 0; @@ -1188,8 +1213,8 @@ impl ValueTable { pub fn get_num_entries(&self) -> Result { if let Some(free_entries) = &self.free_entries { - let filled = self.filled.load(Ordering::Relaxed); let free_entries = free_entries.read(); + let filled = self.filled.load(Ordering::Relaxed); let num_free = free_entries.stack.len(); let num = (filled - 1) - num_free as u64; if num > 0 && self.multipart { From 06b96e22c97722092d02f32d0457bccb19c6929f Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 25 Aug 2023 13:04:10 +0100 Subject: [PATCH 22/53] Separate tree operations --- admin/src/multitree_bench/mod.rs | 2 +- src/btree/mod.rs | 8 ++++-- src/column.rs | 12 +++++--- src/db.rs | 47 ++++++++++++++++++++++---------- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 7be75035..41dfff29 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -923,7 +923,7 @@ fn try_prune( output_helper.write().println(format!("Remove tree {}", tree_index)); - commit.push((TREE_COLUMN, Operation::RemoveTree(key.to_vec()))); + commit.push((TREE_COLUMN, Operation::DereferenceTree(key.to_vec()))); commit.push(( INFO_COLUMN, Operation::Set( diff --git a/src/btree/mod.rs b/src/btree/mod.rs index c113d915..74b6732d 100644 --- a/src/btree/mod.rs +++ b/src/btree/mod.rs @@ -389,7 +389,9 @@ pub mod commit_overlay { Operation::Set(k, v) => Operation::Set(k.into(), v.into()), Operation::Dereference(k) => Operation::Dereference(k.into()), Operation::Reference(k) => Operation::Reference(k.into()), - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => return Err(Error::InvalidInput(format!( "Invalid operation for column {}", self.col @@ -432,7 +434,9 @@ pub mod commit_overlay { ))) } }, - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => return Err(Error::InvalidInput(format!( "Invalid operation for column {}", self.col diff --git a/src/column.rs b/src/column.rs index 86c70331..52fa7e0b 100644 --- a/src/column.rs +++ b/src/column.rs @@ -638,7 +638,9 @@ impl HashColumn { } Ok(PlanOutcome::Skipped) }, - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => Err(Error::InvalidConfiguration("Unsupported operation on hash column".into())), } } @@ -881,9 +883,9 @@ impl HashColumn { return Ok((data, node_values)) }, - Operation::RemoveTree(_key) => + Operation::ReferenceTree(..) | Operation::DereferenceTree(..) => return Err(Error::InvalidInput(format!( - "claim_tree_values should not be called with RemoveTree" + "claim_tree_values should not be called from ReferenceTree or DereferenceTree" ))), _ => return Err(Error::InvalidInput(format!( @@ -1510,7 +1512,9 @@ impl Column { Ok((Some(PlanOutcome::Written), None)) } }, - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => Err(Error::InvalidInput(format!("Invalid operation for column {}", tables.col))), } } diff --git a/src/db.rs b/src/db.rs index c30ff736..a153a38e 100644 --- a/src/db.rs +++ b/src/db.rs @@ -427,15 +427,12 @@ impl DbInner { } else if self.options.columns[col as usize].multitree { match &self.columns[col as usize] { Column::Hash(column) => match change { - Operation::Set(..) => + Operation::Set(..) | + Operation::Reference(..) | + Operation::Dereference(..) => return Err(Error::InvalidConfiguration( "Invalid operation for multitree column".to_string(), )), - Operation::Reference(..) => commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push(change, &self.options, self.db_version)?, Operation::InsertTree(..) => { let (root_data, node_values) = column.claim_tree_values(&change)?; @@ -481,7 +478,15 @@ impl DbInner { .push_node_change(node_change); } }, - Operation::RemoveTree(key) | Operation::Dereference(key) => { + Operation::ReferenceTree(..) => { + let root_operation = Operation::Reference(change.key()); + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(root_operation, &self.options, self.db_version)?; + }, + Operation::DereferenceTree(key) => { let value = self.get(col, &key)?; if let Some(data) = value { let root_data = unpack_node_data(data)?; @@ -1788,8 +1793,12 @@ pub enum Operation { /// Insert a new tree into a MultiTree column using root key and node structure. InsertTree(Key, NewNode), - /// Remove an existing tree (at root Key) from a MultiTree column. - RemoveTree(Key), + /// Increment the reference count of a tree (at root Key) from a MultiTree column. + ReferenceTree(Key), + + /// Dereference an existing tree (at root Key) from a MultiTree column, resulting in either + /// removal of the tree or decrement of its reference count. + DereferenceTree(Key), } impl PartialOrd for Operation { @@ -1811,7 +1820,8 @@ impl Operation { Operation::Dereference(k) | Operation::Reference(k) | Operation::InsertTree(k, _) | - Operation::RemoveTree(k) => k, + Operation::ReferenceTree(k) | + Operation::DereferenceTree(k) => k, } } @@ -1821,7 +1831,8 @@ impl Operation { Operation::Dereference(k) | Operation::Reference(k) | Operation::InsertTree(k, _) | - Operation::RemoveTree(k) => k, + Operation::ReferenceTree(k) | + Operation::DereferenceTree(k) => k, } } } @@ -1833,7 +1844,8 @@ impl, Value> Operation { Operation::Dereference(k) => Operation::Dereference(k.as_ref().to_vec()), Operation::Reference(k) => Operation::Reference(k.as_ref().to_vec()), Operation::InsertTree(k, n) => Operation::InsertTree(k.as_ref().to_vec(), n), - Operation::RemoveTree(k) => Operation::RemoveTree(k.as_ref().to_vec()), + Operation::ReferenceTree(k) => Operation::ReferenceTree(k.as_ref().to_vec()), + Operation::DereferenceTree(k) => Operation::DereferenceTree(k.as_ref().to_vec()), } } } @@ -1888,7 +1900,9 @@ impl IndexedChangeSet { Operation::Set(k, v) => Operation::Set(hash_key(k.as_ref()), v.into()), Operation::Dereference(k) => Operation::Dereference(hash_key(k.as_ref())), Operation::Reference(k) => Operation::Reference(hash_key(k.as_ref())), - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => return Err(Error::InvalidInput(format!( "Invalid operation for column {}", self.col @@ -1934,7 +1948,9 @@ impl IndexedChangeSet { return Err(Error::InvalidInput(format!("No Rc for column {}", self.col))) } }, - Operation::InsertTree(..) | Operation::RemoveTree(..) => + Operation::InsertTree(..) | + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => return Err(Error::InvalidInput(format!( "Invalid operation for column {}", self.col @@ -2058,7 +2074,8 @@ impl IndexedChangeSet { }, Operation::Reference(..) | Operation::InsertTree(..) | - Operation::RemoveTree(..) => (), + Operation::ReferenceTree(..) | + Operation::DereferenceTree(..) => (), } } for change in self.node_changes.iter() { From b04121dcc123a12f14bd9de69887a8863abe34e5 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 25 Aug 2023 17:37:53 +0100 Subject: [PATCH 23/53] Added various checks for correct usage --- src/db.rs | 217 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 127 insertions(+), 90 deletions(-) diff --git a/src/db.rs b/src/db.rs index a153a38e..a5c6e1de 100644 --- a/src/db.rs +++ b/src/db.rs @@ -252,7 +252,12 @@ impl DbInner { }) } - fn get(&self, col: ColId, key: &[u8]) -> Result> { + fn get(&self, col: ColId, key: &[u8], external_call: bool) -> Result> { + if self.options.columns[col as usize].multitree && external_call { + return Err(Error::InvalidConfiguration( + "get not supported for multitree columns.".to_string(), + )) + } match &self.columns[col as usize] { Column::Hash(column) => { let key = column.hash_key(key); @@ -278,6 +283,11 @@ impl DbInner { } fn get_size(&self, col: ColId, key: &[u8]) -> Result> { + if self.options.columns[col as usize].multitree { + return Err(Error::InvalidConfiguration( + "get_size not supported for multitree columns.".to_string(), + )) + } match &self.columns[col as usize] { Column::Hash(column) => { let key = column.hash_key(key); @@ -303,7 +313,15 @@ impl DbInner { } fn get_root(&self, col: ColId, key: &[u8]) -> Result, Children)>> { - let value = self.get(col, key)?; + if !self.options.columns[col as usize].multitree { + return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) + } + if !self.options.columns[col as usize].append_only { + return Err(Error::InvalidConfiguration( + "get_root can only be called on a column with append_only option.".to_string(), + )) + } + let value = self.get(col, key, false)?; if let Some(data) = value { return Ok(Some(unpack_node_data(data)?)) } @@ -314,7 +332,16 @@ impl DbInner { &self, col: ColId, node_address: NodeAddress, + external_call: bool, ) -> Result, Children)>> { + if !self.options.columns[col as usize].multitree { + return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) + } + if !self.options.columns[col as usize].append_only && external_call { + return Err(Error::InvalidConfiguration( + "get_node can only be called on a column with append_only option.".to_string(), + )) + } match &self.columns[col as usize] { Column::Hash(column) => { let overlay = self.commit_overlay.read(); @@ -341,12 +368,15 @@ impl DbInner { key: &[u8], check_existence: bool, ) -> Result>>> { + if !self.options.columns[col as usize].multitree { + return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) + } match &self.columns[col as usize] { Column::Hash(column) => { // Check if the tree actually exists. We can't return the data from this function as // TreeReader is not locked. That is done by the client. if check_existence { - let root = self.get(col, key).unwrap(); + let root = self.get(col, key, false).unwrap(); if root.is_none() { return Ok(None) } @@ -426,104 +456,111 @@ impl DbInner { .push(change)? } else if self.options.columns[col as usize].multitree { match &self.columns[col as usize] { - Column::Hash(column) => match change { - Operation::Set(..) | - Operation::Reference(..) | - Operation::Dereference(..) => - return Err(Error::InvalidConfiguration( - "Invalid operation for multitree column".to_string(), - )), - Operation::InsertTree(..) => { - let (root_data, node_values) = column.claim_tree_values(&change)?; - - let trees = self.trees.read(); - if let Some(column_trees) = trees.get(&col) { - for (hash, count) in &column_trees.to_dereference { - assert!(*count > 0); - - // Check if TreeReader is active for this tree - let mut tree_active = false; - if let Some(reader) = column_trees.readers.get(hash) { - let reader = reader.upgrade(); - if let Some(reader) = reader { - if reader.is_locked() { - tree_active = true; + Column::Hash(column) => + match change { + Operation::Set(..) | + Operation::Reference(..) | + Operation::Dereference(..) => + return Err(Error::InvalidConfiguration( + "Invalid operation for multitree column".to_string(), + )), + Operation::InsertTree(..) => { + let (root_data, node_values) = column.claim_tree_values(&change)?; + + let trees = self.trees.read(); + if let Some(column_trees) = trees.get(&col) { + for (hash, count) in &column_trees.to_dereference { + assert!(*count > 0); + + // Check if TreeReader is active for this tree + let mut tree_active = false; + if let Some(reader) = column_trees.readers.get(hash) { + let reader = reader.upgrade(); + if let Some(reader) = reader { + if reader.is_locked() { + tree_active = true; + } } } - } - if tree_active { - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .used_trees - .insert(*hash); + if tree_active { + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .used_trees + .insert(*hash); + } } } - } - drop(trees); - - let root_operation = Operation::Set(change.key(), root_data); - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push(root_operation, &self.options, self.db_version)?; + drop(trees); - for node_change in node_values { + let root_operation = Operation::Set(change.key(), root_data); commit .indexed .entry(col) .or_insert_with(|| IndexedChangeSet::new(col)) - .push_node_change(node_change); - } - }, - Operation::ReferenceTree(..) => { - let root_operation = Operation::Reference(change.key()); - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push(root_operation, &self.options, self.db_version)?; - }, - Operation::DereferenceTree(key) => { - let value = self.get(col, &key)?; - if let Some(data) = value { - let root_data = unpack_node_data(data)?; - let children = root_data.1; - let salt = self.options.salt.unwrap_or_default(); - let hash = hash_key( - &key, - &salt, - self.options.columns[col as usize].uniform, - self.db_version, - ); - - let mut trees = self.trees.write(); - if let Some(column_trees) = trees.get_mut(&col) { - let count = - column_trees.to_dereference.get(&hash).unwrap_or(&0) + 1; - column_trees.to_dereference.insert(hash, count); + .push(root_operation, &self.options, self.db_version)?; + + for node_change in node_values { + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push_node_change(node_change); } - drop(trees); + }, + Operation::ReferenceTree(..) => { + if !self.options.columns[col as usize].append_only { + let root_operation = Operation::Reference(change.key()); + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push(root_operation, &self.options, self.db_version)?; + } + }, + Operation::DereferenceTree(key) => { + if self.options.columns[col as usize].append_only { + return Err(Error::InvalidConfiguration("Attempting to dereference a tree from an append_only column.".to_string())) + } + let value = self.get(col, &key, false)?; + if let Some(data) = value { + let root_data = unpack_node_data(data)?; + let children = root_data.1; + let salt = self.options.salt.unwrap_or_default(); + let hash = hash_key( + &key, + &salt, + self.options.columns[col as usize].uniform, + self.db_version, + ); + + let mut trees = self.trees.write(); + if let Some(column_trees) = trees.get_mut(&col) { + let count = + column_trees.to_dereference.get(&hash).unwrap_or(&0) + + 1; + column_trees.to_dereference.insert(hash, count); + } + drop(trees); - commit.check_for_deferral = true; + commit.check_for_deferral = true; - let node_change = - NodeChange::DereferenceChildren(key, hash, children); + let node_change = + NodeChange::DereferenceChildren(key, hash, children); - commit - .indexed - .entry(col) - .or_insert_with(|| IndexedChangeSet::new(col)) - .push_node_change(node_change); - } else { - return Err(Error::InvalidConfiguration( - "No entry for tree root".to_string(), - )) - } + commit + .indexed + .entry(col) + .or_insert_with(|| IndexedChangeSet::new(col)) + .push_node_change(node_change); + } else { + return Err(Error::InvalidConfiguration( + "No entry for tree root".to_string(), + )) + } + }, }, - }, Column::Tree(_) => return Err(Error::InvalidConfiguration("Not a HashColumn".to_string())), } @@ -1317,7 +1354,7 @@ impl Db { /// Get a value in a specified column by key. Returns `None` if the key does not exist. pub fn get(&self, col: ColId, key: &[u8]) -> Result> { - self.inner.get(col, key) + self.inner.get(col, key, true) } /// Get value size by key. Returns `None` if the key does not exist. @@ -1344,7 +1381,7 @@ impl Db { col: ColId, node_address: NodeAddress, ) -> Result, Children)>> { - self.inner.get_node(col, node_address) + self.inner.get_node(col, node_address, true) } /// Commit a set of changes to the database. @@ -1669,7 +1706,7 @@ impl TreeReader for DbTreeReader { } fn get_node(&self, node_address: NodeAddress) -> Result, Children)>> { - self.db.get_node(self.col, node_address) + self.db.get_node(self.col, node_address, false) } } From 1d734160a654748b0ac394e44912e91683ab9995 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 28 Sep 2023 13:12:22 +0100 Subject: [PATCH 24/53] Reference count tables --- src/column.rs | 480 ++++++++++++++++++++++++++++++----- src/db.rs | 84 ++++++- src/index.rs | 4 +- src/lib.rs | 1 + src/log.rs | 143 ++++++++++- src/ref_count.rs | 635 +++++++++++++++++++++++++++++++++++++++++++++++ src/table.rs | 50 +++- 7 files changed, 1325 insertions(+), 72 deletions(-) create mode 100644 src/ref_count.rs diff --git a/src/column.rs b/src/column.rs index 52fa7e0b..cf0cfe8d 100644 --- a/src/column.rs +++ b/src/column.rs @@ -12,6 +12,7 @@ use crate::{ multitree::{Children, NewNode, NodeAddress, NodeRef}, options::{ColumnOptions, Metadata, Options, DEFAULT_COMPRESSION_THRESHOLD}, parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, + ref_count::{RefCountTable, RefCountTableId}, stats::{ColumnStatSummary, ColumnStats}, table::{ key::{TableKey, TableKeyQuery}, @@ -29,6 +30,7 @@ use std::{ }; const MIN_INDEX_BITS: u8 = 16; +const MIN_REF_COUNT_BITS: u8 = 11; // Measured in index entries const MAX_REINDEX_BATCH: usize = 8192; @@ -76,11 +78,18 @@ const SIZES: [u16; SIZE_TIERS - 1] = [ struct Tables { index: IndexTable, value: Vec, + ref_count: RefCountTable, +} + +#[derive(Debug)] +enum ReindexEntry { + Index(IndexTable), + RefCount(RefCountTable), } #[derive(Debug)] struct Reindex { - queue: VecDeque, + queue: VecDeque, progress: AtomicU64, } @@ -198,6 +207,9 @@ pub fn hash_key(key: &[u8], salt: &Salt, uniform: bool, db_version: u32) -> Key pub struct ReindexBatch { pub drop_index: Option, pub batch: Vec<(Key, Address)>, + pub drop_ref_count: Option, + pub ref_count_batch: Vec<(Address, u64)>, + pub ref_count_batch_source: Option, } impl HashColumn { @@ -210,12 +222,14 @@ impl HashColumn { } return Ok(Some((value, rc))) } - for r in &self.reindex.read().queue { - if let Some((tier, rc, value)) = self.get_in_index(key, r, values, log)? { - if self.collect_stats { - self.stats.query_hit(tier); + for entry in &self.reindex.read().queue { + if let ReindexEntry::Index(r) = entry { + if let Some((tier, rc, value)) = self.get_in_index(key, r, values, log)? { + if self.collect_stats { + self.stats.query_hit(tier); + } + return Ok(Some((value, rc))) } - return Ok(Some((value, rc))) } } if self.collect_stats { @@ -364,7 +378,8 @@ impl Column { let entry = try_io!(entry); if let Some(file) = entry.path().file_name().and_then(|f| f.to_str()) { if crate::index::TableId::is_file_name(column, file) || - crate::table::TableId::is_file_name(column, file) + crate::table::TableId::is_file_name(column, file) || + crate::ref_count::RefCountTableId::is_file_name(column, file) { to_delete.push(PathBuf::from(file)); } @@ -416,14 +431,15 @@ impl HashColumn { options: &Options, metadata: &Metadata, ) -> Result { - let (index, reindexing, stats) = Self::open_index(&options.path, col)?; + let (index, mut reindexing, stats) = Self::open_index(&options.path, col)?; + let ref_count = Self::open_ref_count(&options.path, col, &mut reindexing)?; let collect_stats = options.stats; let path = &options.path; let col_options = &metadata.columns[col as usize]; let db_version = metadata.version; Ok(HashColumn { col, - tables: RwLock::new(Tables { index, value }), + tables: RwLock::new(Tables { index, value, ref_count }), reindex: RwLock::new(Reindex { queue: reindexing, progress: AtomicU64::new(0) }), path: path.into(), preimage: col_options.preimage, @@ -455,13 +471,14 @@ impl HashColumn { for t in tables.value.iter() { t.flush()?; } + tables.ref_count.flush()?; Ok(()) } fn open_index( path: &std::path::Path, col: ColId, - ) -> Result<(IndexTable, VecDeque, ColumnStats)> { + ) -> Result<(IndexTable, VecDeque, ColumnStats)> { let mut reindexing = VecDeque::new(); let mut top = None; let mut stats = ColumnStats::empty(); @@ -474,7 +491,7 @@ impl HashColumn { top = Some(table); } else { log::trace!(target: "parity-db", "Opened stale index {}", table.id); - reindexing.push_front(table); + reindexing.push_front(ReindexEntry::Index(table)); } } } @@ -485,6 +502,31 @@ impl HashColumn { Ok((table, reindexing, stats)) } + fn open_ref_count( + path: &std::path::Path, + col: ColId, + reindexing: &mut VecDeque, + ) -> Result { + let mut top = None; + for bits in (MIN_REF_COUNT_BITS..65).rev() { + let id = RefCountTableId::new(col, bits); + if let Some(table) = RefCountTable::open_existing(path, id)? { + if top.is_none() { + log::trace!(target: "parity-db", "Opened main ref count {}", table.id); + top = Some(table); + } else { + log::trace!(target: "parity-db", "Opened stale ref count {}", table.id); + reindexing.push_front(ReindexEntry::RefCount(table)); + } + } + } + let table = match top { + Some(table) => table, + None => RefCountTable::create_new(path, RefCountTableId::new(col, MIN_REF_COUNT_BITS)), + }; + Ok(table) + } + fn trigger_reindex<'a, 'b>( tables: RwLockUpgradableReadGuard<'a, Tables>, reindex: RwLockUpgradableReadGuard<'b, Reindex>, @@ -502,7 +544,7 @@ impl HashColumn { IndexTableId::new(tables.index.id.col(), tables.index.id.index_bits() + 1); let new_table = IndexTable::create_new(path, new_index_id); let old_table = std::mem::replace(&mut tables.index, new_table); - reindex.queue.push_back(old_table); + reindex.queue.push_back(ReindexEntry::Index(old_table)); ( RwLockWriteGuard::downgrade_to_upgradable(tables), RwLockWriteGuard::downgrade_to_upgradable(reindex), @@ -599,9 +641,11 @@ impl HashColumn { } // Check old indexes // TODO: don't search if index precedes reindex progress - for index in &reindex.queue { - if let Some(r) = Self::search_index(key, index, tables, log)? { - return Ok(Some(r)) + for entry in &reindex.queue { + if let ReindexEntry::Index(index) = entry { + if let Some(r) = Self::search_index(key, index, tables, log)? { + return Ok(Some(r)) + } } } Ok(None) @@ -716,6 +760,173 @@ impl HashColumn { Ok((outcome, tables, reindex)) } + fn trigger_ref_count_reindex<'a, 'b>( + tables: RwLockUpgradableReadGuard<'a, Tables>, + reindex: RwLockUpgradableReadGuard<'b, Reindex>, + path: &std::path::Path, + ) -> (RwLockUpgradableReadGuard<'a, Tables>, RwLockUpgradableReadGuard<'b, Reindex>) { + let mut tables = RwLockUpgradableReadGuard::upgrade(tables); + let mut reindex = RwLockUpgradableReadGuard::upgrade(reindex); + log::info!( + target: "parity-db", + "Started reindex for ref count {}", + tables.ref_count.id, + ); + // Start reindex + let new_id = + RefCountTableId::new(tables.ref_count.id.col(), tables.ref_count.id.index_bits() + 1); + let new_table = RefCountTable::create_new(path, new_id); + let old_table = std::mem::replace(&mut tables.ref_count, new_table); + reindex.queue.push_back(ReindexEntry::RefCount(old_table)); + ( + RwLockWriteGuard::downgrade_to_upgradable(tables), + RwLockWriteGuard::downgrade_to_upgradable(reindex), + ) + } + + pub fn write_ref_count_reindex_plan( + &self, + address: Address, + ref_count: u64, + source: RefCountTableId, + log: &mut LogWriter, + ) -> Result { + let tables = self.tables.upgradable_read(); + let reindex = self.reindex.upgradable_read(); + self.write_ref_count_reindex_plan_locked(tables, reindex, address, ref_count, source, log) + } + + fn write_ref_count_reindex_plan_locked( + &self, + mut tables: RwLockUpgradableReadGuard, + mut reindex: RwLockUpgradableReadGuard, + address: Address, + ref_count: u64, + source: RefCountTableId, + log: &mut LogWriter, + ) -> Result { + if let Some((_ref_count, _sub_index)) = tables.ref_count.get(address, log)? { + log::trace!(target: "parity-db", "{}: Skipped ref count reindex entry {} when reindexing", tables.ref_count.id, address); + return Ok(PlanOutcome::Skipped) + } + // An intermediate reindex table might contain a more recent value for the ref count so need to check for this and skip. + for entry in reindex.queue.iter().rev() { + if let ReindexEntry::RefCount(ref_count_table) = entry { + if ref_count_table.id == source { + break + } + if let Some(_r) = Self::search_ref_count(address, ref_count_table, log)? { + log::trace!(target: "parity-db", "{}: Skipped ref count reindex entry {} when reindexing", ref_count_table.id, address); + return Ok(PlanOutcome::Skipped) + } + } + } + let mut outcome = PlanOutcome::Written; + while let PlanOutcome::NeedReindex = + tables.ref_count.write_insert_plan(address, ref_count, None, log)? + { + log::debug!(target: "parity-db", "{}: Ref count chunk full {} when reindexing", tables.ref_count.id, address); + (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + outcome = PlanOutcome::NeedReindex; + } + Ok(outcome) + } + + fn search_ref_count<'a>( + address: Address, + ref_count_table: &'a RefCountTable, + log: &LogWriter, + ) -> Result> { + if let Some((ref_count, sub_index)) = ref_count_table.get(address, log)? { + return Ok(Some((ref_count_table, sub_index, ref_count))) + } + Ok(None) + } + + fn search_all_ref_count<'a>( + address: Address, + tables: &'a Tables, + reindex: &'a Reindex, + log: &LogWriter, + ) -> Result> { + if let Some(r) = Self::search_ref_count(address, &tables.ref_count, log)? { + return Ok(Some(r)) + } + // Check old tables + // TODO: don't search if table precedes reindex progress + for entry in reindex.queue.iter().rev() { + if let ReindexEntry::RefCount(ref_count_table) = entry { + if let Some(r) = Self::search_ref_count(address, ref_count_table, log)? { + return Ok(Some(r)) + } + } + } + Ok(None) + } + + fn write_ref_count_plan_existing<'a>( + &self, + tables: &Tables, + reindex: &'a Reindex, + change: (Address, Option), + log: &mut LogWriter, + ref_count_table: &RefCountTable, + sub_index: usize, + ) -> Result { + let (address, ref_count) = change; + if let Some(ref_count) = ref_count { + // Replacing + assert!(ref_count_table.id == tables.ref_count.id); + tables.ref_count.write_insert_plan(address, ref_count, Some(sub_index), log) + } else { + // Removing + let result = ref_count_table.write_remove_plan(address, sub_index, log); + // Need to remove from all old tables in reindex otherwise it will appear that this entry still exists and it might get reintroduced during reindex. + { + if ref_count_table.id != tables.ref_count.id { + if let Some((table, sub_index, _ref_count)) = Self::search_ref_count(address, &tables.ref_count, log)? { + table.write_remove_plan(address, sub_index, log)?; + } + } + for entry in &reindex.queue { + if let ReindexEntry::RefCount(table) = entry { + if table.id != ref_count_table.id { + if let Some((table, sub_index, _ref_count)) = Self::search_ref_count(address, table, log)? { + table.write_remove_plan(address, sub_index, log)?; + } + } + } + } + } + result + } + } + + fn write_ref_count_plan_new<'a, 'b>( + &self, + mut tables: RwLockUpgradableReadGuard<'a, Tables>, + mut reindex: RwLockUpgradableReadGuard<'b, Reindex>, + address: Address, + ref_count: u64, + log: &mut LogWriter, + ) -> Result<( + PlanOutcome, + RwLockUpgradableReadGuard<'a, Tables>, + RwLockUpgradableReadGuard<'b, Reindex>, + )> { + let mut outcome = PlanOutcome::Written; + while let PlanOutcome::NeedReindex = + tables.ref_count.write_insert_plan(address, ref_count, None, log)? + { + log::debug!(target: "parity-db", "{}: Ref count chunk full {}", tables.ref_count.id, address); + (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + outcome = PlanOutcome::NeedReindex; + } + let (test_ref_count, _test_sub_index) = tables.ref_count.get(address, log)?.unwrap(); + assert!(test_ref_count == ref_count); + Ok((outcome, tables, reindex)) + } + fn prepare_children( &self, children: &Vec, @@ -930,20 +1141,43 @@ impl HashColumn { log: &mut LogWriter, ) -> Result { let tables = self.tables.upgradable_read(); - let tables = self.as_ref(&tables.value); let address = Address::from_u64(address); - let target_tier = address.size_tier(); - let offset = address.offset(); - - let exists = tables.tables[target_tier as usize].change_ref(offset, 1, log)?; - assert!(exists); - - let stats = self.collect_stats.then_some(&self.stats); - if let Some(stats) = stats { - stats.reference_increase(); + let table_ref_count = { + let tables = self.as_ref(&tables.value); + let target_tier = address.size_tier(); + let offset = address.offset(); + let (exists, ref_count) = tables.tables[target_tier as usize].change_ref_return(offset, 1, log)?; + assert!(exists); + ref_count + }; + let reindex = self.reindex.upgradable_read(); + let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; + if let Some((table, sub_index, ref_count)) = existing { + assert!(ref_count > 1); + let new_ref_count = ref_count + 1; + if table_ref_count as u64 != new_ref_count { + log::info!(target: "parity-db", "Ref count mismatch, value: {}, {}: {}", table_ref_count, table.id, new_ref_count); + for entry in reindex.queue.iter().rev() { + if let ReindexEntry::RefCount(ref_count_table) = entry { + if let Some(r) = Self::search_ref_count(address, ref_count_table, log)? { + log::info!(target: "parity-db", "Ref count mismatch, value: {}, {}: {}", table_ref_count, r.0.id, r.2); + } + } + } + } + assert!(table_ref_count as u64 == new_ref_count); + if table.id == tables.ref_count.id { + self.write_ref_count_plan_existing(&tables, &reindex, (address, Some(new_ref_count)), log, table, sub_index) + } else { + let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, new_ref_count, log)?; + Ok(r) + } + } else { + // inc ref is only called on addresses that already exist, so we know they must have only 1 reference. + assert!(table_ref_count == 2); + let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, 2, log)?; + Ok(r) } - - Ok(PlanOutcome::Written) } pub fn write_address_dec_ref_plan( @@ -952,13 +1186,44 @@ impl HashColumn { log: &mut LogWriter, ) -> Result<(bool, PlanOutcome)> { let tables = self.tables.upgradable_read(); - let tables = self.as_ref(&tables.value); let address = Address::from_u64(address); - let target_tier = address.size_tier(); - let offset = address.offset(); - let remains = tables.tables[target_tier as usize].write_dec_ref(offset, log)?; - - Ok((remains, PlanOutcome::Written)) + let (value_table_remains, table_ref_count) = { + let tables = self.as_ref(&tables.value); + let target_tier = address.size_tier(); + let offset = address.offset(); + tables.tables[target_tier as usize].change_ref_return(offset, -1, log)? + }; + let reindex = self.reindex.upgradable_read(); + let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; + if let Some((table, sub_index, ref_count)) = existing { + assert!(ref_count > 1); + let new_ref_count = ref_count - 1; + assert!(table_ref_count as u64 == new_ref_count); + assert!(value_table_remains); + let new_ref_count = if new_ref_count > 1 { + Some(new_ref_count) + } else { + None + }; + let outcome = if new_ref_count.is_some() && table.id != tables.ref_count.id { + let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, new_ref_count.unwrap(), log)?; + r + } else { + self.write_ref_count_plan_existing(&tables, &reindex, (address, new_ref_count), log, table, sub_index)? + }; + Ok((true, outcome)) + } else { + // dec ref is only called on addresses that already exist, so we know they must have only 1 reference. + assert!(table_ref_count == 0); + assert!(!value_table_remains); + { + let tables = self.as_ref(&tables.value); + let target_tier = address.size_tier(); + let offset = address.offset(); + tables.tables[target_tier as usize].write_remove_plan(offset, log)?; + } + Ok((false, PlanOutcome::Written)) + } } pub fn enact_plan(&self, action: LogAction, log: &mut LogReader) -> Result<()> { @@ -968,10 +1233,10 @@ impl HashColumn { LogAction::InsertIndex(record) => { if tables.index.id == record.table { tables.index.enact_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().find(|r| r.id == record.table) { + } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { table.enact_plan(record.index, log)?; } else { - // This may happen when removal is planed for an old index when reindexing. + // This may happen when removal is planned for an old index when reindexing. // We can safely skip the removal since the new index does not have the entry // anyway and the old index is already dropped. log::debug!( @@ -985,6 +1250,23 @@ impl HashColumn { LogAction::InsertValue(record) => { tables.value[record.table.size_tier() as usize].enact_plan(record.index, log)?; }, + LogAction::InsertRefCount(record) => { + if tables.ref_count.id == record.table { + tables.ref_count.enact_plan(record.index, log)?; + } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + table.enact_plan(record.index, log)?; + } else { + // This may happen when removal is planned for an old ref count when reindexing. + // We can safely skip the removal since the new ref count does not have the entry + // anyway and the old ref count is already dropped. + log::debug!( + target: "parity-db", + "Missing ref count {}. Skipped", + record.table, + ); + RefCountTable::skip_plan(log)?; + } + }, // This should never happen, unless something has modified the log file while the // database is running. Existing logs should be validated with `validate_plan` on // startup. @@ -1000,7 +1282,7 @@ impl HashColumn { LogAction::InsertIndex(record) => { if tables.index.id == record.table { tables.index.validate_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().find(|r| r.id == record.table) { + } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { table.validate_plan(record.index, log)?; } else { if record.table.index_bits() < tables.index.id.index_bits() { @@ -1023,6 +1305,29 @@ impl HashColumn { LogAction::InsertValue(record) => { tables.value[record.table.size_tier() as usize].validate_plan(record.index, log)?; }, + LogAction::InsertRefCount(record) => { + if tables.ref_count.id == record.table { + tables.ref_count.validate_plan(record.index, log)?; + } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + table.validate_plan(record.index, log)?; + } else { + if record.table.index_bits() < tables.ref_count.id.index_bits() { + // Insertion into a previously dropped ref count. + log::warn!( target: "parity-db", "Ref count {} is too old. Current is {}", record.table, tables.ref_count.id); + return Err(Error::Corruption("Unexpected log ref count id".to_string())) + } + // Re-launch previously started reindex + // TODO: add explicit log records for reindexing events. + log::warn!( + target: "parity-db", + "Missing ref count {}, starting reindex", + record.table, + ); + let lock = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + std::mem::drop(lock); + return self.validate_plan(LogAction::InsertRefCount(record), log) + } + }, _ => { log::error!(target: "parity-db", "Unexpected log action"); return Err(Error::Corruption("Unexpected log action".to_string())) @@ -1345,45 +1650,80 @@ impl HashColumn { let reindex = self.reindex.read(); let mut plan = Vec::new(); let mut drop_index = None; + let mut ref_count_plan = Vec::new(); + let mut ref_count_source = None; + let mut drop_ref_count = None; if let Some(source) = reindex.queue.front() { let progress = reindex.progress.load(Ordering::Relaxed); - if progress != source.id.total_chunks() { - let mut source_index = progress; - if source_index % 500 == 0 { - log::debug!(target: "parity-db", "{}: Reindexing at {}/{}", tables.index.id, source_index, source.id.total_chunks()); - } - log::debug!(target: "parity-db", "{}: Continue reindex at {}/{}", tables.index.id, source_index, source.id.total_chunks()); - while source_index < source.id.total_chunks() && plan.len() < MAX_REINDEX_BATCH { - log::trace!(target: "parity-db", "{}: Reindexing {}", source.id, source_index); - let entries = source.entries(source_index, log.overlays())?; - for entry in entries.iter() { - if entry.is_empty() { - continue + match source { + ReindexEntry::Index(source) => { + if progress != source.id.total_chunks() { + let mut source_index = progress; + if source_index % 500 == 0 { + log::debug!(target: "parity-db", "{}: Reindexing at {}/{}", tables.index.id, source_index, source.id.total_chunks()); + } + log::debug!(target: "parity-db", "{}: Continue reindex at {}/{}", tables.index.id, source_index, source.id.total_chunks()); + while source_index < source.id.total_chunks() && plan.len() < MAX_REINDEX_BATCH { + log::trace!(target: "parity-db", "{}: Reindexing {}", source.id, source_index); + let entries = source.entries(source_index, log.overlays())?; + for entry in entries.iter() { + if entry.is_empty() { + continue + } + // We only need key prefix to reindex. + let key = source.recover_key_prefix(source_index, *entry); + plan.push((key, entry.address(source.id.index_bits()))) + } + source_index += 1; + } + log::trace!(target: "parity-db", "{}: End reindex batch {} ({})", tables.index.id, source_index, plan.len()); + reindex.progress.store(source_index, Ordering::Relaxed); + if source_index == source.id.total_chunks() { + log::info!(target: "parity-db", "Completed reindex {} into {}", source.id, tables.index.id); + drop_index = Some(source.id); } - // We only need key prefix to reindex. - let key = source.recover_key_prefix(source_index, *entry); - plan.push((key, entry.address(source.id.index_bits()))) } - source_index += 1; - } - log::trace!(target: "parity-db", "{}: End reindex batch {} ({})", tables.index.id, source_index, plan.len()); - reindex.progress.store(source_index, Ordering::Relaxed); - if source_index == source.id.total_chunks() { - log::info!(target: "parity-db", "Completed reindex {} into {}", source.id, tables.index.id); - drop_index = Some(source.id); + }, + ReindexEntry::RefCount(source) => { + if progress != source.id.total_chunks() { + let mut source_index = progress; + if source_index % 500 == 0 { + log::debug!(target: "parity-db", "{}: Reindexing ref count at {}/{}", tables.ref_count.id, source_index, source.id.total_chunks()); + } + ref_count_source = Some(source.id); + log::debug!(target: "parity-db", "{}: Continue reindex ref count at {}/{}", tables.ref_count.id, source_index, source.id.total_chunks()); + while source_index < source.id.total_chunks() && ref_count_plan.len() < MAX_REINDEX_BATCH { + log::trace!(target: "parity-db", "{}: Reindexing ref count {}", source.id, source_index); + let entries = source.entries(source_index, log.overlays())?; + for entry in entries.iter() { + if entry.is_empty() { + continue + } + ref_count_plan.push((entry.address(), entry.ref_count())); + } + source_index += 1; + } + log::trace!(target: "parity-db", "{}: End reindex ref count batch {} ({})", tables.ref_count.id, source_index, ref_count_plan.len()); + reindex.progress.store(source_index, Ordering::Relaxed); + if source_index == source.id.total_chunks() { + log::info!(target: "parity-db", "Completed reindex ref count {} into {}", source.id, tables.ref_count.id); + drop_ref_count = Some(source.id); + } + } } } } - Ok(ReindexBatch { drop_index, batch: plan }) + Ok(ReindexBatch { drop_index, batch: plan, drop_ref_count, ref_count_batch: ref_count_plan, ref_count_batch_source: ref_count_source }) } pub fn drop_index(&self, id: IndexTableId) -> Result<()> { log::debug!(target: "parity-db", "Dropping {}", id); let mut reindex = self.reindex.write(); - if reindex.queue.front_mut().map_or(false, |index| index.id == id) { - let table = reindex.queue.pop_front(); + if reindex.queue.front_mut().map_or(false, |e| if let ReindexEntry::Index(t) = e { t.id == id } else { false }) { reindex.progress.store(0, Ordering::Relaxed); - table.unwrap().drop_file()?; + let table = reindex.queue.pop_front().unwrap(); + let table = if let ReindexEntry::Index(table) = table { table } else { return Err(Error::Corruption(format!("Incorrect reindex type"))) }; + table.drop_file()?; } else { log::warn!(target: "parity-db", "Dropping invalid index {}", id); return Ok(()) @@ -1392,6 +1732,22 @@ impl HashColumn { Ok(()) } + pub fn drop_ref_count(&self, id: RefCountTableId) -> Result<()> { + log::debug!(target: "parity-db", "Dropping ref count {}", id); + let mut reindex = self.reindex.write(); + if reindex.queue.front_mut().map_or(false, |e| if let ReindexEntry::RefCount(t) = e { t.id == id } else { false }) { + reindex.progress.store(0, Ordering::Relaxed); + let table = reindex.queue.pop_front().unwrap(); + let table = if let ReindexEntry::RefCount(table) = table { table } else { return Err(Error::Corruption(format!("Incorrect reindex type"))) }; + table.drop_file()?; + } else { + log::warn!(target: "parity-db", "Dropping invalid ref count {}", id); + return Ok(()) + } + log::debug!(target: "parity-db", "Dropped ref count {}", id); + Ok(()) + } + pub fn get_num_value_entries(&self) -> Result { let tables = self.tables.read(); let mut num_entries = 0; diff --git a/src/db.rs b/src/db.rs index a5c6e1de..d2039753 100644 --- a/src/db.rs +++ b/src/db.rs @@ -902,8 +902,9 @@ impl DbInner { // Process any pending reindexes for column in self.columns.iter() { let column = if let Column::Hash(c) = column { c } else { continue }; - let ReindexBatch { drop_index, batch } = column.reindex(&self.log)?; + let ReindexBatch { drop_index, batch, drop_ref_count, ref_count_batch, ref_count_batch_source } = column.reindex(&self.log)?; if !batch.is_empty() || drop_index.is_some() { + assert!(ref_count_batch.is_empty() && ref_count_batch_source.is_none() && drop_ref_count.is_none()); let mut next_reindex = false; let mut writer = self.log.begin_record(); log::debug!( @@ -939,6 +940,45 @@ impl DbInner { self.flush_worker_wait.signal(); return Ok(true) } + if !ref_count_batch.is_empty() || drop_ref_count.is_some() { + assert!(batch.is_empty() && drop_index.is_none()); + assert!(ref_count_batch_source.is_some()); + let ref_count_source = ref_count_batch_source.unwrap(); + let mut next_reindex = false; + let mut writer = self.log.begin_record(); + log::debug!( + target: "parity-db", + "Creating ref count reindex record {}", + writer.record_id(), + ); + for (address, ref_count) in ref_count_batch.into_iter() { + if let PlanOutcome::NeedReindex = + column.write_ref_count_reindex_plan(address, ref_count, ref_count_source, &mut writer)? + { + next_reindex = true + } + } + if let Some(table) = drop_ref_count { + writer.drop_ref_count_table(table); + } + let record_id = writer.record_id(); + let l = writer.drain(); + + let mut logged_bytes = self.log_queue_wait.work.lock(); + let bytes = self.log.end_record(l)?; + log::debug!( + target: "parity-db", + "Created ref count reindex record {}, {} bytes", + record_id, + bytes, + ); + *logged_bytes += bytes as i64; + if next_reindex { + self.start_reindex(record_id); + } + self.flush_worker_wait.signal(); + return Ok(true) + } } self.next_reindex.store(0, Ordering::SeqCst); Ok(false) @@ -1024,7 +1064,24 @@ impl DbInner { return Ok(false) } }, - LogAction::DropTable(_) => continue, + LogAction::InsertRefCount(insertion) => { + let col = insertion.table.col() as usize; + if let Err(e) = self.columns.get(col).map_or_else( + || Err(Error::Corruption(format!("Invalid column id {col}"))), + |col| { + col.validate_plan( + LogAction::InsertRefCount(insertion), + &mut reader, + ) + }, + ) { + log::warn!(target: "parity-db", "Error validating log: {:?}.", e); + drop(reader); + self.log.clear_replay_logs(); + return Ok(false) + } + }, + LogAction::DropTable(_) | LogAction::DropRefCountTable(_) => continue, } } reader.reset()?; @@ -1043,6 +1100,10 @@ impl DbInner { self.columns[insertion.table.col() as usize] .enact_plan(LogAction::InsertValue(insertion), &mut reader)?; }, + LogAction::InsertRefCount(insertion) => { + self.columns[insertion.table.col() as usize] + .enact_plan(LogAction::InsertRefCount(insertion), &mut reader)?; + }, LogAction::DropTable(id) => { log::debug!( target: "parity-db", @@ -1058,6 +1119,21 @@ impl DbInner { Column::Tree(_) => (), } }, + LogAction::DropRefCountTable(id) => { + log::debug!( + target: "parity-db", + "Dropping ref count {}", + id, + ); + match &self.columns[id.col() as usize] { + Column::Hash(col) => { + col.drop_ref_count(id)?; + // Check if there's another reindex on the next iteration + self.start_reindex(reader.record_id()); + }, + Column::Tree(_) => (), + } + }, } } log::debug!( @@ -2037,7 +2113,9 @@ impl IndexedChangeSet { )?; }, NodeChange::IncrementReference(address) => { - column.write_address_inc_ref_plan(*address, writer)?; + if let PlanOutcome::NeedReindex = column.write_address_inc_ref_plan(*address, writer)? { + *reindex = true; + } }, NodeChange::DereferenceChildren(key, hash, children) => { if let Some((_root, rc)) = column.get(hash, writer)? { diff --git a/src/index.rs b/src/index.rs index c8fb2875..ec3427d7 100644 --- a/src/index.rs +++ b/src/index.rs @@ -607,8 +607,10 @@ impl IndexTable { } pub fn drop_file(self) -> Result<()> { + if self.map.read().is_some() { + try_io!(std::fs::remove_file(self.path.as_path())); + } drop(self.map); - try_io!(std::fs::remove_file(self.path.as_path())); log::debug!(target: "parity-db", "{}: Dropped table", self.id); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index cb9f06a7..d736806a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ mod options; mod parking_lot; mod stats; mod table; +mod ref_count; pub use btree::BTreeIterator; pub use column::{ColId, ValueIterState}; diff --git a/src/log.rs b/src/log.rs index 19e54ba9..989957c1 100644 --- a/src/log.rs +++ b/src/log.rs @@ -4,6 +4,7 @@ use crate::{ column::ColId, error::{try_io, Error, Result}, + ref_count::{Chunk as RefCountChunk, RefCountTableId, ENTRY_BYTES as REF_COUNT_ENTRY_BYTES}, index::{Chunk as IndexChunk, TableId as IndexTableId, ENTRY_BYTES}, options::Options, parking_lot::{RwLock, RwLockWriteGuard}, @@ -21,8 +22,10 @@ const MAX_LOG_POOL_SIZE: usize = 16; const BEGIN_RECORD: u8 = 1; const INSERT_INDEX: u8 = 2; const INSERT_VALUE: u8 = 3; -const END_RECORD: u8 = 4; -const DROP_TABLE: u8 = 5; +const INSERT_REF_COUNT: u8 = 4; +const END_RECORD: u8 = 5; +const DROP_TABLE: u8 = 6; +const DROP_REF_COUNT_TABLE: u8 = 7; #[derive(Debug)] pub struct InsertIndexAction { @@ -36,12 +39,20 @@ pub struct InsertValueAction { pub index: u64, } +#[derive(Debug)] +pub struct InsertRefCountAction { + pub table: RefCountTableId, + pub index: u64, +} + #[derive(Debug)] pub enum LogAction { BeginRecord, InsertIndex(InsertIndexAction), InsertValue(InsertValueAction), + InsertRefCount(InsertRefCountAction), DropTable(IndexTableId), + DropRefCountTable(RefCountTableId), EndRecord, } @@ -53,12 +64,19 @@ pub trait LogQuery { f: F, ) -> Option; fn value(&self, table: ValueTableId, index: u64, dest: &mut [u8]) -> bool; + fn ref_count R>( + &self, + table: RefCountTableId, + index: u64, + f: F, + ) -> Option; } #[derive(Default, Debug)] pub struct LogOverlays { index: HashMap, value: HashMap, + ref_count: HashMap, last_record_id: HashMap, } @@ -81,6 +99,15 @@ impl LogQuery for RwLock { fn value(&self, table: ValueTableId, index: u64, dest: &mut [u8]) -> bool { self.read().value(table, index, dest) } + + fn ref_count R>( + &self, + table: RefCountTableId, + index: u64, + f: F, + ) -> Option { + self.read().ref_count(table, index, f) + } } impl LogQuery for LogOverlays { @@ -106,12 +133,24 @@ impl LogQuery for LogOverlays { false } } + + fn ref_count R>( + &self, + table: RefCountTableId, + index: u64, + f: F, + ) -> Option { + self.ref_count + .get(&table) + .and_then(|o| o.map.get(&index).map(|(_id, _mask, data)| f(data))) + } } #[derive(Debug, Default)] pub struct Cleared { index: Vec<(IndexTableId, u64)>, values: Vec<(ValueTableId, u64)>, + ref_count: Vec<(RefCountTableId, u64)>, } #[derive(Debug)] @@ -191,6 +230,15 @@ impl<'a> LogReader<'a> { self.cleared.values.push((table, index)); Ok(LogAction::InsertValue(InsertValueAction { table, index })) }, + INSERT_REF_COUNT => { + read_buf(2, &mut buf)?; + let table = + RefCountTableId::from_u16(u16::from_le_bytes(buf[0..2].try_into().unwrap())); + read_buf(8, &mut buf)?; + let index = u64::from_le_bytes(buf); + self.cleared.ref_count.push((table, index)); + Ok(LogAction::InsertRefCount(InsertRefCountAction { table, index })) + }, END_RECORD => { try_io!(self.reading.as_mut().unwrap().file.read_exact(&mut buf[0..4])); self.read_bytes += 4; @@ -216,6 +264,12 @@ impl<'a> LogReader<'a> { IndexTableId::from_u16(u16::from_le_bytes(buf[0..2].try_into().unwrap())); Ok(LogAction::DropTable(table)) }, + DROP_REF_COUNT_TABLE => { + read_buf(2, &mut buf)?; + let table = + RefCountTableId::from_u16(u16::from_le_bytes(buf[0..2].try_into().unwrap())); + Ok(LogAction::DropRefCountTable(table)) + }, _ => Err(Error::Corruption("Bad log entry type".into())), } } @@ -242,8 +296,10 @@ impl<'a> LogReader<'a> { pub struct LogChange { local_index: HashMap, local_values: HashMap, + local_ref_count: HashMap, record_id: u64, dropped_tables: Vec, + dropped_ref_count_tables: Vec, } impl LogChange { @@ -251,7 +307,9 @@ impl LogChange { LogChange { local_index: Default::default(), local_values: Default::default(), + local_ref_count: Default::default(), dropped_tables: Default::default(), + dropped_ref_count_tables: Default::default(), record_id, } } @@ -296,17 +354,36 @@ impl LogChange { write(value)?; } } + for (id, overlay) in self.local_ref_count.iter() { + for (index, (_, modified_entries_mask, chunk)) in overlay.map.iter() { + write(INSERT_REF_COUNT.to_le_bytes().as_ref())?; + write(&id.as_u16().to_le_bytes())?; + write(&index.to_le_bytes())?; + write(&modified_entries_mask.to_le_bytes())?; + let mut mask = *modified_entries_mask; + while mask != 0 { + let i = mask.trailing_zeros(); + mask &= !(1 << i); + write(&chunk[i as usize * REF_COUNT_ENTRY_BYTES..(i as usize + 1) * REF_COUNT_ENTRY_BYTES])?; + } + } + } for id in self.dropped_tables.iter() { log::debug!(target: "parity-db", "Finalizing drop {}", id); write(DROP_TABLE.to_le_bytes().as_ref())?; write(&id.as_u16().to_le_bytes())?; } + for id in self.dropped_ref_count_tables.iter() { + log::debug!(target: "parity-db", "Finalizing ref count drop {}", id); + write(DROP_REF_COUNT_TABLE.to_le_bytes().as_ref())?; + write(&id.as_u16().to_le_bytes())?; + } write(&END_RECORD.to_le_bytes())?; let checksum: u32 = crc32.finalize(); try_io!(file.write_all(&checksum.to_le_bytes())); bytes += 4; try_io!(file.flush()); - Ok(FlushedLog { index: self.local_index, values: self.local_values, bytes }) + Ok(FlushedLog { index: self.local_index, values: self.local_values, ref_count: self.local_ref_count, bytes }) } } @@ -314,6 +391,7 @@ impl LogChange { struct FlushedLog { index: HashMap, values: HashMap, + ref_count: HashMap, bytes: u64, } @@ -352,10 +430,25 @@ impl<'a> LogWriter<'a> { .insert(index, (self.log.record_id, data)); } + pub fn insert_ref_count(&mut self, table: RefCountTableId, index: u64, sub: u8, data: &RefCountChunk) { + match self.log.local_ref_count.entry(table).or_default().map.entry(index) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + *entry.get_mut() = (self.log.record_id, entry.get().1 | (1 << sub), *data); + }, + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert((self.log.record_id, 1 << sub, *data)); + }, + } + } + pub fn drop_table(&mut self, id: IndexTableId) { self.log.dropped_tables.push(id); } + pub fn drop_ref_count_table(&mut self, id: RefCountTableId) { + self.log.dropped_ref_count_tables.push(id); + } + pub fn drain(self) -> LogChange { self.log } @@ -393,6 +486,23 @@ impl<'a> LogQuery for LogWriter<'a> { self.overlays.value(table, index, dest) } } + + fn ref_count R>( + &self, + table: RefCountTableId, + index: u64, + f: F, + ) -> Option { + match self + .log + .local_ref_count + .get(&table) + .and_then(|o| o.map.get(&index).map(|(_id, _mask, data)| data)) + { + Some(data) => Some(f(data)), + None => self.overlays.ref_count(table, index, f), + } + } } // Identity hash. @@ -450,6 +560,11 @@ pub struct ValueLogOverlay { pub map: HashMap), BuildIdHash>, // index -> (record_id, entry) } +#[derive(Debug, Default)] +pub struct RefCountLogOverlay { + pub map: HashMap, // index -> (record_id, modified_mask, entry) +} + #[derive(Debug)] struct Appending { id: u32, @@ -577,6 +692,7 @@ impl Log { let mut overlays = self.overlays.write(); overlays.index.clear(); overlays.value.clear(); + overlays.ref_count.clear(); overlays.last_record_id.clear(); self.dirty.store(false, Ordering::Relaxed); } @@ -610,7 +726,7 @@ impl Log { *appending = Some(Appending { size: 0, file: std::io::BufWriter::new(file), id }); } let appending = appending.as_mut().unwrap(); - let FlushedLog { index, values, bytes } = log.flush_to_file(&mut appending.file)?; + let FlushedLog { index, values, ref_count, bytes } = log.flush_to_file(&mut appending.file)?; let mut overlays = self.overlays.write(); let mut total_index = 0; for (id, overlay) in index.into_iter() { @@ -623,13 +739,19 @@ impl Log { overlays.last_record_id.insert(id.col(), record_id); overlays.value.entry(id).or_default().map.extend(overlay.map.into_iter()); } + let mut total_ref_count = 0; + for (id, overlay) in ref_count.into_iter() { + total_ref_count += overlay.map.len(); + overlays.ref_count.entry(id).or_default().map.extend(overlay.map.into_iter()); + } log::debug!( target: "parity-db", - "Finalizing log record {} ({} index, {} value)", + "Finalizing log record {} ({} index, {} value, {} ref count)", record_id, total_index, total_value, + total_ref_count, ); appending.size += bytes; self.dirty.store(true, Ordering::Relaxed); @@ -659,8 +781,19 @@ impl Log { } } } + for (table, index) in cleared.ref_count.into_iter() { + if let Some(ref mut overlay) = overlays.ref_count.get_mut(&table) { + if let std::collections::hash_map::Entry::Occupied(e) = overlay.map.entry(index) { + if e.get().0 == record_id { + e.remove_entry(); + } + } + } + } // Cleanup index overlays overlays.index.retain(|_, overlay| !overlay.map.is_empty()); + // Cleanup ref count overlays + overlays.ref_count.retain(|_, overlay| !overlay.map.is_empty()); } pub fn flush_one(&self, min_size: u64) -> Result { diff --git a/src/ref_count.rs b/src/ref_count.rs new file mode 100644 index 00000000..95af3876 --- /dev/null +++ b/src/ref_count.rs @@ -0,0 +1,635 @@ +// Copyright 2021-2022 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or MIT. + +use crate::{ + column::ColId, + error::{try_io, Error, Result}, + index::{Address, PlanOutcome}, + log::{LogQuery, LogReader, LogWriter}, + parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, +}; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::convert::TryInto; + +const CHUNK_LEN: usize = CHUNK_ENTRIES * ENTRY_BYTES; +const CHUNK_ENTRIES: usize = 1 << CHUNK_ENTRIES_BITS; +const CHUNK_ENTRIES_BITS: u8 = 5; +const META_SIZE: usize = 0; +const ENTRY_BITS: u8 = 128; +pub const ENTRY_BYTES: usize = ENTRY_BITS as usize / 8; + +const EMPTY_CHUNK: Chunk = [0u8; CHUNK_LEN]; + +pub type Chunk = [u8; CHUNK_LEN]; + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Entry(u64, u64); + +impl Entry { + #[inline] + fn new(address: Address, ref_count: u64) -> Entry { + Entry(address.as_u64(), ref_count) + } + + #[inline] + pub fn address(&self) -> Address { + Address::from_u64(self.0) + } + + #[inline] + pub fn ref_count(&self) -> u64 { + self.1 + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.0 == 0 + } + + pub fn as_u128(&self) -> u128 { + self.0 as u128 | (self.1 as u128) << 64 + } + + fn empty() -> Self { + Entry(0, 0) + } + + fn from_u128(e: u128) -> Self { + Entry((e & u64::MAX as u128) as u64, (e >> 64) as u64) + } +} + +#[derive(Debug)] +pub struct RefCountTable { + pub id: RefCountTableId, + map: RwLock>, + path: std::path::PathBuf, +} + +fn total_entries(index_bits: u8) -> u64 { + total_chunks(index_bits) * CHUNK_ENTRIES as u64 +} + +fn total_chunks(index_bits: u8) -> u64 { + 1u64 << index_bits +} + +fn file_size(index_bits: u8) -> u64 { + total_entries(index_bits) * ENTRY_BYTES as u64 + META_SIZE as u64 +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub struct RefCountTableId(u16); + +impl RefCountTableId { + pub fn new(col: ColId, index_bits: u8) -> RefCountTableId { + RefCountTableId(((col as u16) << 8) | (index_bits as u16)) + } + + pub fn from_u16(id: u16) -> RefCountTableId { + RefCountTableId(id) + } + + pub fn col(&self) -> ColId { + (self.0 >> 8) as ColId + } + + pub fn index_bits(&self) -> u8 { + (self.0 & 0xff) as u8 + } + + pub fn file_name(&self) -> String { + format!("refcount_{:02}_{}", self.col(), self.index_bits()) + } + + pub fn is_file_name(col: ColId, name: &str) -> bool { + name.starts_with(&format!("refcount_{col:02}_")) + } + + pub fn as_u16(&self) -> u16 { + self.0 + } + + pub fn total_chunks(&self) -> u64 { + total_chunks(self.index_bits()) + } +} + +impl std::fmt::Display for RefCountTableId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "rc{:02}-{:02}", self.col(), self.index_bits()) + } +} + +impl RefCountTable { + pub fn open_existing(path: &std::path::Path, id: RefCountTableId) -> Result> { + let mut path: std::path::PathBuf = path.into(); + path.push(id.file_name()); + + let file = match std::fs::OpenOptions::new().read(true).write(true).open(path.as_path()) { + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(e) => return Err(Error::Io(e)), + Ok(file) => file, + }; + + try_io!(file.set_len(file_size(id.index_bits()))); + let map = try_io!(unsafe { memmap2::MmapMut::map_mut(&file) }); + log::debug!(target: "parity-db", "Opened existing refcount table {}", id); + Ok(Some(RefCountTable { id, path, map: RwLock::new(Some(map)) })) + } + + pub fn create_new(path: &std::path::Path, id: RefCountTableId) -> RefCountTable { + let mut path: std::path::PathBuf = path.into(); + path.push(id.file_name()); + RefCountTable { id, path, map: RwLock::new(None) } + } + + fn chunk_at(index: u64, map: &memmap2::MmapMut) -> Result<&[u8; CHUNK_LEN]> { + let offset = META_SIZE + index as usize * CHUNK_LEN; + let ptr = unsafe { &*(map[offset..offset + CHUNK_LEN].as_ptr() as *const [u8; CHUNK_LEN]) }; + Ok(try_io!(Ok(ptr))) + } + + fn find_entry( + &self, + address: u64, + chunk: &[u8; CHUNK_LEN], + ) -> Option<(Entry, usize)> { + self.find_entry_base(address, chunk) + } + + fn find_entry_base( + &self, + address: u64, + chunk: &[u8; CHUNK_LEN], + ) -> Option<(Entry, usize)> { + for i in 0..CHUNK_ENTRIES { + let entry = Self::read_entry(chunk, i); + if entry.address().as_u64() == address && !entry.is_empty() { + return Some((entry, i)) + } + } + None + } + + pub fn get(&self, address: Address, log: &impl LogQuery) -> Result> { + log::trace!(target: "parity-db", "{}: Querying ref count {}", self.id, address); + let chunk_index = self.chunk_index(address); + + if let Some(entry) = log.ref_count(self.id, chunk_index, |chunk| { + log::trace!(target: "parity-db", "{}: Querying ref count overlay at {}", self.id, chunk_index); + self.find_entry(address.as_u64(), chunk) + }) { + return Ok(entry.map(|(e, sub_index)| (e.ref_count(), sub_index))) + } + + if let Some(map) = &*self.map.read() { + log::trace!(target: "parity-db", "{}: Querying ref count chunk at {}", self.id, chunk_index); + let chunk = Self::chunk_at(chunk_index, map)?; + return Ok(self.find_entry(address.as_u64(), chunk).map(|(e, sub_index)| (e.ref_count(), sub_index))) + } + Ok(None) + } + + pub fn entries(&self, chunk_index: u64, log: &impl LogQuery) -> Result<[Entry; CHUNK_ENTRIES]> { + let mut chunk = [0; CHUNK_LEN]; + if let Some(entry) = + log.ref_count(self.id, chunk_index, |chunk| Self::transmute_chunk(*chunk)) + { + return Ok(entry) + } + if let Some(map) = &*self.map.read() { + let source = Self::chunk_at(chunk_index, map)?; + chunk.copy_from_slice(source); + return Ok(Self::transmute_chunk(chunk)) + } + Ok(Self::transmute_chunk(EMPTY_CHUNK)) + } + + #[inline(always)] + fn transmute_chunk(chunk: [u8; CHUNK_LEN]) -> [Entry; CHUNK_ENTRIES] { + let mut result: [Entry; CHUNK_ENTRIES] = unsafe { std::mem::transmute(chunk) }; + if !cfg!(target_endian = "little") { + for item in result.iter_mut() { + // TODO: Confirm this is correct + *item = Entry::from_u128(u128::from_le(item.as_u128())); + } + } + result + } + + #[inline(always)] + fn write_entry(entry: &Entry, at: usize, chunk: &mut [u8; CHUNK_LEN]) { + chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].copy_from_slice(&entry.as_u128().to_le_bytes()); + } + + #[inline(always)] + fn read_entry(chunk: &[u8; CHUNK_LEN], at: usize) -> Entry { + Entry::from_u128(u128::from_le_bytes(chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].try_into().unwrap())) + } + + #[inline(always)] + fn chunk_index(&self, address: Address) -> u64 { + use std::hash::Hasher; + let mut hasher = siphasher::sip::SipHasher::new(); + hasher.write_u64(address.as_u64()); + let hash = hasher.finish(); + hash >> (64 - self.id.index_bits()) + } + + fn plan_insert_chunk( + &self, + address: Address, + ref_count: u64, + source: &[u8], + sub_index: Option, + log: &mut LogWriter, + ) -> Result { + let chunk_index = self.chunk_index(address); + let mut chunk = [0; CHUNK_LEN]; + chunk.copy_from_slice(source); + let new_entry = Entry::new(address, ref_count); + if let Some(i) = sub_index { + let entry = Self::read_entry(&chunk, i); + assert_eq!( + entry.address(), + new_entry.address() + ); + Self::write_entry(&new_entry, i, &mut chunk); + log::trace!(target: "parity-db", "{}: Replaced ref count at {}.{}: {}", self.id, chunk_index, i, new_entry.address()); + log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + return Ok(PlanOutcome::Written) + } + for i in 0..CHUNK_ENTRIES { + let entry = Self::read_entry(&chunk, i); + if entry.is_empty() { + Self::write_entry(&new_entry, i, &mut chunk); + log::trace!(target: "parity-db", "{}: Inserted ref count at {}.{}: {}", self.id, chunk_index, i, new_entry.address()); + log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + return Ok(PlanOutcome::Written) + } + } + log::debug!(target: "parity-db", "{}: Ref count chunk full at {}", self.id, chunk_index); + Ok(PlanOutcome::NeedReindex) + } + + pub fn write_insert_plan( + &self, + address: Address, + ref_count: u64, + sub_index: Option, + log: &mut LogWriter, + ) -> Result { + log::trace!(target: "parity-db", "{}: Inserting ref count {} -> {}", self.id, address, ref_count); + let chunk_index = self.chunk_index(address); + + if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| *chunk) { + return self.plan_insert_chunk(address, ref_count, &chunk, sub_index, log) + } + + if let Some(map) = &*self.map.read() { + let chunk = Self::chunk_at(chunk_index, map)?; + return self.plan_insert_chunk(address, ref_count, chunk, sub_index, log) + } + + let chunk = &EMPTY_CHUNK; + self.plan_insert_chunk(address, ref_count, chunk, sub_index, log) + } + + fn plan_remove_chunk( + &self, + address: Address, + source: &[u8], + sub_index: usize, + log: &mut LogWriter, + ) -> Result { + let mut chunk = [0; CHUNK_LEN]; + chunk.copy_from_slice(source); + let chunk_index = self.chunk_index(address); + + let i = sub_index; + let entry = Self::read_entry(&chunk, i); + if !entry.is_empty() && entry.address() == address { + let new_entry = Entry::empty(); + Self::write_entry(&new_entry, i, &mut chunk); + log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + log::trace!(target: "parity-db", "{}: Removed ref count at {}.{}", self.id, chunk_index, i); + return Ok(PlanOutcome::Written) + } + assert!(false); + Ok(PlanOutcome::Skipped) + } + + pub fn write_remove_plan( + &self, + address: Address, + sub_index: usize, + log: &mut LogWriter, + ) -> Result { + log::trace!(target: "parity-db", "{}: Removing ref count {}", self.id, address); + let chunk_index = self.chunk_index(address); + + if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| *chunk) { + return self.plan_remove_chunk(address, &chunk, sub_index, log) + } + + if let Some(map) = &*self.map.read() { + let chunk = Self::chunk_at(chunk_index, map)?; + return self.plan_remove_chunk(address, chunk, sub_index, log) + } + + assert!(false); + Ok(PlanOutcome::Skipped) + } + + pub fn enact_plan(&self, index: u64, log: &mut LogReader) -> Result<()> { + let mut map = self.map.upgradable_read(); + if map.is_none() { + let mut wmap = RwLockUpgradableReadGuard::upgrade(map); + let file = try_io!(std::fs::OpenOptions::new() + .write(true) + .read(true) + .create_new(true) + .open(self.path.as_path())); + log::debug!(target: "parity-db", "Created new ref count {}", self.id); + //TODO: check for potential overflows on 32-bit platforms + try_io!(file.set_len(file_size(self.id.index_bits()))); + let mut mmap = try_io!(unsafe { memmap2::MmapMut::map_mut(&file) }); + self.madvise_random(&mut mmap); + *wmap = Some(mmap); + map = RwLockWriteGuard::downgrade_to_upgradable(wmap); + } + + let map = map.as_ref().unwrap(); + let offset = META_SIZE + index as usize * CHUNK_LEN; + // Nasty mutable pointer cast. We do ensure that all chunks that are being written are + // accessed through the overlay in other threads. + let ptr: *mut u8 = map.as_ptr() as *mut u8; + let chunk: &mut [u8] = unsafe { + let ptr = ptr.add(offset); + std::slice::from_raw_parts_mut(ptr, CHUNK_LEN) + }; + let mut mask_buf = [0u8; 8]; + log.read(&mut mask_buf)?; + let mut mask = u64::from_le_bytes(mask_buf); + while mask != 0 { + let i = mask.trailing_zeros(); + mask &= !(1 << i); + log.read(try_io!(Ok( + &mut chunk[i as usize * ENTRY_BYTES..(i as usize + 1) * ENTRY_BYTES] + )))?; + } + log::trace!(target: "parity-db", "{}: Enacted ref count chunk {}", self.id, index); + Ok(()) + } + + pub fn validate_plan(&self, index: u64, log: &mut LogReader) -> Result<()> { + if index >= self.id.total_chunks() { + return Err(Error::Corruption("Bad index".into())) + } + let mut mask_buf = [0u8; 8]; + let mut entry_buf = [0u8; ENTRY_BYTES]; + log.read(&mut mask_buf)?; + let mut mask = u64::from_le_bytes(mask_buf); + while mask != 0 { + let i = mask.trailing_zeros(); + mask &= !(1 << i); + log.read(&mut entry_buf[..])?; + } + log::trace!(target: "parity-db", "{}: Validated ref count chunk {}", self.id, index); + Ok(()) + } + + pub fn skip_plan(log: &mut LogReader) -> Result<()> { + let mut mask_buf = [0u8; 8]; + let mut entry_buf = [0u8; ENTRY_BYTES]; + log.read(&mut mask_buf)?; + let mut mask = u64::from_le_bytes(mask_buf); + while mask != 0 { + let i = mask.trailing_zeros(); + mask &= !(1 << i); + log.read(&mut entry_buf[..])?; + } + Ok(()) + } + + pub fn drop_file(self) -> Result<()> { + if self.map.read().is_some() { + try_io!(std::fs::remove_file(self.path.as_path())); + } + drop(self.map); + log::debug!(target: "parity-db", "{}: Dropped ref count table", self.id); + Ok(()) + } + + pub fn flush(&self) -> Result<()> { + if let Some(map) = &*self.map.read() { + // Flush everything except stats. + try_io!(map.flush_range(META_SIZE, map.len() - META_SIZE)); + } + Ok(()) + } + + #[cfg(unix)] + fn madvise_random(&self, map: &mut memmap2::MmapMut) { + unsafe { + libc::madvise( + map.as_mut_ptr() as _, + file_size(self.id.index_bits()) as usize, + libc::MADV_RANDOM, + ); + } + } + + #[cfg(not(unix))] + fn madvise_random(&self, _map: &mut memmap2::MmapMut) {} +} + +#[cfg(test)] +mod test { + /* use super::*; + use rand::{Rng, SeedableRng}; + use std::path::PathBuf; + + #[cfg(feature = "bench")] + use test::Bencher; + #[cfg(feature = "bench")] + extern crate test; + + #[test] + fn test_entries() { + let mut chunk = IndexTable::transmute_chunk(EMPTY_CHUNK); + let mut chunk2 = EMPTY_CHUNK; + for (i, chunk) in chunk.iter_mut().enumerate().take(CHUNK_ENTRIES) { + use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + }; + let mut hasher = DefaultHasher::new(); + i.hash(&mut hasher); + let hash = hasher.finish(); + let entry = Entry::from_u64(hash); + IndexTable::write_entry(&entry, i, &mut chunk2); + *chunk = entry; + } + + assert!(IndexTable::transmute_chunk(chunk2) == chunk); + } + + #[test] + fn test_find_entries() { + let partial_keys = [1, 1 << 10, 1 << 20]; + for index_bits in [16, 18, 20, 22] { + let index_table = IndexTable { + id: TableId(index_bits.into()), + map: RwLock::new(None), + path: PathBuf::new(), + }; + + let data_address = Address::from_u64((1 << index_bits) - 1); + + let mut chunk = [0; CHUNK_ENTRIES * 8]; + for (i, partial_key) in partial_keys.iter().enumerate() { + chunk[i * 8..(i + 1) * 8].copy_from_slice( + &Entry::new(data_address, *partial_key, index_bits).as_u64().to_le_bytes(), + ); + } + + for partial_key in &partial_keys { + let key_prefix = *partial_key << (CHUNK_ENTRIES_BITS + SIZE_TIERS_BITS); + #[cfg(target_arch = "x86_64")] + assert_eq!( + index_table.find_entry_sse2(key_prefix, 0, &chunk).0.partial_key(index_bits), + *partial_key + ); + assert_eq!( + index_table.find_entry_base(key_prefix, 0, &chunk).0.partial_key(index_bits), + *partial_key + ); + } + } + } + + #[test] + fn test_find_any_entry() { + let table = + IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; + let mut chunk = [0u8; CHUNK_LEN]; + let mut entries = [Entry::empty(); CHUNK_ENTRIES]; + let mut keys = [0u64; CHUNK_ENTRIES]; + let mut rng = rand::prelude::SmallRng::from_seed(Default::default()); + for i in 0..CHUNK_ENTRIES { + keys[i] = rng.gen(); + let partial_key = Entry::extract_key(keys[i], 18); + let e = Entry::new(Address::new(0, 0), partial_key, 18); + entries[i] = e; + IndexTable::write_entry(&e, i, &mut chunk); + } + + for target in 0..CHUNK_ENTRIES { + for start_pos in 0..CHUNK_ENTRIES { + let (e, i) = table.find_entry_base(keys[target], start_pos, &chunk); + if start_pos <= target { + assert_eq!((e.as_u64(), i), (entries[target].as_u64(), target)); + } else { + assert_eq!((e.as_u64(), i), (Entry::empty().as_u64(), 0)); + } + #[cfg(target_arch = "x86_64")] + { + let (e, i) = table.find_entry_sse2(keys[target], start_pos, &chunk); + if start_pos <= target { + assert_eq!((e.as_u64(), i), (entries[target].as_u64(), target)); + } else { + assert_eq!((e.as_u64(), i), (Entry::empty().as_u64(), 0)); + } + } + } + } + } + + #[test] + fn test_find_entry_same_value() { + let table = + IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; + let mut chunk = [0u8; CHUNK_LEN]; + let key = 0x4242424242424242; + let partial_key = Entry::extract_key(key, 18); + let entry = Entry::new(Address::new(0, 0), partial_key, 18); + for i in 0..CHUNK_ENTRIES { + IndexTable::write_entry(&entry, i, &mut chunk); + } + + for start_pos in 0..CHUNK_ENTRIES { + let (_, i) = table.find_entry_base(key, start_pos, &chunk); + assert_eq!(i, start_pos); + #[cfg(target_arch = "x86_64")] + { + let (_, i) = table.find_entry_sse2(key, start_pos, &chunk); + assert_eq!(i, start_pos); + } + } + } + + #[test] + fn test_find_entry_zero_pk() { + let table = + IndexTable { id: TableId(16), map: RwLock::new(None), path: Default::default() }; + let mut chunk = [0u8; CHUNK_LEN]; + let zero_key = 0x0000000000000000; + let entry = Entry::new(Address::new(1, 1), zero_key, 16); + + // Write at index 1. Index 0 contains an empty entry. + IndexTable::write_entry(&entry, 1, &mut chunk); + + let (_, i) = table.find_entry_base(zero_key, 0, &chunk); + assert_eq!(i, 1); + #[cfg(target_arch = "x86_64")] + { + let (_, i) = table.find_entry_sse2(zero_key, 0, &chunk); + assert_eq!(i, 1); + } + } */ + + /* #[cfg(feature = "bench")] + fn bench_find_entry_internal< + F: Fn(&IndexTable, u64, usize, &[u8; CHUNK_LEN]) -> (Entry, usize), + >( + b: &mut Bencher, + f: F, + ) { + let table = + IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; + let mut chunk = [0u8; CHUNK_LEN]; + let mut keys = [0u64; CHUNK_ENTRIES]; + let mut rng = rand::prelude::SmallRng::from_seed(Default::default()); + for i in 0..CHUNK_ENTRIES { + keys[i] = rng.gen(); + let partial_key = Entry::extract_key(keys[i], 18); + let e = Entry::new(Address::new(0, 0), partial_key, 18); + IndexTable::write_entry(&e, i, &mut chunk); + } + + let mut index = 0; + b.iter(|| { + let x = f(&table, keys[index], 0, &chunk).1; + assert_eq!(x, index); + index = (index + 1) % CHUNK_ENTRIES; + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_find_entry(b: &mut Bencher) { + bench_find_entry_internal(b, IndexTable::find_entry_base) + } + + #[cfg(feature = "bench")] + #[cfg(target_arch = "x86_64")] + #[bench] + fn bench_find_entry_sse(b: &mut Bencher) { + bench_find_entry_internal(b, IndexTable::find_entry_sse2) + } */ +} diff --git a/src/table.rs b/src/table.rs index a8995267..029a15de 100644 --- a/src/table.rs +++ b/src/table.rs @@ -1013,6 +1013,52 @@ impl ValueTable { Ok(true) } + pub fn change_ref_return(&self, index: u64, delta: i32, log: &mut LogWriter) -> Result<(bool, u32)> { + let mut buf = FullEntry::new_uninit_full_entry(); + let buf = if log.value(self.id, index, buf.as_mut()) { + &mut buf + } else { + self.file + .read_at(&mut buf[0..self.entry_size as usize], index * self.entry_size as u64)?; + &mut buf + }; + + if buf.is_tombstone() { + return Ok((false, 0)) + } + + let size = if self.multipart && buf.is_multi(self.db_version) { + buf.skip_size(); + buf.skip_next(); + self.entry_size as usize + } else { + let (size, _compressed) = buf.read_size(); + buf.offset() + size as usize + }; + + let rc_offset = buf.offset(); + let mut counter = buf.read_rc(); + if delta > 0 { + if counter >= LOCKED_REF - delta as u32 { + counter = LOCKED_REF + } else { + counter += delta as u32; + } + } else if counter != LOCKED_REF { + counter = counter.saturating_sub(-delta as u32); + if counter == 0 { + return Ok((false, 0)) + } + } + + buf.set_offset(rc_offset); + buf.write_rc(counter); + // TODO: optimize actual buf size + log.insert_value(self.id, index, buf[0..size].to_vec()); + Ok((true, counter)) + } + + pub fn enact_plan(&self, index: u64, log: &mut LogReader) -> Result<()> { while index >= self.file.capacity.load(Ordering::Relaxed) { self.file.grow(self.entry_size)?; @@ -1344,7 +1390,9 @@ mod test { match reader.next().unwrap() { LogAction::BeginRecord | LogAction::InsertIndex { .. } | - LogAction::DropTable { .. } => { + LogAction::InsertRefCount { .. } | + LogAction::DropTable { .. } | + LogAction::DropRefCountTable { .. } => { panic!("Unexpected log entry"); }, LogAction::EndRecord => { From 5aa61af56f46348ec059245f7ebe00456c91b281 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 28 Sep 2023 13:28:54 +0100 Subject: [PATCH 25/53] fmt --- src/column.rs | 154 +++++++++++++++++++++++++++++++++++------------ src/db.rs | 27 +++++++-- src/lib.rs | 2 +- src/log.rs | 25 ++++++-- src/ref_count.rs | 33 +++++----- src/table.rs | 8 ++- 6 files changed, 180 insertions(+), 69 deletions(-) diff --git a/src/column.rs b/src/column.rs index cf0cfe8d..635bf788 100644 --- a/src/column.rs +++ b/src/column.rs @@ -809,7 +809,8 @@ impl HashColumn { log::trace!(target: "parity-db", "{}: Skipped ref count reindex entry {} when reindexing", tables.ref_count.id, address); return Ok(PlanOutcome::Skipped) } - // An intermediate reindex table might contain a more recent value for the ref count so need to check for this and skip. + // An intermediate reindex table might contain a more recent value for the ref count so need + // to check for this and skip. for entry in reindex.queue.iter().rev() { if let ReindexEntry::RefCount(ref_count_table) = entry { if ref_count_table.id == source { @@ -826,7 +827,8 @@ impl HashColumn { tables.ref_count.write_insert_plan(address, ref_count, None, log)? { log::debug!(target: "parity-db", "{}: Ref count chunk full {} when reindexing", tables.ref_count.id, address); - (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + (tables, reindex) = + Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); outcome = PlanOutcome::NeedReindex; } Ok(outcome) @@ -881,17 +883,22 @@ impl HashColumn { } else { // Removing let result = ref_count_table.write_remove_plan(address, sub_index, log); - // Need to remove from all old tables in reindex otherwise it will appear that this entry still exists and it might get reintroduced during reindex. + // Need to remove from all old tables in reindex otherwise it will appear that this + // entry still exists and it might get reintroduced during reindex. { if ref_count_table.id != tables.ref_count.id { - if let Some((table, sub_index, _ref_count)) = Self::search_ref_count(address, &tables.ref_count, log)? { + if let Some((table, sub_index, _ref_count)) = + Self::search_ref_count(address, &tables.ref_count, log)? + { table.write_remove_plan(address, sub_index, log)?; } } for entry in &reindex.queue { if let ReindexEntry::RefCount(table) = entry { if table.id != ref_count_table.id { - if let Some((table, sub_index, _ref_count)) = Self::search_ref_count(address, table, log)? { + if let Some((table, sub_index, _ref_count)) = + Self::search_ref_count(address, table, log)? + { table.write_remove_plan(address, sub_index, log)?; } } @@ -919,7 +926,8 @@ impl HashColumn { tables.ref_count.write_insert_plan(address, ref_count, None, log)? { log::debug!(target: "parity-db", "{}: Ref count chunk full {}", tables.ref_count.id, address); - (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + (tables, reindex) = + Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); outcome = PlanOutcome::NeedReindex; } let (test_ref_count, _test_sub_index) = tables.ref_count.get(address, log)?.unwrap(); @@ -1146,12 +1154,14 @@ impl HashColumn { let tables = self.as_ref(&tables.value); let target_tier = address.size_tier(); let offset = address.offset(); - let (exists, ref_count) = tables.tables[target_tier as usize].change_ref_return(offset, 1, log)?; + let (exists, ref_count) = + tables.tables[target_tier as usize].change_ref_return(offset, 1, log)?; assert!(exists); ref_count }; let reindex = self.reindex.upgradable_read(); - let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; + let existing: Option<(&RefCountTable, usize, u64)> = + Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); let new_ref_count = ref_count + 1; @@ -1167,13 +1177,22 @@ impl HashColumn { } assert!(table_ref_count as u64 == new_ref_count); if table.id == tables.ref_count.id { - self.write_ref_count_plan_existing(&tables, &reindex, (address, Some(new_ref_count)), log, table, sub_index) + self.write_ref_count_plan_existing( + &tables, + &reindex, + (address, Some(new_ref_count)), + log, + table, + sub_index, + ) } else { - let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, new_ref_count, log)?; + let (r, _, _) = + self.write_ref_count_plan_new(tables, reindex, address, new_ref_count, log)?; Ok(r) } } else { - // inc ref is only called on addresses that already exist, so we know they must have only 1 reference. + // inc ref is only called on addresses that already exist, so we know they must have + // only 1 reference. assert!(table_ref_count == 2); let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, 2, log)?; Ok(r) @@ -1194,26 +1213,37 @@ impl HashColumn { tables.tables[target_tier as usize].change_ref_return(offset, -1, log)? }; let reindex = self.reindex.upgradable_read(); - let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; + let existing: Option<(&RefCountTable, usize, u64)> = + Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); let new_ref_count = ref_count - 1; assert!(table_ref_count as u64 == new_ref_count); assert!(value_table_remains); - let new_ref_count = if new_ref_count > 1 { - Some(new_ref_count) - } else { - None - }; + let new_ref_count = if new_ref_count > 1 { Some(new_ref_count) } else { None }; let outcome = if new_ref_count.is_some() && table.id != tables.ref_count.id { - let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, new_ref_count.unwrap(), log)?; + let (r, _, _) = self.write_ref_count_plan_new( + tables, + reindex, + address, + new_ref_count.unwrap(), + log, + )?; r } else { - self.write_ref_count_plan_existing(&tables, &reindex, (address, new_ref_count), log, table, sub_index)? + self.write_ref_count_plan_existing( + &tables, + &reindex, + (address, new_ref_count), + log, + table, + sub_index, + )? }; Ok((true, outcome)) } else { - // dec ref is only called on addresses that already exist, so we know they must have only 1 reference. + // dec ref is only called on addresses that already exist, so we know they must have + // only 1 reference. assert!(table_ref_count == 0); assert!(!value_table_remains); { @@ -1233,7 +1263,12 @@ impl HashColumn { LogAction::InsertIndex(record) => { if tables.index.id == record.table { tables.index.enact_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + } else if let Some(table) = reindex + .queue + .iter() + .filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }) + .find(|r| r.id == record.table) + { table.enact_plan(record.index, log)?; } else { // This may happen when removal is planned for an old index when reindexing. @@ -1253,12 +1288,17 @@ impl HashColumn { LogAction::InsertRefCount(record) => { if tables.ref_count.id == record.table { tables.ref_count.enact_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + } else if let Some(table) = reindex + .queue + .iter() + .filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }) + .find(|r| r.id == record.table) + { table.enact_plan(record.index, log)?; } else { // This may happen when removal is planned for an old ref count when reindexing. - // We can safely skip the removal since the new ref count does not have the entry - // anyway and the old ref count is already dropped. + // We can safely skip the removal since the new ref count does not have the + // entry anyway and the old ref count is already dropped. log::debug!( target: "parity-db", "Missing ref count {}. Skipped", @@ -1282,7 +1322,12 @@ impl HashColumn { LogAction::InsertIndex(record) => { if tables.index.id == record.table { tables.index.validate_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + } else if let Some(table) = reindex + .queue + .iter() + .filter_map(|s| if let ReindexEntry::Index(t) = s { Some(t) } else { None }) + .find(|r| r.id == record.table) + { table.validate_plan(record.index, log)?; } else { if record.table.index_bits() < tables.index.id.index_bits() { @@ -1308,7 +1353,12 @@ impl HashColumn { LogAction::InsertRefCount(record) => { if tables.ref_count.id == record.table { tables.ref_count.validate_plan(record.index, log)?; - } else if let Some(table) = reindex.queue.iter().filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }).find(|r| r.id == record.table) { + } else if let Some(table) = reindex + .queue + .iter() + .filter_map(|s| if let ReindexEntry::RefCount(t) = s { Some(t) } else { None }) + .find(|r| r.id == record.table) + { table.validate_plan(record.index, log)?; } else { if record.table.index_bits() < tables.ref_count.id.index_bits() { @@ -1323,7 +1373,8 @@ impl HashColumn { "Missing ref count {}, starting reindex", record.table, ); - let lock = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); + let lock = + Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); std::mem::drop(lock); return self.validate_plan(LogAction::InsertRefCount(record), log) } @@ -1663,7 +1714,9 @@ impl HashColumn { log::debug!(target: "parity-db", "{}: Reindexing at {}/{}", tables.index.id, source_index, source.id.total_chunks()); } log::debug!(target: "parity-db", "{}: Continue reindex at {}/{}", tables.index.id, source_index, source.id.total_chunks()); - while source_index < source.id.total_chunks() && plan.len() < MAX_REINDEX_BATCH { + while source_index < source.id.total_chunks() && + plan.len() < MAX_REINDEX_BATCH + { log::trace!(target: "parity-db", "{}: Reindexing {}", source.id, source_index); let entries = source.entries(source_index, log.overlays())?; for entry in entries.iter() { @@ -1684,7 +1737,7 @@ impl HashColumn { } } }, - ReindexEntry::RefCount(source) => { + ReindexEntry::RefCount(source) => if progress != source.id.total_chunks() { let mut source_index = progress; if source_index % 500 == 0 { @@ -1692,7 +1745,9 @@ impl HashColumn { } ref_count_source = Some(source.id); log::debug!(target: "parity-db", "{}: Continue reindex ref count at {}/{}", tables.ref_count.id, source_index, source.id.total_chunks()); - while source_index < source.id.total_chunks() && ref_count_plan.len() < MAX_REINDEX_BATCH { + while source_index < source.id.total_chunks() && + ref_count_plan.len() < MAX_REINDEX_BATCH + { log::trace!(target: "parity-db", "{}: Reindexing ref count {}", source.id, source_index); let entries = source.entries(source_index, log.overlays())?; for entry in entries.iter() { @@ -1709,20 +1764,35 @@ impl HashColumn { log::info!(target: "parity-db", "Completed reindex ref count {} into {}", source.id, tables.ref_count.id); drop_ref_count = Some(source.id); } - } - } + }, } } - Ok(ReindexBatch { drop_index, batch: plan, drop_ref_count, ref_count_batch: ref_count_plan, ref_count_batch_source: ref_count_source }) + Ok(ReindexBatch { + drop_index, + batch: plan, + drop_ref_count, + ref_count_batch: ref_count_plan, + ref_count_batch_source: ref_count_source, + }) } pub fn drop_index(&self, id: IndexTableId) -> Result<()> { log::debug!(target: "parity-db", "Dropping {}", id); let mut reindex = self.reindex.write(); - if reindex.queue.front_mut().map_or(false, |e| if let ReindexEntry::Index(t) = e { t.id == id } else { false }) { + if reindex.queue.front_mut().map_or(false, |e| { + if let ReindexEntry::Index(t) = e { + t.id == id + } else { + false + } + }) { reindex.progress.store(0, Ordering::Relaxed); let table = reindex.queue.pop_front().unwrap(); - let table = if let ReindexEntry::Index(table) = table { table } else { return Err(Error::Corruption(format!("Incorrect reindex type"))) }; + let table = if let ReindexEntry::Index(table) = table { + table + } else { + return Err(Error::Corruption(format!("Incorrect reindex type"))) + }; table.drop_file()?; } else { log::warn!(target: "parity-db", "Dropping invalid index {}", id); @@ -1735,10 +1805,20 @@ impl HashColumn { pub fn drop_ref_count(&self, id: RefCountTableId) -> Result<()> { log::debug!(target: "parity-db", "Dropping ref count {}", id); let mut reindex = self.reindex.write(); - if reindex.queue.front_mut().map_or(false, |e| if let ReindexEntry::RefCount(t) = e { t.id == id } else { false }) { + if reindex.queue.front_mut().map_or(false, |e| { + if let ReindexEntry::RefCount(t) = e { + t.id == id + } else { + false + } + }) { reindex.progress.store(0, Ordering::Relaxed); let table = reindex.queue.pop_front().unwrap(); - let table = if let ReindexEntry::RefCount(table) = table { table } else { return Err(Error::Corruption(format!("Incorrect reindex type"))) }; + let table = if let ReindexEntry::RefCount(table) = table { + table + } else { + return Err(Error::Corruption(format!("Incorrect reindex type"))) + }; table.drop_file()?; } else { log::warn!(target: "parity-db", "Dropping invalid ref count {}", id); diff --git a/src/db.rs b/src/db.rs index d2039753..2e65120a 100644 --- a/src/db.rs +++ b/src/db.rs @@ -902,9 +902,19 @@ impl DbInner { // Process any pending reindexes for column in self.columns.iter() { let column = if let Column::Hash(c) = column { c } else { continue }; - let ReindexBatch { drop_index, batch, drop_ref_count, ref_count_batch, ref_count_batch_source } = column.reindex(&self.log)?; + let ReindexBatch { + drop_index, + batch, + drop_ref_count, + ref_count_batch, + ref_count_batch_source, + } = column.reindex(&self.log)?; if !batch.is_empty() || drop_index.is_some() { - assert!(ref_count_batch.is_empty() && ref_count_batch_source.is_none() && drop_ref_count.is_none()); + assert!( + ref_count_batch.is_empty() && + ref_count_batch_source.is_none() && + drop_ref_count.is_none() + ); let mut next_reindex = false; let mut writer = self.log.begin_record(); log::debug!( @@ -952,9 +962,12 @@ impl DbInner { writer.record_id(), ); for (address, ref_count) in ref_count_batch.into_iter() { - if let PlanOutcome::NeedReindex = - column.write_ref_count_reindex_plan(address, ref_count, ref_count_source, &mut writer)? - { + if let PlanOutcome::NeedReindex = column.write_ref_count_reindex_plan( + address, + ref_count, + ref_count_source, + &mut writer, + )? { next_reindex = true } } @@ -2113,7 +2126,9 @@ impl IndexedChangeSet { )?; }, NodeChange::IncrementReference(address) => { - if let PlanOutcome::NeedReindex = column.write_address_inc_ref_plan(*address, writer)? { + if let PlanOutcome::NeedReindex = + column.write_address_inc_ref_plan(*address, writer)? + { *reindex = true; } }, diff --git a/src/lib.rs b/src/lib.rs index d736806a..1a73015a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,9 +17,9 @@ mod migration; mod multitree; mod options; mod parking_lot; +mod ref_count; mod stats; mod table; -mod ref_count; pub use btree::BTreeIterator; pub use column::{ColId, ValueIterState}; diff --git a/src/log.rs b/src/log.rs index 989957c1..45e7a6f5 100644 --- a/src/log.rs +++ b/src/log.rs @@ -4,10 +4,10 @@ use crate::{ column::ColId, error::{try_io, Error, Result}, - ref_count::{Chunk as RefCountChunk, RefCountTableId, ENTRY_BYTES as REF_COUNT_ENTRY_BYTES}, index::{Chunk as IndexChunk, TableId as IndexTableId, ENTRY_BYTES}, options::Options, parking_lot::{RwLock, RwLockWriteGuard}, + ref_count::{Chunk as RefCountChunk, RefCountTableId, ENTRY_BYTES as REF_COUNT_ENTRY_BYTES}, table::TableId as ValueTableId, }; use std::{ @@ -364,7 +364,10 @@ impl LogChange { while mask != 0 { let i = mask.trailing_zeros(); mask &= !(1 << i); - write(&chunk[i as usize * REF_COUNT_ENTRY_BYTES..(i as usize + 1) * REF_COUNT_ENTRY_BYTES])?; + write( + &chunk[i as usize * REF_COUNT_ENTRY_BYTES.. + (i as usize + 1) * REF_COUNT_ENTRY_BYTES], + )?; } } } @@ -383,7 +386,12 @@ impl LogChange { try_io!(file.write_all(&checksum.to_le_bytes())); bytes += 4; try_io!(file.flush()); - Ok(FlushedLog { index: self.local_index, values: self.local_values, ref_count: self.local_ref_count, bytes }) + Ok(FlushedLog { + index: self.local_index, + values: self.local_values, + ref_count: self.local_ref_count, + bytes, + }) } } @@ -430,7 +438,13 @@ impl<'a> LogWriter<'a> { .insert(index, (self.log.record_id, data)); } - pub fn insert_ref_count(&mut self, table: RefCountTableId, index: u64, sub: u8, data: &RefCountChunk) { + pub fn insert_ref_count( + &mut self, + table: RefCountTableId, + index: u64, + sub: u8, + data: &RefCountChunk, + ) { match self.log.local_ref_count.entry(table).or_default().map.entry(index) { std::collections::hash_map::Entry::Occupied(mut entry) => { *entry.get_mut() = (self.log.record_id, entry.get().1 | (1 << sub), *data); @@ -726,7 +740,8 @@ impl Log { *appending = Some(Appending { size: 0, file: std::io::BufWriter::new(file), id }); } let appending = appending.as_mut().unwrap(); - let FlushedLog { index, values, ref_count, bytes } = log.flush_to_file(&mut appending.file)?; + let FlushedLog { index, values, ref_count, bytes } = + log.flush_to_file(&mut appending.file)?; let mut overlays = self.overlays.write(); let mut total_index = 0; for (id, overlay) in index.into_iter() { diff --git a/src/ref_count.rs b/src/ref_count.rs index 95af3876..c579f2e9 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -125,7 +125,10 @@ impl std::fmt::Display for RefCountTableId { } impl RefCountTable { - pub fn open_existing(path: &std::path::Path, id: RefCountTableId) -> Result> { + pub fn open_existing( + path: &std::path::Path, + id: RefCountTableId, + ) -> Result> { let mut path: std::path::PathBuf = path.into(); path.push(id.file_name()); @@ -153,19 +156,11 @@ impl RefCountTable { Ok(try_io!(Ok(ptr))) } - fn find_entry( - &self, - address: u64, - chunk: &[u8; CHUNK_LEN], - ) -> Option<(Entry, usize)> { + fn find_entry(&self, address: u64, chunk: &[u8; CHUNK_LEN]) -> Option<(Entry, usize)> { self.find_entry_base(address, chunk) } - fn find_entry_base( - &self, - address: u64, - chunk: &[u8; CHUNK_LEN], - ) -> Option<(Entry, usize)> { + fn find_entry_base(&self, address: u64, chunk: &[u8; CHUNK_LEN]) -> Option<(Entry, usize)> { for i in 0..CHUNK_ENTRIES { let entry = Self::read_entry(chunk, i); if entry.address().as_u64() == address && !entry.is_empty() { @@ -189,7 +184,9 @@ impl RefCountTable { if let Some(map) = &*self.map.read() { log::trace!(target: "parity-db", "{}: Querying ref count chunk at {}", self.id, chunk_index); let chunk = Self::chunk_at(chunk_index, map)?; - return Ok(self.find_entry(address.as_u64(), chunk).map(|(e, sub_index)| (e.ref_count(), sub_index))) + return Ok(self + .find_entry(address.as_u64(), chunk) + .map(|(e, sub_index)| (e.ref_count(), sub_index))) } Ok(None) } @@ -223,12 +220,15 @@ impl RefCountTable { #[inline(always)] fn write_entry(entry: &Entry, at: usize, chunk: &mut [u8; CHUNK_LEN]) { - chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].copy_from_slice(&entry.as_u128().to_le_bytes()); + chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES] + .copy_from_slice(&entry.as_u128().to_le_bytes()); } #[inline(always)] fn read_entry(chunk: &[u8; CHUNK_LEN], at: usize) -> Entry { - Entry::from_u128(u128::from_le_bytes(chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].try_into().unwrap())) + Entry::from_u128(u128::from_le_bytes( + chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].try_into().unwrap(), + )) } #[inline(always)] @@ -254,10 +254,7 @@ impl RefCountTable { let new_entry = Entry::new(address, ref_count); if let Some(i) = sub_index { let entry = Self::read_entry(&chunk, i); - assert_eq!( - entry.address(), - new_entry.address() - ); + assert_eq!(entry.address(), new_entry.address()); Self::write_entry(&new_entry, i, &mut chunk); log::trace!(target: "parity-db", "{}: Replaced ref count at {}.{}: {}", self.id, chunk_index, i, new_entry.address()); log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); diff --git a/src/table.rs b/src/table.rs index 029a15de..e7fca692 100644 --- a/src/table.rs +++ b/src/table.rs @@ -1013,7 +1013,12 @@ impl ValueTable { Ok(true) } - pub fn change_ref_return(&self, index: u64, delta: i32, log: &mut LogWriter) -> Result<(bool, u32)> { + pub fn change_ref_return( + &self, + index: u64, + delta: i32, + log: &mut LogWriter, + ) -> Result<(bool, u32)> { let mut buf = FullEntry::new_uninit_full_entry(); let buf = if log.value(self.id, index, buf.as_mut()) { &mut buf @@ -1058,7 +1063,6 @@ impl ValueTable { Ok((true, counter)) } - pub fn enact_plan(&self, index: u64, log: &mut LogReader) -> Result<()> { while index >= self.file.capacity.load(Ordering::Relaxed) { self.file.grow(self.entry_size)?; From 85451814d9749890214c4daa4a505be601ff160a Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 29 Sep 2023 11:11:27 +0100 Subject: [PATCH 26/53] Remove value table verification of ref counts --- admin/src/lib.rs | 5 +-- admin/src/multitree_bench/mod.rs | 5 ++- src/column.rs | 45 ++++----------------------- src/table.rs | 52 +------------------------------- 4 files changed, 12 insertions(+), 95 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index 04f1da0e..c1aa03e0 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -141,10 +141,7 @@ pub fn run() -> Result<(), String> { for c in &mut db_options.columns { c.multitree = true; - if args.pruning > 0 { - c.ref_counted = true; - c.preimage = true; - } else { + if args.pruning == 0 { c.append_only = true; } } diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index 41dfff29..ae576775 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -1272,7 +1272,10 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { } if args.empty_on_shutdown && args.pruning > 0 { - output_helper.write().println_final(format!("Removed all entries")); + let elapsed_time = start_time.elapsed().as_secs_f64(); + output_helper + .write() + .println_final(format!("Removed all entries. Total time: {}", elapsed_time)); } Ok(()) diff --git a/src/column.rs b/src/column.rs index 635bf788..5c0bcc5c 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1149,33 +1149,13 @@ impl HashColumn { log: &mut LogWriter, ) -> Result { let tables = self.tables.upgradable_read(); - let address = Address::from_u64(address); - let table_ref_count = { - let tables = self.as_ref(&tables.value); - let target_tier = address.size_tier(); - let offset = address.offset(); - let (exists, ref_count) = - tables.tables[target_tier as usize].change_ref_return(offset, 1, log)?; - assert!(exists); - ref_count - }; let reindex = self.reindex.upgradable_read(); + let address = Address::from_u64(address); let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); let new_ref_count = ref_count + 1; - if table_ref_count as u64 != new_ref_count { - log::info!(target: "parity-db", "Ref count mismatch, value: {}, {}: {}", table_ref_count, table.id, new_ref_count); - for entry in reindex.queue.iter().rev() { - if let ReindexEntry::RefCount(ref_count_table) = entry { - if let Some(r) = Self::search_ref_count(address, ref_count_table, log)? { - log::info!(target: "parity-db", "Ref count mismatch, value: {}, {}: {}", table_ref_count, r.0.id, r.2); - } - } - } - } - assert!(table_ref_count as u64 == new_ref_count); if table.id == tables.ref_count.id { self.write_ref_count_plan_existing( &tables, @@ -1193,7 +1173,6 @@ impl HashColumn { } else { // inc ref is only called on addresses that already exist, so we know they must have // only 1 reference. - assert!(table_ref_count == 2); let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, 2, log)?; Ok(r) } @@ -1205,21 +1184,13 @@ impl HashColumn { log: &mut LogWriter, ) -> Result<(bool, PlanOutcome)> { let tables = self.tables.upgradable_read(); - let address = Address::from_u64(address); - let (value_table_remains, table_ref_count) = { - let tables = self.as_ref(&tables.value); - let target_tier = address.size_tier(); - let offset = address.offset(); - tables.tables[target_tier as usize].change_ref_return(offset, -1, log)? - }; let reindex = self.reindex.upgradable_read(); + let address = Address::from_u64(address); let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); let new_ref_count = ref_count - 1; - assert!(table_ref_count as u64 == new_ref_count); - assert!(value_table_remains); let new_ref_count = if new_ref_count > 1 { Some(new_ref_count) } else { None }; let outcome = if new_ref_count.is_some() && table.id != tables.ref_count.id { let (r, _, _) = self.write_ref_count_plan_new( @@ -1244,14 +1215,10 @@ impl HashColumn { } else { // dec ref is only called on addresses that already exist, so we know they must have // only 1 reference. - assert!(table_ref_count == 0); - assert!(!value_table_remains); - { - let tables = self.as_ref(&tables.value); - let target_tier = address.size_tier(); - let offset = address.offset(); - tables.tables[target_tier as usize].write_remove_plan(offset, log)?; - } + let tables = self.as_ref(&tables.value); + let target_tier = address.size_tier(); + let offset = address.offset(); + tables.tables[target_tier as usize].write_remove_plan(offset, log)?; Ok((false, PlanOutcome::Written)) } } diff --git a/src/table.rs b/src/table.rs index e7fca692..0ef74d00 100644 --- a/src/table.rs +++ b/src/table.rs @@ -447,7 +447,7 @@ impl ValueTable { dirty_header: AtomicBool::new(false), free_entries, multipart, - ref_counted: options.ref_counted || (options.multitree && !options.append_only), + ref_counted: options.ref_counted, db_version, }) } @@ -1013,56 +1013,6 @@ impl ValueTable { Ok(true) } - pub fn change_ref_return( - &self, - index: u64, - delta: i32, - log: &mut LogWriter, - ) -> Result<(bool, u32)> { - let mut buf = FullEntry::new_uninit_full_entry(); - let buf = if log.value(self.id, index, buf.as_mut()) { - &mut buf - } else { - self.file - .read_at(&mut buf[0..self.entry_size as usize], index * self.entry_size as u64)?; - &mut buf - }; - - if buf.is_tombstone() { - return Ok((false, 0)) - } - - let size = if self.multipart && buf.is_multi(self.db_version) { - buf.skip_size(); - buf.skip_next(); - self.entry_size as usize - } else { - let (size, _compressed) = buf.read_size(); - buf.offset() + size as usize - }; - - let rc_offset = buf.offset(); - let mut counter = buf.read_rc(); - if delta > 0 { - if counter >= LOCKED_REF - delta as u32 { - counter = LOCKED_REF - } else { - counter += delta as u32; - } - } else if counter != LOCKED_REF { - counter = counter.saturating_sub(-delta as u32); - if counter == 0 { - return Ok((false, 0)) - } - } - - buf.set_offset(rc_offset); - buf.write_rc(counter); - // TODO: optimize actual buf size - log.insert_value(self.id, index, buf[0..size].to_vec()); - Ok((true, counter)) - } - pub fn enact_plan(&self, index: u64, log: &mut LogReader) -> Result<()> { while index >= self.file.capacity.load(Ordering::Relaxed) { self.file.grow(self.entry_size)?; From 91d10adc52de00274eff7c215010953d2cfcb4c2 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 3 Oct 2023 12:43:12 +0200 Subject: [PATCH 27/53] Only create and use ref count table when needed --- src/column.rs | 80 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/src/column.rs b/src/column.rs index 5c0bcc5c..c580dec5 100644 --- a/src/column.rs +++ b/src/column.rs @@ -78,7 +78,13 @@ const SIZES: [u16; SIZE_TIERS - 1] = [ struct Tables { index: IndexTable, value: Vec, - ref_count: RefCountTable, + ref_count: Option, +} + +impl Tables { + fn get_ref_count(&self) -> &RefCountTable { + self.ref_count.as_ref().unwrap() + } } #[derive(Debug)] @@ -432,11 +438,15 @@ impl HashColumn { metadata: &Metadata, ) -> Result { let (index, mut reindexing, stats) = Self::open_index(&options.path, col)?; - let ref_count = Self::open_ref_count(&options.path, col, &mut reindexing)?; let collect_stats = options.stats; let path = &options.path; let col_options = &metadata.columns[col as usize]; let db_version = metadata.version; + let ref_count = if col_options.multitree && !col_options.append_only { + Some(Self::open_ref_count(&options.path, col, &mut reindexing)?) + } else { + None + }; Ok(HashColumn { col, tables: RwLock::new(Tables { index, value, ref_count }), @@ -471,7 +481,9 @@ impl HashColumn { for t in tables.value.iter() { t.flush()?; } - tables.ref_count.flush()?; + if tables.ref_count.is_some() { + tables.get_ref_count().flush()?; + } Ok(()) } @@ -770,14 +782,16 @@ impl HashColumn { log::info!( target: "parity-db", "Started reindex for ref count {}", - tables.ref_count.id, + tables.get_ref_count().id, ); // Start reindex - let new_id = - RefCountTableId::new(tables.ref_count.id.col(), tables.ref_count.id.index_bits() + 1); - let new_table = RefCountTable::create_new(path, new_id); + let new_id = RefCountTableId::new( + tables.get_ref_count().id.col(), + tables.get_ref_count().id.index_bits() + 1, + ); + let new_table = Some(RefCountTable::create_new(path, new_id)); let old_table = std::mem::replace(&mut tables.ref_count, new_table); - reindex.queue.push_back(ReindexEntry::RefCount(old_table)); + reindex.queue.push_back(ReindexEntry::RefCount(old_table.unwrap())); ( RwLockWriteGuard::downgrade_to_upgradable(tables), RwLockWriteGuard::downgrade_to_upgradable(reindex), @@ -805,8 +819,8 @@ impl HashColumn { source: RefCountTableId, log: &mut LogWriter, ) -> Result { - if let Some((_ref_count, _sub_index)) = tables.ref_count.get(address, log)? { - log::trace!(target: "parity-db", "{}: Skipped ref count reindex entry {} when reindexing", tables.ref_count.id, address); + if let Some((_ref_count, _sub_index)) = tables.get_ref_count().get(address, log)? { + log::trace!(target: "parity-db", "{}: Skipped ref count reindex entry {} when reindexing", tables.get_ref_count().id, address); return Ok(PlanOutcome::Skipped) } // An intermediate reindex table might contain a more recent value for the ref count so need @@ -824,9 +838,9 @@ impl HashColumn { } let mut outcome = PlanOutcome::Written; while let PlanOutcome::NeedReindex = - tables.ref_count.write_insert_plan(address, ref_count, None, log)? + tables.get_ref_count().write_insert_plan(address, ref_count, None, log)? { - log::debug!(target: "parity-db", "{}: Ref count chunk full {} when reindexing", tables.ref_count.id, address); + log::debug!(target: "parity-db", "{}: Ref count chunk full {} when reindexing", tables.get_ref_count().id, address); (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); outcome = PlanOutcome::NeedReindex; @@ -851,7 +865,7 @@ impl HashColumn { reindex: &'a Reindex, log: &LogWriter, ) -> Result> { - if let Some(r) = Self::search_ref_count(address, &tables.ref_count, log)? { + if let Some(r) = Self::search_ref_count(address, tables.get_ref_count(), log)? { return Ok(Some(r)) } // Check old tables @@ -878,17 +892,19 @@ impl HashColumn { let (address, ref_count) = change; if let Some(ref_count) = ref_count { // Replacing - assert!(ref_count_table.id == tables.ref_count.id); - tables.ref_count.write_insert_plan(address, ref_count, Some(sub_index), log) + assert!(ref_count_table.id == tables.get_ref_count().id); + tables + .get_ref_count() + .write_insert_plan(address, ref_count, Some(sub_index), log) } else { // Removing let result = ref_count_table.write_remove_plan(address, sub_index, log); // Need to remove from all old tables in reindex otherwise it will appear that this // entry still exists and it might get reintroduced during reindex. { - if ref_count_table.id != tables.ref_count.id { + if ref_count_table.id != tables.get_ref_count().id { if let Some((table, sub_index, _ref_count)) = - Self::search_ref_count(address, &tables.ref_count, log)? + Self::search_ref_count(address, tables.get_ref_count(), log)? { table.write_remove_plan(address, sub_index, log)?; } @@ -923,14 +939,14 @@ impl HashColumn { )> { let mut outcome = PlanOutcome::Written; while let PlanOutcome::NeedReindex = - tables.ref_count.write_insert_plan(address, ref_count, None, log)? + tables.get_ref_count().write_insert_plan(address, ref_count, None, log)? { - log::debug!(target: "parity-db", "{}: Ref count chunk full {}", tables.ref_count.id, address); + log::debug!(target: "parity-db", "{}: Ref count chunk full {}", tables.get_ref_count().id, address); (tables, reindex) = Self::trigger_ref_count_reindex(tables, reindex, self.path.as_path()); outcome = PlanOutcome::NeedReindex; } - let (test_ref_count, _test_sub_index) = tables.ref_count.get(address, log)?.unwrap(); + let (test_ref_count, _test_sub_index) = tables.get_ref_count().get(address, log)?.unwrap(); assert!(test_ref_count == ref_count); Ok((outcome, tables, reindex)) } @@ -1156,7 +1172,7 @@ impl HashColumn { if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); let new_ref_count = ref_count + 1; - if table.id == tables.ref_count.id { + if table.id == tables.get_ref_count().id { self.write_ref_count_plan_existing( &tables, &reindex, @@ -1192,7 +1208,7 @@ impl HashColumn { assert!(ref_count > 1); let new_ref_count = ref_count - 1; let new_ref_count = if new_ref_count > 1 { Some(new_ref_count) } else { None }; - let outcome = if new_ref_count.is_some() && table.id != tables.ref_count.id { + let outcome = if new_ref_count.is_some() && table.id != tables.get_ref_count().id { let (r, _, _) = self.write_ref_count_plan_new( tables, reindex, @@ -1253,8 +1269,8 @@ impl HashColumn { tables.value[record.table.size_tier() as usize].enact_plan(record.index, log)?; }, LogAction::InsertRefCount(record) => { - if tables.ref_count.id == record.table { - tables.ref_count.enact_plan(record.index, log)?; + if tables.get_ref_count().id == record.table { + tables.get_ref_count().enact_plan(record.index, log)?; } else if let Some(table) = reindex .queue .iter() @@ -1318,8 +1334,8 @@ impl HashColumn { tables.value[record.table.size_tier() as usize].validate_plan(record.index, log)?; }, LogAction::InsertRefCount(record) => { - if tables.ref_count.id == record.table { - tables.ref_count.validate_plan(record.index, log)?; + if tables.get_ref_count().id == record.table { + tables.get_ref_count().validate_plan(record.index, log)?; } else if let Some(table) = reindex .queue .iter() @@ -1328,9 +1344,9 @@ impl HashColumn { { table.validate_plan(record.index, log)?; } else { - if record.table.index_bits() < tables.ref_count.id.index_bits() { + if record.table.index_bits() < tables.get_ref_count().id.index_bits() { // Insertion into a previously dropped ref count. - log::warn!( target: "parity-db", "Ref count {} is too old. Current is {}", record.table, tables.ref_count.id); + log::warn!( target: "parity-db", "Ref count {} is too old. Current is {}", record.table, tables.get_ref_count().id); return Err(Error::Corruption("Unexpected log ref count id".to_string())) } // Re-launch previously started reindex @@ -1708,10 +1724,10 @@ impl HashColumn { if progress != source.id.total_chunks() { let mut source_index = progress; if source_index % 500 == 0 { - log::debug!(target: "parity-db", "{}: Reindexing ref count at {}/{}", tables.ref_count.id, source_index, source.id.total_chunks()); + log::debug!(target: "parity-db", "{}: Reindexing ref count at {}/{}", tables.get_ref_count().id, source_index, source.id.total_chunks()); } ref_count_source = Some(source.id); - log::debug!(target: "parity-db", "{}: Continue reindex ref count at {}/{}", tables.ref_count.id, source_index, source.id.total_chunks()); + log::debug!(target: "parity-db", "{}: Continue reindex ref count at {}/{}", tables.get_ref_count().id, source_index, source.id.total_chunks()); while source_index < source.id.total_chunks() && ref_count_plan.len() < MAX_REINDEX_BATCH { @@ -1725,10 +1741,10 @@ impl HashColumn { } source_index += 1; } - log::trace!(target: "parity-db", "{}: End reindex ref count batch {} ({})", tables.ref_count.id, source_index, ref_count_plan.len()); + log::trace!(target: "parity-db", "{}: End reindex ref count batch {} ({})", tables.get_ref_count().id, source_index, ref_count_plan.len()); reindex.progress.store(source_index, Ordering::Relaxed); if source_index == source.id.total_chunks() { - log::info!(target: "parity-db", "Completed reindex ref count {} into {}", source.id, tables.ref_count.id); + log::info!(target: "parity-db", "Completed reindex ref count {} into {}", source.id, tables.get_ref_count().id); drop_ref_count = Some(source.id); } }, From 5709d13120a1a8faaed74599c2c0788f980ea5d4 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 5 Oct 2023 11:48:28 +0200 Subject: [PATCH 28/53] Multitree stress fix for appending to existing database --- admin/src/multitree_bench/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index ae576775..b2683c61 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -1254,8 +1254,8 @@ pub fn run_internal(args: Args, db: Db) -> Result<(), String> { if args.empty_on_shutdown && args.pruning > 0 { // Continue removing trees until they are all gone. - TARGET_NUM_REMOVED.store(args.commits, Ordering::SeqCst); - while NUM_REMOVED.load(Ordering::Relaxed) < args.commits { + TARGET_NUM_REMOVED.store(start_commit + args.commits, Ordering::SeqCst); + while NUM_REMOVED.load(Ordering::Relaxed) < start_commit + args.commits { thread::sleep(std::time::Duration::from_millis(50)); } From 29e2070b4589b3bf5d09da93a0a1e03c06581246 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 12 Oct 2023 13:49:18 +0100 Subject: [PATCH 29/53] On restart table data needs to be generated after all log files have been enacted --- src/column.rs | 15 +++++++++++++++ src/db.rs | 10 +++++++++- src/table.rs | 39 ++++++++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/column.rs b/src/column.rs index c580dec5..ad6ec2dc 100644 --- a/src/column.rs +++ b/src/column.rs @@ -471,6 +471,14 @@ impl HashColumn { }) } + pub fn init_table_data(&mut self) -> Result<()> { + let mut tables = self.tables.write(); + for table in &mut tables.value { + table.init_table_data()?; + } + Ok(()) + } + pub fn hash_key(&self, key: &[u8]) -> Key { hash_key(key, &self.salt, self.uniform_keys, self.db_version) } @@ -1980,6 +1988,13 @@ impl Column { } } + pub fn init_table_data(&mut self) -> Result<()> { + match self { + Column::Hash(column) => column.init_table_data(), + Column::Tree(_column) => Ok(()), + } + } + pub fn flush(&self) -> Result<()> { match self { Column::Hash(column) => column.flush(), diff --git a/src/db.rs b/src/db.rs index 2e65120a..bf2c726f 100644 --- a/src/db.rs +++ b/src/db.rs @@ -252,6 +252,13 @@ impl DbInner { }) } + fn init_table_data(&mut self) -> Result<()> { + for column in &mut self.columns { + column.init_table_data()?; + } + Ok(()) + } + fn get(&self, col: ColId, key: &[u8], external_call: bool) -> Result> { if self.options.columns[col as usize].multitree && external_call { return Err(Error::InvalidConfiguration( @@ -1386,7 +1393,7 @@ impl Db { fn open_inner(options: &Options, opening_mode: OpeningMode) -> Result { assert!(options.is_valid()); - let db = DbInner::open(options, opening_mode)?; + let mut db = DbInner::open(options, opening_mode)?; // This needs to be call before log thread: so first reindexing // will run in correct state. if let Err(e) = db.replay_all_logs() { @@ -1397,6 +1404,7 @@ impl Db { db.clean_all_logs()?; db.log.kill_logs()?; } + db.init_table_data()?; let db = Arc::new(db); #[cfg(any(test, feature = "instrumentation"))] let start_threads = opening_mode != OpeningMode::ReadOnly && options.with_background_thread; diff --git a/src/table.rs b/src/table.rs index 0ef74d00..bac999fc 100644 --- a/src/table.rs +++ b/src/table.rs @@ -140,6 +140,7 @@ pub struct ValueTable { filled: AtomicU64, last_removed: AtomicU64, dirty_header: AtomicBool, + needs_free_entries: bool, free_entries: Option>, multipart: bool, ref_counted: bool, @@ -411,10 +412,29 @@ impl ValueTable { log::debug!(target: "parity-db", "Opened value table {} with {} entries, entry_size={}, removed={}", id, filled, entry_size, last_removed); } - let free_entries = if options.multitree { + Ok(ValueTable { + id, + entry_size, + file, + filled: AtomicU64::new(filled), + last_removed: AtomicU64::new(last_removed), + dirty_header: AtomicBool::new(false), + needs_free_entries: options.multitree, + free_entries: None, + multipart, + ref_counted: options.ref_counted, + db_version, + }) + } + + pub fn init_table_data(&mut self) -> Result<()> { + let free_entries = if self.needs_free_entries { let mut stack: Vec = Default::default(); let mut ordered: BTreeSet = Default::default(); + let filled = self.filled.load(Ordering::Relaxed); + let last_removed = self.last_removed.load(Ordering::Relaxed); + let mut next = last_removed; while next != 0 { if next >= filled { @@ -428,7 +448,7 @@ impl ValueTable { ordered.insert(next); let mut buf = PartialEntry::new_uninit(); - file.read_at(buf.as_mut(), next * entry_size as u64)?; + self.file.read_at(buf.as_mut(), next * self.entry_size as u64)?; buf.skip_size(); next = buf.read_next(); } @@ -437,19 +457,8 @@ impl ValueTable { } else { None }; - - Ok(ValueTable { - id, - entry_size, - file, - filled: AtomicU64::new(filled), - last_removed: AtomicU64::new(last_removed), - dirty_header: AtomicBool::new(false), - free_entries, - multipart, - ref_counted: options.ref_counted, - db_version, - }) + self.free_entries = free_entries; + Ok(()) } pub fn value_size(&self, key: &TableKey) -> Option { From 29c94d329951679ccbe9964794626361b235ab5c Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 19 Oct 2023 12:15:36 +0100 Subject: [PATCH 30/53] In memory ref count cache. Verifies with table. --- src/column.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++--- src/ref_count.rs | 10 ++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/column.rs b/src/column.rs index ad6ec2dc..65f87aa2 100644 --- a/src/column.rs +++ b/src/column.rs @@ -111,6 +111,7 @@ pub struct HashColumn { col: ColId, tables: RwLock, reindex: RwLock, + ref_count_cache: Option>>, path: PathBuf, preimage: bool, uniform_keys: bool, @@ -442,15 +443,19 @@ impl HashColumn { let path = &options.path; let col_options = &metadata.columns[col as usize]; let db_version = metadata.version; - let ref_count = if col_options.multitree && !col_options.append_only { - Some(Self::open_ref_count(&options.path, col, &mut reindexing)?) + let (ref_count, ref_count_cache) = if col_options.multitree && !col_options.append_only { + ( + Some(Self::open_ref_count(&options.path, col, &mut reindexing)?), + Some(RwLock::new(Default::default())), + ) } else { - None + (None, None) }; Ok(HashColumn { col, tables: RwLock::new(Tables { index, value, ref_count }), reindex: RwLock::new(Reindex { queue: reindexing, progress: AtomicU64::new(0) }), + ref_count_cache, path: path.into(), preimage: col_options.preimage, uniform_keys: col_options.uniform, @@ -476,6 +481,36 @@ impl HashColumn { for table in &mut tables.value { table.init_table_data()?; } + + if let Some(cache) = &self.ref_count_cache { + let mut cache = cache.write(); + + for entry in &self.reindex.read().queue { + if let ReindexEntry::RefCount(table) = entry { + for index in 0..table.id.total_chunks() { + let entries = table.table_entries(index)?; + for entry in entries.iter() { + if !entry.is_empty() { + cache.insert(entry.address().as_u64(), entry.ref_count()); + } + } + } + } + } + + let table = &tables.ref_count; + if let Some(table) = table { + for index in 0..table.id.total_chunks() { + let entries = table.table_entries(index)?; + for entry in entries.iter() { + if !entry.is_empty() { + cache.insert(entry.address().as_u64(), entry.ref_count()); + } + } + } + } + } + Ok(()) } @@ -1175,11 +1210,20 @@ impl HashColumn { let tables = self.tables.upgradable_read(); let reindex = self.reindex.upgradable_read(); let address = Address::from_u64(address); + let cached = self + .ref_count_cache + .as_ref() + .map_or(None, |c| c.read().get(&address.as_u64()).cloned()); let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); + assert!(cached.is_some()); + assert!(ref_count == cached.unwrap()); let new_ref_count = ref_count + 1; + self.ref_count_cache + .as_ref() + .map(|c| c.write().insert(address.as_u64(), new_ref_count)); if table.id == tables.get_ref_count().id { self.write_ref_count_plan_existing( &tables, @@ -1197,6 +1241,8 @@ impl HashColumn { } else { // inc ref is only called on addresses that already exist, so we know they must have // only 1 reference. + assert!(cached.is_none()); + self.ref_count_cache.as_ref().map(|c| c.write().insert(address.as_u64(), 2)); let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, 2, log)?; Ok(r) } @@ -1210,11 +1256,24 @@ impl HashColumn { let tables = self.tables.upgradable_read(); let reindex = self.reindex.upgradable_read(); let address = Address::from_u64(address); + let cached = self + .ref_count_cache + .as_ref() + .map_or(None, |c| c.read().get(&address.as_u64()).cloned()); let existing: Option<(&RefCountTable, usize, u64)> = Self::search_all_ref_count(address, &tables, &reindex, log)?; if let Some((table, sub_index, ref_count)) = existing { assert!(ref_count > 1); + assert!(cached.is_some()); + assert!(ref_count == cached.unwrap()); let new_ref_count = ref_count - 1; + self.ref_count_cache.as_ref().map(|c| { + if new_ref_count > 1 { + c.write().insert(address.as_u64(), new_ref_count); + } else { + c.write().remove(&address.as_u64()); + } + }); let new_ref_count = if new_ref_count > 1 { Some(new_ref_count) } else { None }; let outcome = if new_ref_count.is_some() && table.id != tables.get_ref_count().id { let (r, _, _) = self.write_ref_count_plan_new( diff --git a/src/ref_count.rs b/src/ref_count.rs index c579f2e9..bfe66bdd 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -206,6 +206,16 @@ impl RefCountTable { Ok(Self::transmute_chunk(EMPTY_CHUNK)) } + pub fn table_entries(&self, chunk_index: u64) -> Result<[Entry; CHUNK_ENTRIES]> { + let mut chunk = [0; CHUNK_LEN]; + if let Some(map) = &*self.map.read() { + let source = Self::chunk_at(chunk_index, map)?; + chunk.copy_from_slice(source); + return Ok(Self::transmute_chunk(chunk)) + } + Ok(Self::transmute_chunk(EMPTY_CHUNK)) + } + #[inline(always)] fn transmute_chunk(chunk: [u8; CHUNK_LEN]) -> [Entry; CHUNK_ENTRIES] { let mut result: [Entry; CHUNK_ENTRIES] = unsafe { std::mem::transmute(chunk) }; From 8ac418e2fa9df02c7b5a801db19478d8c9fed3d2 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 19 Oct 2023 15:18:39 +0100 Subject: [PATCH 31/53] Only access ref count table when needed --- src/column.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/column.rs b/src/column.rs index 65f87aa2..aa268a03 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1214,13 +1214,13 @@ impl HashColumn { .ref_count_cache .as_ref() .map_or(None, |c| c.read().get(&address.as_u64()).cloned()); - let existing: Option<(&RefCountTable, usize, u64)> = - Self::search_all_ref_count(address, &tables, &reindex, log)?; - if let Some((table, sub_index, ref_count)) = existing { - assert!(ref_count > 1); - assert!(cached.is_some()); - assert!(ref_count == cached.unwrap()); - let new_ref_count = ref_count + 1; + if let Some(cached_ref_count) = cached { + let existing: Option<(&RefCountTable, usize, u64)> = + Self::search_all_ref_count(address, &tables, &reindex, log)?; + let (table, sub_index, table_ref_count) = existing.unwrap(); + assert!(cached_ref_count > 1); + assert!(table_ref_count == cached_ref_count); + let new_ref_count = cached_ref_count + 1; self.ref_count_cache .as_ref() .map(|c| c.write().insert(address.as_u64(), new_ref_count)); @@ -1241,7 +1241,6 @@ impl HashColumn { } else { // inc ref is only called on addresses that already exist, so we know they must have // only 1 reference. - assert!(cached.is_none()); self.ref_count_cache.as_ref().map(|c| c.write().insert(address.as_u64(), 2)); let (r, _, _) = self.write_ref_count_plan_new(tables, reindex, address, 2, log)?; Ok(r) @@ -1260,13 +1259,13 @@ impl HashColumn { .ref_count_cache .as_ref() .map_or(None, |c| c.read().get(&address.as_u64()).cloned()); - let existing: Option<(&RefCountTable, usize, u64)> = - Self::search_all_ref_count(address, &tables, &reindex, log)?; - if let Some((table, sub_index, ref_count)) = existing { - assert!(ref_count > 1); - assert!(cached.is_some()); - assert!(ref_count == cached.unwrap()); - let new_ref_count = ref_count - 1; + if let Some(cached_ref_count) = cached { + let existing: Option<(&RefCountTable, usize, u64)> = + Self::search_all_ref_count(address, &tables, &reindex, log)?; + let (table, sub_index, table_ref_count) = existing.unwrap(); + assert!(cached_ref_count > 1); + assert!(table_ref_count == cached_ref_count); + let new_ref_count = cached_ref_count - 1; self.ref_count_cache.as_ref().map(|c| { if new_ref_count > 1 { c.write().insert(address.as_u64(), new_ref_count); From b943f2106fdd72f8047fe06b891284f2b169e4cf Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 24 Oct 2023 12:49:03 +0100 Subject: [PATCH 32/53] Rename --- src/column.rs | 2 +- src/table.rs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/column.rs b/src/column.rs index fa5cc63c..4c6d31e5 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1139,7 +1139,7 @@ impl HashColumn { let mut tier_addresses: HashMap> = Default::default(); let mut tier_index: HashMap = Default::default(); for (tier, count) in tier_count { - let offsets = values.tables[tier].claim_contiguous_entries(count, 8)?; + let offsets = values.tables[tier].claim_entries(count)?; tier_addresses.insert(tier, offsets); tier_index.insert(tier, 0); } diff --git a/src/table.rs b/src/table.rs index 85abed2f..f207a973 100644 --- a/src/table.rs +++ b/src/table.rs @@ -799,11 +799,7 @@ impl ValueTable { } } - pub fn claim_contiguous_entries( - &self, - num: usize, - _min_span_length: usize, - ) -> Result> { + pub fn claim_entries(&self, num: usize) -> Result> { let mut entries: Vec = Default::default(); for _i in 0..num { entries.push(self.claim_next_free()?); From d8fb0a0ac46033b1f10b4deb084fcd51bb6cf3cd Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 24 Oct 2023 12:51:43 +0100 Subject: [PATCH 33/53] Remove commented out lines --- src/db.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/db.rs b/src/db.rs index 19bc906c..bec7a6b1 100644 --- a/src/db.rs +++ b/src/db.rs @@ -2155,10 +2155,8 @@ impl IndexedChangeSet { if rc == 1 { let tree = db.get_tree(db, col, key, false).unwrap(); if let Some(tree) = tree { - //println!("Locking tree {:?}", &key[0..3]); let guard = tree.write(); let mut num_removed = 0; - //println!("Dereferencing tree {:?}", &key[0..3]); self.write_dereference_children_plan( column, &guard, From 551bbab5f225c79bf4238cb20f5c7df375ab5d3a Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 25 Oct 2023 12:59:33 +0100 Subject: [PATCH 34/53] madvise --- src/ref_count.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/ref_count.rs b/src/ref_count.rs index bfe66bdd..da22525b 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -4,6 +4,7 @@ use crate::{ column::ColId, error::{try_io, Error, Result}, + file::madvise_random, index::{Address, PlanOutcome}, log::{LogQuery, LogReader, LogWriter}, parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, @@ -139,7 +140,8 @@ impl RefCountTable { }; try_io!(file.set_len(file_size(id.index_bits()))); - let map = try_io!(unsafe { memmap2::MmapMut::map_mut(&file) }); + let mut map = try_io!(unsafe { memmap2::MmapMut::map_mut(&file) }); + madvise_random(&mut map); log::debug!(target: "parity-db", "Opened existing refcount table {}", id); Ok(Some(RefCountTable { id, path, map: RwLock::new(Some(map)) })) } @@ -362,10 +364,9 @@ impl RefCountTable { .create_new(true) .open(self.path.as_path())); log::debug!(target: "parity-db", "Created new ref count {}", self.id); - //TODO: check for potential overflows on 32-bit platforms try_io!(file.set_len(file_size(self.id.index_bits()))); let mut mmap = try_io!(unsafe { memmap2::MmapMut::map_mut(&file) }); - self.madvise_random(&mut mmap); + madvise_random(&mut mmap); *wmap = Some(mmap); map = RwLockWriteGuard::downgrade_to_upgradable(wmap); } @@ -439,20 +440,6 @@ impl RefCountTable { } Ok(()) } - - #[cfg(unix)] - fn madvise_random(&self, map: &mut memmap2::MmapMut) { - unsafe { - libc::madvise( - map.as_mut_ptr() as _, - file_size(self.id.index_bits()) as usize, - libc::MADV_RANDOM, - ); - } - } - - #[cfg(not(unix))] - fn madvise_random(&self, _map: &mut memmap2::MmapMut) {} } #[cfg(test)] From 9e7032feb4dcec42bb9e7aaa2051f76d6169a210 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 25 Oct 2023 14:22:57 +0100 Subject: [PATCH 35/53] Ref count overlay reclaiming --- src/column.rs | 2 +- src/log.rs | 33 ++++++++++++++++++++++++--------- src/ref_count.rs | 16 +++++++++++++++- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/column.rs b/src/column.rs index 4c6d31e5..9ac9266d 100644 --- a/src/column.rs +++ b/src/column.rs @@ -30,7 +30,7 @@ use std::{ }; pub const MIN_INDEX_BITS: u8 = 16; -const MIN_REF_COUNT_BITS: u8 = 11; +pub const MIN_REF_COUNT_BITS: u8 = 11; // Measured in index entries const MAX_REINDEX_BATCH: usize = 8192; diff --git a/src/log.rs b/src/log.rs index 494a127e..4cf73f7d 100644 --- a/src/log.rs +++ b/src/log.rs @@ -33,6 +33,8 @@ const INDEX_OVERLAY_RECLAIM_FACTOR: usize = 10; const VALUE_OVERLAY_RECLAIM_FACTOR: usize = 10; // Min number of value items to initiate reclaim. Each item is around 40 bytes. const VALUE_OVERLAY_MIN_RECLAIM_ITEMS: usize = 10240; +// Once ref count overly uses less than 1/10 of its capacity, it will be reclaimed. +const REF_COUNT_OVERLAY_RECLAIM_FACTOR: usize = 10; #[derive(Debug)] pub struct InsertIndexAction { @@ -89,7 +91,7 @@ pub trait LogQuery { pub struct LogOverlays { index: Vec, value: Vec, - ref_count: HashMap, + ref_count: Vec, last_record_ids: Vec, } @@ -106,7 +108,9 @@ impl LogOverlays { value: (0..ValueTableId::max_log_tables(count)) .map(|_| ValueLogOverlay::default()) .collect(), - ref_count: Default::default(), + ref_count: (0..RefCountTableId::max_log_indicies(count)) + .map(|_| RefCountLogOverlay::default()) + .collect(), last_record_ids: (0..count).map(|_| 0).collect(), } } @@ -172,7 +176,7 @@ impl LogQuery for RwLock { index: u64, f: F, ) -> Option { - self.read().ref_count(table, index, f) + (&*self.read()).ref_count(table, index, f) } } @@ -216,7 +220,7 @@ impl LogQuery for LogOverlays { f: F, ) -> Option { self.ref_count - .get(&table) + .get(table.log_index()) .and_then(|o| o.map.get(&index).map(|(_id, _mask, data)| f(data))) } } @@ -818,7 +822,9 @@ impl Log { for o in overlays.value.iter_mut() { o.map.clear(); } - overlays.ref_count.clear(); + for o in overlays.ref_count.iter_mut() { + o.map.clear(); + } for r in overlays.last_record_ids.iter_mut() { *r = 0; } @@ -871,7 +877,7 @@ impl Log { let mut total_ref_count = 0; for (id, overlay) in ref_count.into_iter() { total_ref_count += overlay.map.len(); - overlays.ref_count.entry(id).or_default().map.extend(overlay.map.into_iter()); + overlays.ref_count[id.log_index()].map.extend(overlay.map.into_iter()); } log::debug!( @@ -911,7 +917,7 @@ impl Log { } } for (table, index) in cleared.ref_count.into_iter() { - if let Some(ref mut overlay) = overlays.ref_count.get_mut(&table) { + if let Some(ref mut overlay) = overlays.ref_count.get_mut(table.log_index()) { if let std::collections::hash_map::Entry::Occupied(e) = overlay.map.entry(index) { if e.get().0 == record_id { e.remove_entry(); @@ -944,8 +950,17 @@ impl Log { o.map.shrink_to_fit(); } } - // Cleanup ref count overlays - overlays.ref_count.retain(|_, overlay| !overlay.map.is_empty()); + for (i, o) in overlays.ref_count.iter_mut().enumerate() { + if o.map.capacity() > o.map.len() * REF_COUNT_OVERLAY_RECLAIM_FACTOR { + log::trace!( + "Schrinking ref count overlay {}: {}/{}", + RefCountTableId::from_log_index(i), + o.map.len(), + o.map.capacity(), + ); + o.map.shrink_to_fit(); + } + } } pub fn flush_one(&self, min_size: u64) -> Result { diff --git a/src/ref_count.rs b/src/ref_count.rs index da22525b..e0741d49 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or MIT. use crate::{ - column::ColId, + column::{ColId, MIN_REF_COUNT_BITS}, error::{try_io, Error, Result}, file::madvise_random, index::{Address, PlanOutcome}, @@ -117,6 +117,20 @@ impl RefCountTableId { pub fn total_chunks(&self) -> u64 { total_chunks(self.index_bits()) } + + pub fn log_index(&self) -> usize { + self.col() as usize * (64 - MIN_REF_COUNT_BITS) as usize + self.index_bits() as usize + } + + pub fn from_log_index(i: usize) -> Self { + let col = i / (64 - MIN_REF_COUNT_BITS) as usize; + let bits = i % (64 - MIN_REF_COUNT_BITS) as usize; + RefCountTableId::new(col as ColId, bits as u8) + } + + pub const fn max_log_indicies(num_columns: usize) -> usize { + (64 - MIN_REF_COUNT_BITS) as usize * num_columns + } } impl std::fmt::Display for RefCountTableId { From a0e66e105a3137a96d033cb6aac8eb1c591ace6f Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 25 Oct 2023 16:00:09 +0100 Subject: [PATCH 36/53] Chunk buffer alignment --- src/log.rs | 8 ++--- src/ref_count.rs | 82 +++++++++++++++++++++--------------------------- 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/src/log.rs b/src/log.rs index 4cf73f7d..f1b2caf1 100644 --- a/src/log.rs +++ b/src/log.rs @@ -444,7 +444,7 @@ impl LogChange { let i = mask.trailing_zeros(); mask &= !(1 << i); write( - &chunk[i as usize * REF_COUNT_ENTRY_BYTES.. + &chunk.0[i as usize * REF_COUNT_ENTRY_BYTES.. (i as usize + 1) * REF_COUNT_ENTRY_BYTES], )?; } @@ -522,14 +522,14 @@ impl<'a> LogWriter<'a> { table: RefCountTableId, index: u64, sub: u8, - data: &RefCountChunk, + data: RefCountChunk, ) { match self.log.local_ref_count.entry(table).or_default().map.entry(index) { std::collections::hash_map::Entry::Occupied(mut entry) => { - *entry.get_mut() = (self.log.record_id, entry.get().1 | (1 << sub), *data); + *entry.get_mut() = (self.log.record_id, entry.get().1 | (1 << sub), data); }, std::collections::hash_map::Entry::Vacant(entry) => { - entry.insert((self.log.record_id, 1 << sub, *data)); + entry.insert((self.log.record_id, 1 << sub, data)); }, } } diff --git a/src/ref_count.rs b/src/ref_count.rs index e0741d49..42932f05 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -22,9 +22,12 @@ const META_SIZE: usize = 0; const ENTRY_BITS: u8 = 128; pub const ENTRY_BYTES: usize = ENTRY_BITS as usize / 8; -const EMPTY_CHUNK: Chunk = [0u8; CHUNK_LEN]; +const EMPTY_CHUNK: Chunk = Chunk([0u8; CHUNK_LEN]); +const EMPTY_ENTRIES: [Entry; CHUNK_ENTRIES] = [Entry::empty(); CHUNK_ENTRIES]; -pub type Chunk = [u8; CHUNK_LEN]; +#[repr(C, align(8))] +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct Chunk(pub [u8; CHUNK_LEN]); #[derive(PartialEq, Eq, Clone, Copy)] pub struct Entry(u64, u64); @@ -54,7 +57,7 @@ impl Entry { self.0 as u128 | (self.1 as u128) << 64 } - fn empty() -> Self { + const fn empty() -> Self { Entry(0, 0) } @@ -166,17 +169,17 @@ impl RefCountTable { RefCountTable { id, path, map: RwLock::new(None) } } - fn chunk_at(index: u64, map: &memmap2::MmapMut) -> Result<&[u8; CHUNK_LEN]> { + fn chunk_at(index: u64, map: &memmap2::MmapMut) -> Result<&Chunk> { let offset = META_SIZE + index as usize * CHUNK_LEN; - let ptr = unsafe { &*(map[offset..offset + CHUNK_LEN].as_ptr() as *const [u8; CHUNK_LEN]) }; + let ptr = unsafe { &*(map[offset..offset + CHUNK_LEN].as_ptr() as *const Chunk) }; Ok(try_io!(Ok(ptr))) } - fn find_entry(&self, address: u64, chunk: &[u8; CHUNK_LEN]) -> Option<(Entry, usize)> { + fn find_entry(&self, address: u64, chunk: &Chunk) -> Option<(Entry, usize)> { self.find_entry_base(address, chunk) } - fn find_entry_base(&self, address: u64, chunk: &[u8; CHUNK_LEN]) -> Option<(Entry, usize)> { + fn find_entry_base(&self, address: u64, chunk: &Chunk) -> Option<(Entry, usize)> { for i in 0..CHUNK_ENTRIES { let entry = Self::read_entry(chunk, i); if entry.address().as_u64() == address && !entry.is_empty() { @@ -208,52 +211,41 @@ impl RefCountTable { } pub fn entries(&self, chunk_index: u64, log: &impl LogQuery) -> Result<[Entry; CHUNK_ENTRIES]> { - let mut chunk = [0; CHUNK_LEN]; if let Some(entry) = - log.ref_count(self.id, chunk_index, |chunk| Self::transmute_chunk(*chunk)) + log.ref_count(self.id, chunk_index, |chunk| *Self::transmute_chunk(chunk)) { return Ok(entry) } if let Some(map) = &*self.map.read() { - let source = Self::chunk_at(chunk_index, map)?; - chunk.copy_from_slice(source); - return Ok(Self::transmute_chunk(chunk)) + let chunk = Self::chunk_at(chunk_index, map)?; + return Ok(*Self::transmute_chunk(chunk)) } - Ok(Self::transmute_chunk(EMPTY_CHUNK)) + Ok(EMPTY_ENTRIES) } pub fn table_entries(&self, chunk_index: u64) -> Result<[Entry; CHUNK_ENTRIES]> { - let mut chunk = [0; CHUNK_LEN]; if let Some(map) = &*self.map.read() { - let source = Self::chunk_at(chunk_index, map)?; - chunk.copy_from_slice(source); - return Ok(Self::transmute_chunk(chunk)) + let chunk = Self::chunk_at(chunk_index, map)?; + return Ok(*Self::transmute_chunk(chunk)) } - Ok(Self::transmute_chunk(EMPTY_CHUNK)) + Ok(EMPTY_ENTRIES) } #[inline(always)] - fn transmute_chunk(chunk: [u8; CHUNK_LEN]) -> [Entry; CHUNK_ENTRIES] { - let mut result: [Entry; CHUNK_ENTRIES] = unsafe { std::mem::transmute(chunk) }; - if !cfg!(target_endian = "little") { - for item in result.iter_mut() { - // TODO: Confirm this is correct - *item = Entry::from_u128(u128::from_le(item.as_u128())); - } - } - result + fn transmute_chunk(chunk: &Chunk) -> &[Entry; CHUNK_ENTRIES] { + unsafe { std::mem::transmute(chunk) } } #[inline(always)] - fn write_entry(entry: &Entry, at: usize, chunk: &mut [u8; CHUNK_LEN]) { - chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES] + fn write_entry(entry: &Entry, at: usize, chunk: &mut Chunk) { + chunk.0[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES] .copy_from_slice(&entry.as_u128().to_le_bytes()); } #[inline(always)] - fn read_entry(chunk: &[u8; CHUNK_LEN], at: usize) -> Entry { + fn read_entry(chunk: &Chunk, at: usize) -> Entry { Entry::from_u128(u128::from_le_bytes( - chunk[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].try_into().unwrap(), + chunk.0[at * ENTRY_BYTES..at * ENTRY_BYTES + ENTRY_BYTES].try_into().unwrap(), )) } @@ -270,20 +262,18 @@ impl RefCountTable { &self, address: Address, ref_count: u64, - source: &[u8], + mut chunk: Chunk, sub_index: Option, log: &mut LogWriter, ) -> Result { let chunk_index = self.chunk_index(address); - let mut chunk = [0; CHUNK_LEN]; - chunk.copy_from_slice(source); let new_entry = Entry::new(address, ref_count); if let Some(i) = sub_index { let entry = Self::read_entry(&chunk, i); assert_eq!(entry.address(), new_entry.address()); Self::write_entry(&new_entry, i, &mut chunk); log::trace!(target: "parity-db", "{}: Replaced ref count at {}.{}: {}", self.id, chunk_index, i, new_entry.address()); - log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + log.insert_ref_count(self.id, chunk_index, i as u8, chunk); return Ok(PlanOutcome::Written) } for i in 0..CHUNK_ENTRIES { @@ -291,7 +281,7 @@ impl RefCountTable { if entry.is_empty() { Self::write_entry(&new_entry, i, &mut chunk); log::trace!(target: "parity-db", "{}: Inserted ref count at {}.{}: {}", self.id, chunk_index, i, new_entry.address()); - log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + log.insert_ref_count(self.id, chunk_index, i as u8, chunk); return Ok(PlanOutcome::Written) } } @@ -309,28 +299,26 @@ impl RefCountTable { log::trace!(target: "parity-db", "{}: Inserting ref count {} -> {}", self.id, address, ref_count); let chunk_index = self.chunk_index(address); - if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| *chunk) { - return self.plan_insert_chunk(address, ref_count, &chunk, sub_index, log) + if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| chunk.clone()) { + return self.plan_insert_chunk(address, ref_count, chunk, sub_index, log) } if let Some(map) = &*self.map.read() { - let chunk = Self::chunk_at(chunk_index, map)?; + let chunk = Self::chunk_at(chunk_index, map)?.clone(); return self.plan_insert_chunk(address, ref_count, chunk, sub_index, log) } - let chunk = &EMPTY_CHUNK; + let chunk = EMPTY_CHUNK.clone(); self.plan_insert_chunk(address, ref_count, chunk, sub_index, log) } fn plan_remove_chunk( &self, address: Address, - source: &[u8], + mut chunk: Chunk, sub_index: usize, log: &mut LogWriter, ) -> Result { - let mut chunk = [0; CHUNK_LEN]; - chunk.copy_from_slice(source); let chunk_index = self.chunk_index(address); let i = sub_index; @@ -338,7 +326,7 @@ impl RefCountTable { if !entry.is_empty() && entry.address() == address { let new_entry = Entry::empty(); Self::write_entry(&new_entry, i, &mut chunk); - log.insert_ref_count(self.id, chunk_index, i as u8, &chunk); + log.insert_ref_count(self.id, chunk_index, i as u8, chunk); log::trace!(target: "parity-db", "{}: Removed ref count at {}.{}", self.id, chunk_index, i); return Ok(PlanOutcome::Written) } @@ -355,12 +343,12 @@ impl RefCountTable { log::trace!(target: "parity-db", "{}: Removing ref count {}", self.id, address); let chunk_index = self.chunk_index(address); - if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| *chunk) { - return self.plan_remove_chunk(address, &chunk, sub_index, log) + if let Some(chunk) = log.ref_count(self.id, chunk_index, |chunk| chunk.clone()) { + return self.plan_remove_chunk(address, chunk, sub_index, log) } if let Some(map) = &*self.map.read() { - let chunk = Self::chunk_at(chunk_index, map)?; + let chunk = Self::chunk_at(chunk_index, map)?.clone(); return self.plan_remove_chunk(address, chunk, sub_index, log) } From 001672a0a288a19d5926cae00088c6121bb0ab65 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 26 Oct 2023 11:55:29 +0100 Subject: [PATCH 37/53] Test fix --- src/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db.rs b/src/db.rs index bec7a6b1..76717595 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1702,7 +1702,7 @@ impl Db { #[cfg(feature = "instrumentation")] pub fn process_commits(&self) -> Result<()> { - self.inner.process_commits()?; + self.inner.process_commits(&self.inner)?; Ok(()) } From 29db3407101555258fba1d76b8e28c21d79c17f3 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 26 Oct 2023 12:12:35 +0100 Subject: [PATCH 38/53] Windows fix --- src/ref_count.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ref_count.rs b/src/ref_count.rs index 42932f05..d0ac6dc3 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -9,10 +9,6 @@ use crate::{ log::{LogQuery, LogReader, LogWriter}, parking_lot::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}, }; -#[cfg(target_arch = "x86")] -use std::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use std::arch::x86_64::*; use std::convert::TryInto; const CHUNK_LEN: usize = CHUNK_ENTRIES * ENTRY_BYTES; From 5ffa52834f29d92bcbbca826947f30fa0af0c7d6 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 26 Oct 2023 15:55:43 +0100 Subject: [PATCH 39/53] Fix --- src/index.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/index.rs b/src/index.rs index 3ce1329b..40c0721e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -593,10 +593,8 @@ impl IndexTable { } pub fn drop_file(self) -> Result<()> { - if self.map.read().is_some() { - try_io!(std::fs::remove_file(self.path.as_path())); - } drop(self.map); + try_io!(std::fs::remove_file(self.path.as_path())); log::debug!(target: "parity-db", "{}: Dropped table", self.id); Ok(()) } From 08ae7d185754c22ece1adf5abb916f06236ad900 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 26 Oct 2023 17:40:24 +0100 Subject: [PATCH 40/53] Fix --- src/ref_count.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ref_count.rs b/src/ref_count.rs index d0ac6dc3..9876e9e2 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -423,10 +423,8 @@ impl RefCountTable { } pub fn drop_file(self) -> Result<()> { - if self.map.read().is_some() { - try_io!(std::fs::remove_file(self.path.as_path())); - } drop(self.map); + try_io!(std::fs::remove_file(self.path.as_path())); log::debug!(target: "parity-db", "{}: Dropped ref count table", self.id); Ok(()) } From 3d263d7a52c3b9f8c8048a05ed5ea51c4d7ba3f0 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Sun, 29 Oct 2023 19:15:33 +0000 Subject: [PATCH 41/53] Loom RwLock requires Sized --- admin/src/multitree_bench/mod.rs | 8 ++++---- src/db.rs | 17 +++++++++++------ src/parking_lot.rs | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index b2683c61..f23c215d 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -784,7 +784,7 @@ fn read_value( } struct TreeReaderRef<'d> { - reader_ref: Arc>, + reader_ref: Arc>>, } impl<'d> TreeReaderRef<'d> { @@ -794,11 +794,11 @@ impl<'d> TreeReaderRef<'d> { } struct TreeReaderGuard<'s, 'd: 's> { - lock_guard: RwLockReadGuard<'s, dyn TreeReader + 'd>, + lock_guard: RwLockReadGuard<'s, Box>, } impl<'s, 'd: 's> Deref for TreeReaderGuard<'s, 'd> { - type Target = dyn TreeReader + 'd; + type Target = Box; fn deref(&self) -> &Self::Target { self.lock_guard.deref() @@ -987,7 +987,7 @@ fn iter_children<'a>( depth: u32, generated_children: &mut Vec, database_children: &mut Vec, - reader: &RwLockReadGuard<'a, dyn TreeReader>, + reader: &RwLockReadGuard<'a, Box>, chain_generator: &ChainGenerator, ) -> Result<(), String> { for i in 0..generated_children.len() { diff --git a/src/db.rs b/src/db.rs index 76717595..4714aec1 100644 --- a/src/db.rs +++ b/src/db.rs @@ -138,7 +138,7 @@ struct CommitQueue { #[derive(Debug)] struct Trees { - readers: HashMap>, IdentityBuildHasher>, + readers: HashMap>>, IdentityBuildHasher>, /// Number of queued dereferences for each tree to_dereference: HashMap, } @@ -376,7 +376,7 @@ impl DbInner { col: ColId, key: &[u8], check_existence: bool, - ) -> Result>>> { + ) -> Result>>>> { if !self.options.columns[col as usize].multitree { return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) } @@ -411,8 +411,9 @@ impl DbInner { to_dereference: Default::default(), }); - let reader = - Arc::new(RwLock::new(DbTreeReader { db: db.clone(), col, key: hash_key })); + let reader: Box = + Box::new(DbTreeReader { db: db.clone(), col, key: hash_key }); + let reader = Arc::new(RwLock::new(reader)); column_trees.readers.insert(hash_key, Arc::downgrade(&reader)); @@ -1470,7 +1471,11 @@ impl Db { self.inner.btree_iter(col) } - pub fn get_tree(&self, col: ColId, key: &[u8]) -> Result>>> { + pub fn get_tree( + &self, + col: ColId, + key: &[u8], + ) -> Result>>>> { self.inner.get_tree(&self.inner, col, key, true) } @@ -2178,7 +2183,7 @@ impl IndexedChangeSet { fn write_dereference_children_plan( &self, column: &HashColumn, - guard: &RwLockWriteGuard<'_, dyn TreeReader>, + guard: &RwLockWriteGuard<'_, Box>, children: &Vec, num_removed: &mut u64, writer: &mut crate::log::LogWriter, diff --git a/src/parking_lot.rs b/src/parking_lot.rs index 90ef5735..e10f3bcf 100644 --- a/src/parking_lot.rs +++ b/src/parking_lot.rs @@ -87,6 +87,10 @@ mod with_loom { pub fn write(&self) -> RwLockWriteGuard { RwLockWriteGuard(self.0.write().unwrap()) } + + pub fn is_locked(&self) -> bool { + !self.0.try_write().is_ok() + } } #[derive(Debug)] From 59594a237ad82f4c3c671babb3d3c49c1944062e Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 10 Jan 2024 12:32:15 +0000 Subject: [PATCH 42/53] Debug asserts --- src/db.rs | 6 +++--- src/table.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/db.rs b/src/db.rs index 4714aec1..76bc1359 100644 --- a/src/db.rs +++ b/src/db.rs @@ -920,7 +920,7 @@ impl DbInner { ref_count_batch_source, } = column.reindex(&self.log)?; if !batch.is_empty() || drop_index.is_some() { - assert!( + debug_assert!( ref_count_batch.is_empty() && ref_count_batch_source.is_none() && drop_ref_count.is_none() @@ -961,8 +961,8 @@ impl DbInner { return Ok(true) } if !ref_count_batch.is_empty() || drop_ref_count.is_some() { - assert!(batch.is_empty() && drop_index.is_none()); - assert!(ref_count_batch_source.is_some()); + debug_assert!(batch.is_empty() && drop_index.is_none()); + debug_assert!(ref_count_batch_source.is_some()); let ref_count_source = ref_count_batch_source.unwrap(); let mut next_reindex = false; let mut writer = self.log.begin_record(); diff --git a/src/table.rs b/src/table.rs index f207a973..14b95366 100644 --- a/src/table.rs +++ b/src/table.rs @@ -751,7 +751,7 @@ impl ValueTable { self.last_removed.store(next_removed, Ordering::Relaxed); if let Some(mut free_entries) = free_entries_guard { let last = free_entries.stack.pop().unwrap(); - assert_eq!(last, last_removed); + debug_assert_eq!(last, last_removed); free_entries.ordered.remove(&last_removed); } last_removed @@ -778,7 +778,7 @@ impl ValueTable { let last_removed = self.last_removed.load(Ordering::Relaxed); let index = if last_removed != 0 { let last = free_entries.stack.pop().unwrap(); - assert_eq!(last, last_removed); + debug_assert_eq!(last, last_removed); free_entries.ordered.remove(&last_removed); let next_removed = *free_entries.stack.last().unwrap_or(&0u64); From b1e90f028397ccef22db4cb71bdac2a237801a5b Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 10 Jan 2024 12:44:18 +0000 Subject: [PATCH 43/53] Use INFO_COLUMN as column index --- admin/src/lib.rs | 2 +- admin/src/multitree_bench/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/src/lib.rs b/admin/src/lib.rs index c1aa03e0..9f3673ff 100644 --- a/admin/src/lib.rs +++ b/admin/src/lib.rs @@ -157,7 +157,7 @@ pub fn run() -> Result<(), String> { db_options.columns.push(info_column); } - let info_column = &mut db_options.columns[1]; + let info_column = &mut db_options.columns[multitree_bench::INFO_COLUMN as usize]; info_column.uniform = false; info_column.multitree = false; info_column.ref_counted = false; diff --git a/admin/src/multitree_bench/mod.rs b/admin/src/multitree_bench/mod.rs index f23c215d..c7464110 100644 --- a/admin/src/multitree_bench/mod.rs +++ b/admin/src/multitree_bench/mod.rs @@ -33,8 +33,8 @@ static EXPECTED_NUM_ENTRIES: AtomicUsize = AtomicUsize::new(0); static NUM_PATHS: AtomicUsize = AtomicUsize::new(0); static NUM_PATHS_SUCCESS: AtomicUsize = AtomicUsize::new(0); -const TREE_COLUMN: u8 = 0; -const INFO_COLUMN: u8 = 1; +pub const TREE_COLUMN: u8 = 0; +pub const INFO_COLUMN: u8 = 1; const KEY_LAST_COMMIT: Key = [1u8; 32]; const KEY_NUM_REMOVED: Key = [2u8; 32]; From 9662b92bca628e4c442722aa3ffea96363ebe2ac Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 10 Jan 2024 12:48:01 +0000 Subject: [PATCH 44/53] Avoid changing existing log action values --- src/log.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/log.rs b/src/log.rs index f1b2caf1..46ada1cb 100644 --- a/src/log.rs +++ b/src/log.rs @@ -22,9 +22,9 @@ const MAX_LOG_POOL_SIZE: usize = 16; const BEGIN_RECORD: u8 = 1; const INSERT_INDEX: u8 = 2; const INSERT_VALUE: u8 = 3; -const INSERT_REF_COUNT: u8 = 4; -const END_RECORD: u8 = 5; -const DROP_TABLE: u8 = 6; +const END_RECORD: u8 = 4; +const DROP_TABLE: u8 = 5; +const INSERT_REF_COUNT: u8 = 6; const DROP_REF_COUNT_TABLE: u8 = 7; // Once index overly uses less than 1/10 of its capacity, it will be reclaimed. From 0077b00d74037fd5a0aaa55ef4c254d6c7921ff7 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Wed, 10 Jan 2024 13:02:35 +0000 Subject: [PATCH 45/53] Typo --- src/log.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log.rs b/src/log.rs index 46ada1cb..c40cee60 100644 --- a/src/log.rs +++ b/src/log.rs @@ -33,7 +33,7 @@ const INDEX_OVERLAY_RECLAIM_FACTOR: usize = 10; const VALUE_OVERLAY_RECLAIM_FACTOR: usize = 10; // Min number of value items to initiate reclaim. Each item is around 40 bytes. const VALUE_OVERLAY_MIN_RECLAIM_ITEMS: usize = 10240; -// Once ref count overly uses less than 1/10 of its capacity, it will be reclaimed. +// Once ref count overlay uses less than 1/10 of its capacity, it will be reclaimed. const REF_COUNT_OVERLAY_RECLAIM_FACTOR: usize = 10; #[derive(Debug)] From 115b5c817ecd4575ae5ddddc15b1e01dff74f137 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 11 Jan 2024 11:58:14 +0000 Subject: [PATCH 46/53] Fix --- src/column.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/column.rs b/src/column.rs index 9ac9266d..a378c668 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1072,9 +1072,7 @@ impl HashColumn { *address }, }; - let mut data_buf = [0u8; 8]; - data_buf.copy_from_slice(&address.to_le_bytes()); - data.append(&mut data_buf.to_vec()); + data.extend_from_slice(&address.to_le_bytes()); } Ok(data) } From 0424bdf801d057cc37d6ba3f6308cbae1d514ff8 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Tue, 23 Jan 2024 13:46:24 +0000 Subject: [PATCH 47/53] Remove ordered for now --- src/table.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/table.rs b/src/table.rs index 14b95366..e053a453 100644 --- a/src/table.rs +++ b/src/table.rs @@ -54,7 +54,6 @@ use crate::{ table::key::{TableKey, TableKeyQuery, PARTIAL_SIZE}, }; use std::{ - collections::BTreeSet, convert::TryInto, mem::MaybeUninit, sync::{ @@ -142,7 +141,6 @@ impl std::fmt::Display for TableId { #[derive(Debug)] struct FreeEntries { stack: Vec, - ordered: BTreeSet, } #[derive(Debug)] @@ -447,7 +445,6 @@ impl ValueTable { pub fn init_table_data(&mut self) -> Result<()> { let free_entries = if self.needs_free_entries { let mut stack: Vec = Default::default(); - let mut ordered: BTreeSet = Default::default(); let filled = self.filled.load(Ordering::Relaxed); let last_removed = self.last_removed.load(Ordering::Relaxed); @@ -462,7 +459,6 @@ impl ValueTable { } stack.insert(0, next); - ordered.insert(next); let mut buf = PartialEntry::new_uninit(); self.file.read_at(buf.as_mut(), next * self.entry_size as u64)?; @@ -470,7 +466,7 @@ impl ValueTable { next = buf.read_next(); } - Some(RwLock::new(FreeEntries { stack, ordered })) + Some(RwLock::new(FreeEntries { stack })) } else { None }; @@ -752,7 +748,6 @@ impl ValueTable { if let Some(mut free_entries) = free_entries_guard { let last = free_entries.stack.pop().unwrap(); debug_assert_eq!(last, last_removed); - free_entries.ordered.remove(&last_removed); } last_removed } else { @@ -779,7 +774,6 @@ impl ValueTable { let index = if last_removed != 0 { let last = free_entries.stack.pop().unwrap(); debug_assert_eq!(last, last_removed); - free_entries.ordered.remove(&last_removed); let next_removed = *free_entries.stack.last().unwrap_or(&0u64); @@ -934,7 +928,6 @@ impl ValueTable { if let Some(mut free_entries) = free_entries_guard { free_entries.stack.push(index); - free_entries.ordered.insert(index); } Ok(()) From dff334dbf60152df08dc1d4c6d312a1045a6ca6d Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 1 Feb 2024 15:33:31 +0000 Subject: [PATCH 48/53] Remove claim_next_free --- src/table.rs | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/table.rs b/src/table.rs index e053a453..d965d9ec 100644 --- a/src/table.rs +++ b/src/table.rs @@ -764,43 +764,41 @@ impl ValueTable { Ok(index) } - pub fn claim_next_free(&self) -> Result { + pub fn claim_entries(&self, num: usize) -> Result> { match &self.free_entries { Some(free_entries) => { let mut free_entries = free_entries.write(); - let filled = self.filled.load(Ordering::Relaxed); - let last_removed = self.last_removed.load(Ordering::Relaxed); - let index = if last_removed != 0 { - let last = free_entries.stack.pop().unwrap(); - debug_assert_eq!(last, last_removed); + let mut entries: Vec = Default::default(); - let next_removed = *free_entries.stack.last().unwrap_or(&0u64); + for _i in 0..num { + let filled = self.filled.load(Ordering::Relaxed); + let last_removed = self.last_removed.load(Ordering::Relaxed); + let index = if last_removed != 0 { + let last = free_entries.stack.pop().unwrap(); + debug_assert_eq!(last, last_removed); - self.last_removed.store(next_removed, Ordering::Relaxed); - last_removed - } else { - self.filled.store(filled + 1, Ordering::Relaxed); - filled - }; + let next_removed = *free_entries.stack.last().unwrap_or(&0u64); + + self.last_removed.store(next_removed, Ordering::Relaxed); + last_removed + } else { + self.filled.store(filled + 1, Ordering::Relaxed); + filled + }; + entries.push(index); + } self.dirty_header.store(true, Ordering::Relaxed); - Ok(index) + + Ok(entries) }, None => return Err(crate::error::Error::InvalidConfiguration(format!( - "claim_next_free called without free_entries" + "claim_entries called without free_entries" ))), } } - pub fn claim_entries(&self, num: usize) -> Result> { - let mut entries: Vec = Default::default(); - for _i in 0..num { - entries.push(self.claim_next_free()?); - } - Ok(entries) - } - fn overwrite_chain( &self, key: &TableKey, From e3e90325d8756dd8fb8558e02d1436db2cd928ce Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 1 Feb 2024 15:53:04 +0000 Subject: [PATCH 49/53] Read lock --- src/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/table.rs b/src/table.rs index d965d9ec..74b71e5b 100644 --- a/src/table.rs +++ b/src/table.rs @@ -1116,7 +1116,7 @@ impl ValueTable { pub fn complete_plan(&self, log: &mut LogWriter) -> Result<()> { let _free_entries_guard = if let Some(free_entries) = &self.free_entries { - Some(free_entries.write()) + Some(free_entries.read()) } else { None }; From b5665773782e3280cd1aaf65879d5a39cdb532a0 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 2 Feb 2024 15:12:06 +0000 Subject: [PATCH 50/53] Improved node data packing and unpacking --- src/column.rs | 68 ++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/column.rs b/src/column.rs index a378c668..78c72436 100644 --- a/src/column.rs +++ b/src/column.rs @@ -403,32 +403,27 @@ impl Column { } pub fn packed_node_size(data: &Vec, num_children: u8) -> usize { - 1 + data.len() + num_children as usize * 8 -} - -pub fn pack_node_data(data: Vec, child_data: Vec, num_children: u8) -> Vec { - [vec![num_children], data, child_data].concat() + data.len() + num_children as usize * 8 + 1 } pub fn unpack_node_data(data: Vec) -> Result<(Vec, Children)> { if data.len() == 0 { return Err(Error::InvalidValueData) } - let num_children = data[0] as usize; - let (_, data) = data.split_at(1); + let num_children = data[data.len() - 1] as usize; let child_buf_len = num_children * 8; - if data.len() < child_buf_len { + if data.len() < (child_buf_len + 1) { return Err(Error::InvalidValueData) } - let (data, child_buf) = data.split_at(data.len() - child_buf_len); - + let data_len = data.len() - (child_buf_len + 1); let mut children = Children::new(); for i in 0..num_children { - let node_address = u64::from_le_bytes(child_buf[i * 8..(i + 1) * 8].try_into().unwrap()); + let node_address = + u64::from_le_bytes(data[data_len + i * 8..data_len + (i + 1) * 8].try_into().unwrap()); children.push(node_address); } - - Ok((data.to_vec(), children)) + let data = data.split_at(data_len).0.to_vec(); + Ok((data, children)) } impl HashColumn { @@ -1052,15 +1047,15 @@ impl HashColumn { Ok(()) } - fn claim_children( + fn claim_children_to_data( &self, children: &Vec, tables: TablesRef, tier_addresses: &HashMap>, tier_index: &mut HashMap, node_values: &mut Vec, - ) -> Result> { - let mut data = Vec::new(); + data: &mut Vec, + ) -> Result<()> { for child in children { let address = match child { NodeRef::New(node) => @@ -1074,7 +1069,7 @@ impl HashColumn { }; data.extend_from_slice(&address.to_le_bytes()); } - Ok(data) + Ok(()) } fn claim_node( @@ -1102,11 +1097,17 @@ impl HashColumn { let offset = tier_addresses.get(&target_tier).unwrap()[index]; - let data = pack_node_data( - node.data.clone(), - self.claim_children(&node.children, tables, tier_addresses, tier_index, node_values)?, - num_children as u8, - ); + let mut data: Vec = Vec::with_capacity(data_size); + data.extend_from_slice(&node.data); + self.claim_children_to_data( + &node.children, + tables, + tier_addresses, + tier_index, + node_values, + &mut data, + )?; + data.push(num_children as u8); // Can't support compression as we need to know the size earlier to get the tier. let val: RcValue = data.into(); @@ -1145,17 +1146,18 @@ impl HashColumn { let mut node_values: Vec = Default::default(); let num_children = node.children.len(); - let data = pack_node_data( - node.data.clone(), - self.claim_children( - &node.children, - values, - &tier_addresses, - &mut tier_index, - &mut node_values, - )?, - num_children as u8, - ); + let data_size = packed_node_size(&node.data, num_children as u8); + let mut data: Vec = Vec::with_capacity(data_size); + data.extend_from_slice(&node.data); + self.claim_children_to_data( + &node.children, + values, + &tier_addresses, + &mut tier_index, + &mut node_values, + &mut data, + )?; + data.push(num_children as u8); return Ok((data, node_values)) }, From fad625563f849d091022497a564ef1be98b73ec9 Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 8 Feb 2024 15:17:11 +0000 Subject: [PATCH 51/53] Simple ref_count tests --- src/ref_count.rs | 200 +++++++++++++++-------------------------------- 1 file changed, 61 insertions(+), 139 deletions(-) diff --git a/src/ref_count.rs b/src/ref_count.rs index 9876e9e2..b546d95e 100644 --- a/src/ref_count.rs +++ b/src/ref_count.rs @@ -440,9 +440,9 @@ impl RefCountTable { #[cfg(test)] mod test { - /* use super::*; + use super::*; use rand::{Rng, SeedableRng}; - use std::path::PathBuf; + use siphasher::sip128::Hasher128; #[cfg(feature = "bench")] use test::Bencher; @@ -451,175 +451,97 @@ mod test { #[test] fn test_entries() { - let mut chunk = IndexTable::transmute_chunk(EMPTY_CHUNK); + let mut chunk = RefCountTable::transmute_chunk(&EMPTY_CHUNK).clone(); let mut chunk2 = EMPTY_CHUNK; - for (i, chunk) in chunk.iter_mut().enumerate().take(CHUNK_ENTRIES) { - use std::{ - collections::hash_map::DefaultHasher, - hash::{Hash, Hasher}, - }; - let mut hasher = DefaultHasher::new(); + for (i, chunk_entry) in chunk.iter_mut().enumerate().take(CHUNK_ENTRIES) { + use std::hash::Hash; + let mut hasher = siphasher::sip128::SipHasher::new(); i.hash(&mut hasher); - let hash = hasher.finish(); - let entry = Entry::from_u64(hash); - IndexTable::write_entry(&entry, i, &mut chunk2); - *chunk = entry; + let hash = hasher.finish128().as_u128(); + let entry = Entry::from_u128(hash); + RefCountTable::write_entry(&entry, i, &mut chunk2); + assert_eq!(entry.as_u128(), RefCountTable::read_entry(&chunk2, i).as_u128()); + *chunk_entry = entry; } - assert!(IndexTable::transmute_chunk(chunk2) == chunk); - } - - #[test] - fn test_find_entries() { - let partial_keys = [1, 1 << 10, 1 << 20]; - for index_bits in [16, 18, 20, 22] { - let index_table = IndexTable { - id: TableId(index_bits.into()), - map: RwLock::new(None), - path: PathBuf::new(), - }; - - let data_address = Address::from_u64((1 << index_bits) - 1); - - let mut chunk = [0; CHUNK_ENTRIES * 8]; - for (i, partial_key) in partial_keys.iter().enumerate() { - chunk[i * 8..(i + 1) * 8].copy_from_slice( - &Entry::new(data_address, *partial_key, index_bits).as_u64().to_le_bytes(), - ); - } - - for partial_key in &partial_keys { - let key_prefix = *partial_key << (CHUNK_ENTRIES_BITS + SIZE_TIERS_BITS); - #[cfg(target_arch = "x86_64")] - assert_eq!( - index_table.find_entry_sse2(key_prefix, 0, &chunk).0.partial_key(index_bits), - *partial_key - ); - assert_eq!( - index_table.find_entry_base(key_prefix, 0, &chunk).0.partial_key(index_bits), - *partial_key - ); - } - } + assert!(RefCountTable::transmute_chunk(&chunk2) == &chunk); } #[test] fn test_find_any_entry() { - let table = - IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; - let mut chunk = [0u8; CHUNK_LEN]; + let table = RefCountTable { + id: RefCountTableId(18), + map: RwLock::new(None), + path: Default::default(), + }; + let mut chunk = Chunk([0u8; CHUNK_LEN]); let mut entries = [Entry::empty(); CHUNK_ENTRIES]; - let mut keys = [0u64; CHUNK_ENTRIES]; + let mut addresses = [0u64; CHUNK_ENTRIES]; let mut rng = rand::prelude::SmallRng::from_seed(Default::default()); for i in 0..CHUNK_ENTRIES { - keys[i] = rng.gen(); - let partial_key = Entry::extract_key(keys[i], 18); - let e = Entry::new(Address::new(0, 0), partial_key, 18); + addresses[i] = rng.gen(); + let ref_count = rng.gen(); + let e = Entry::new(Address::from_u64(addresses[i]), ref_count); entries[i] = e; - IndexTable::write_entry(&e, i, &mut chunk); + RefCountTable::write_entry(&e, i, &mut chunk); } for target in 0..CHUNK_ENTRIES { - for start_pos in 0..CHUNK_ENTRIES { - let (e, i) = table.find_entry_base(keys[target], start_pos, &chunk); - if start_pos <= target { - assert_eq!((e.as_u64(), i), (entries[target].as_u64(), target)); - } else { - assert_eq!((e.as_u64(), i), (Entry::empty().as_u64(), 0)); - } - #[cfg(target_arch = "x86_64")] - { - let (e, i) = table.find_entry_sse2(keys[target], start_pos, &chunk); - if start_pos <= target { - assert_eq!((e.as_u64(), i), (entries[target].as_u64(), target)); - } else { - assert_eq!((e.as_u64(), i), (Entry::empty().as_u64(), 0)); - } - } + let result = table.find_entry_base(addresses[target], &chunk); + assert!(result.is_some()); + if let Some((e, i)) = result { + assert_eq!((e.as_u128(), i), (entries[target].as_u128(), target)); } } } #[test] - fn test_find_entry_same_value() { - let table = - IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; - let mut chunk = [0u8; CHUNK_LEN]; - let key = 0x4242424242424242; - let partial_key = Entry::extract_key(key, 18); - let entry = Entry::new(Address::new(0, 0), partial_key, 18); - for i in 0..CHUNK_ENTRIES { - IndexTable::write_entry(&entry, i, &mut chunk); - } - - for start_pos in 0..CHUNK_ENTRIES { - let (_, i) = table.find_entry_base(key, start_pos, &chunk); - assert_eq!(i, start_pos); - #[cfg(target_arch = "x86_64")] - { - let (_, i) = table.find_entry_sse2(key, start_pos, &chunk); - assert_eq!(i, start_pos); - } - } - } - - #[test] - fn test_find_entry_zero_pk() { - let table = - IndexTable { id: TableId(16), map: RwLock::new(None), path: Default::default() }; - let mut chunk = [0u8; CHUNK_LEN]; - let zero_key = 0x0000000000000000; - let entry = Entry::new(Address::new(1, 1), zero_key, 16); + fn test_find_entry_zero() { + let table = RefCountTable { + id: RefCountTableId(16), + map: RwLock::new(None), + path: Default::default(), + }; + let mut chunk = Chunk([0u8; CHUNK_LEN]); + let address = Address::new(1, 1); + let entry = Entry::new(address, 0); // Write at index 1. Index 0 contains an empty entry. - IndexTable::write_entry(&entry, 1, &mut chunk); + RefCountTable::write_entry(&entry, 1, &mut chunk); - let (_, i) = table.find_entry_base(zero_key, 0, &chunk); - assert_eq!(i, 1); - #[cfg(target_arch = "x86_64")] - { - let (_, i) = table.find_entry_sse2(zero_key, 0, &chunk); + let result = table.find_entry_base(address.as_u64(), &chunk); + assert!(result.is_some()); + if let Some((_e, i)) = result { assert_eq!(i, 1); } - } */ - - /* #[cfg(feature = "bench")] - fn bench_find_entry_internal< - F: Fn(&IndexTable, u64, usize, &[u8; CHUNK_LEN]) -> (Entry, usize), - >( - b: &mut Bencher, - f: F, - ) { - let table = - IndexTable { id: TableId(18), map: RwLock::new(None), path: Default::default() }; - let mut chunk = [0u8; CHUNK_LEN]; - let mut keys = [0u64; CHUNK_ENTRIES]; + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_find_entry(b: &mut Bencher) { + let table = RefCountTable { + id: RefCountTableId(18), + map: RwLock::new(None), + path: Default::default(), + }; + let mut chunk = Chunk([0u8; CHUNK_LEN]); + let mut addresses = [0u64; CHUNK_ENTRIES]; let mut rng = rand::prelude::SmallRng::from_seed(Default::default()); for i in 0..CHUNK_ENTRIES { - keys[i] = rng.gen(); - let partial_key = Entry::extract_key(keys[i], 18); - let e = Entry::new(Address::new(0, 0), partial_key, 18); - IndexTable::write_entry(&e, i, &mut chunk); + addresses[i] = rng.gen(); + let ref_count = rng.gen(); + let e = Entry::new(Address::from_u64(addresses[i]), ref_count); + RefCountTable::write_entry(&e, i, &mut chunk); } let mut index = 0; b.iter(|| { - let x = f(&table, keys[index], 0, &chunk).1; - assert_eq!(x, index); + let result = RefCountTable::find_entry_base(&table, addresses[index], &chunk); + assert!(result.is_some()); + if let Some((_e, i)) = result { + assert_eq!(i, index); + } index = (index + 1) % CHUNK_ENTRIES; }); } - - #[cfg(feature = "bench")] - #[bench] - fn bench_find_entry(b: &mut Bencher) { - bench_find_entry_internal(b, IndexTable::find_entry_base) - } - - #[cfg(feature = "bench")] - #[cfg(target_arch = "x86_64")] - #[bench] - fn bench_find_entry_sse(b: &mut Bencher) { - bench_find_entry_internal(b, IndexTable::find_entry_sse2) - } */ } From 963d7efce38663929b0dd6d433a381863118b63f Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Thu, 8 Feb 2024 15:35:12 +0000 Subject: [PATCH 52/53] Remove unused multi tree node compression --- src/column.rs | 14 +------------- src/db.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/column.rs b/src/column.rs index 78c72436..f50f9e09 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1014,16 +1014,6 @@ impl HashColumn { let table_key = TableKey::NoHash; - /* let (cval, target_tier) = - Column::compress(tables.compression, &table_key, data.as_ref(), tables.tables); - let (cval, compressed) = cval - .as_ref() - .map(|cval| (cval.as_slice(), true)) - .unwrap_or((data.as_ref(), false)); - - let cval: RcValue = cval.to_vec().into(); - let val = if compressed { data.into() } else { cval.clone() }; */ - let target_tier = tables .tables .iter() @@ -1111,12 +1101,10 @@ impl HashColumn { // Can't support compression as we need to know the size earlier to get the tier. let val: RcValue = data.into(); - let cval = val.clone(); - let compressed = false; let address = Address::new(offset, target_tier as u8); - node_values.push(NodeChange::NewValue(address.as_u64(), val, cval, compressed)); + node_values.push(NodeChange::NewValue(address.as_u64(), val)); Ok(address.as_u64()) } diff --git a/src/db.rs b/src/db.rs index 76bc1359..ed5c178f 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1999,8 +1999,8 @@ impl, Value> Operation { #[derive(Debug, PartialEq, Eq)] pub enum NodeChange { - /// (address, value, compressed value, compressed) - NewValue(u64, RcValue, RcValue, bool), + /// (address, value) + NewValue(u64, RcValue), /// (address) IncrementReference(u64), /// Dereference and remove any of the children in the tree @@ -2105,7 +2105,7 @@ impl IndexedChangeSet { } } for change in self.node_changes.iter() { - if let NodeChange::NewValue(address, val, _cval, _compressed) = change { + if let NodeChange::NewValue(address, val) = change { overlay.address.insert(*address, (record_id, val.clone())); } } @@ -2137,11 +2137,11 @@ impl IndexedChangeSet { } for change in self.node_changes.iter() { match change { - NodeChange::NewValue(address, val, cval, compressed) => { + NodeChange::NewValue(address, val) => { column.write_address_value_plan( *address, - cval.clone(), - *compressed, + val.clone(), + false, val.value().len() as u32, writer, )?; @@ -2228,7 +2228,7 @@ impl IndexedChangeSet { } } for change in self.node_changes.iter() { - if let NodeChange::NewValue(address, _val, _cval, _compressed) = change { + if let NodeChange::NewValue(address, _val) = change { overlay.address.remove(address); } } From d4caa3f46ca3ec1e6868f4a8c63a76d0cefc521c Mon Sep 17 00:00:00 2001 From: MattHalpinParity Date: Fri, 9 Feb 2024 12:18:25 +0000 Subject: [PATCH 53/53] Added allow_direct_node_access column option --- src/db.rs | 13 +++++++++---- src/options.rs | 12 +++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/db.rs b/src/db.rs index ed5c178f..55f7b272 100644 --- a/src/db.rs +++ b/src/db.rs @@ -325,9 +325,11 @@ impl DbInner { if !self.options.columns[col as usize].multitree { return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) } - if !self.options.columns[col as usize].append_only { + if !self.options.columns[col as usize].append_only && + !self.options.columns[col as usize].allow_direct_node_access + { return Err(Error::InvalidConfiguration( - "get_root can only be called on a column with append_only option.".to_string(), + "get_root can only be called on a column with append_only or allow_direct_node_access options.".to_string(), )) } let value = self.get(col, key, false)?; @@ -346,9 +348,12 @@ impl DbInner { if !self.options.columns[col as usize].multitree { return Err(Error::InvalidConfiguration("Not a multitree column.".to_string())) } - if !self.options.columns[col as usize].append_only && external_call { + if !self.options.columns[col as usize].append_only && + !self.options.columns[col as usize].allow_direct_node_access && + external_call + { return Err(Error::InvalidConfiguration( - "get_node can only be called on a column with append_only option.".to_string(), + "get_node can only be called on a column with append_only or allow_direct_node_access options.".to_string(), )) } match &self.columns[col as usize] { diff --git a/src/options.rs b/src/options.rs index de534e4d..7fefbf86 100644 --- a/src/options.rs +++ b/src/options.rs @@ -70,6 +70,9 @@ pub struct ColumnOptions { pub multitree: bool, /// Column is append-only. Delete operations are ignored. pub append_only: bool, + /// Allow Multitree root and child nodes to be accessed directly without using TreeReader. + /// Client code must ensure this is safe. + pub allow_direct_node_access: bool, } /// Database metadata. @@ -86,7 +89,7 @@ pub struct Metadata { impl ColumnOptions { fn as_string(&self) -> String { format!( - "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}, multitree: {}, append_only: {}", + "preimage: {}, uniform: {}, refc: {}, compression: {}, ordered: {}, multitree: {}, append_only: {}, allow_direct_node_access: {}", self.preimage, self.uniform, self.ref_counted, @@ -94,6 +97,7 @@ impl ColumnOptions { self.btree_index, self.multitree, self.append_only, + self.allow_direct_node_access, ) } @@ -132,6 +136,10 @@ impl ColumnOptions { let btree_index = vals.get("ordered").and_then(|c| c.parse().ok()).unwrap_or(false); let multitree = vals.get("multitree").and_then(|c| c.parse().ok()).unwrap_or(false); let append_only = vals.get("append_only").and_then(|c| c.parse().ok()).unwrap_or(false); + let allow_direct_node_access = vals + .get("allow_direct_node_access") + .and_then(|c| c.parse().ok()) + .unwrap_or(false); Some(ColumnOptions { preimage, @@ -141,6 +149,7 @@ impl ColumnOptions { btree_index, multitree, append_only, + allow_direct_node_access, }) } } @@ -155,6 +164,7 @@ impl Default for ColumnOptions { btree_index: false, multitree: false, append_only: false, + allow_direct_node_access: false, } } }