Skip to content

Commit 176f96f

Browse files
Deepak Singhfacebook-github-bot
authored andcommitted
Parallelize dumping schemas to disk
Reviewed By: arseniy-panfilov Differential Revision: D61515272 fbshipit-source-id: e67feb735db2911acafe7a68133ca1a0c5f56d55
1 parent 81d40f6 commit 176f96f

18 files changed

+1299
-18
lines changed

compiler/crates/schema-print/Cargo.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# @generated by autocargo from //relay/oss/crates/schema-print:[schema-print,schema-print_test]
1+
# @generated by autocargo from //relay/oss/crates/schema-print:[schema-print,schema-print-consistency_test,schema-print-par_test,schema-print_test]
22

33
[package]
44
name = "schema-print"
@@ -8,6 +8,14 @@ edition = "2021"
88
repository = "https://github.com/facebook/relay"
99
license = "MIT"
1010

11+
[[test]]
12+
name = "schema_print_consistency_test"
13+
path = "tests/print_schema_consistency_test.rs"
14+
15+
[[test]]
16+
name = "schema_print_par_test"
17+
path = "tests/print_schema_in_parallel_test.rs"
18+
1119
[[test]]
1220
name = "schema_print_test"
1321
path = "tests/print_schema_test.rs"
@@ -16,8 +24,10 @@ path = "tests/print_schema_test.rs"
1624
fnv = "1.0"
1725
intern = { path = "../intern" }
1826
itertools = "0.11.0"
27+
rayon = "1.9.0"
1928
schema = { path = "../schema" }
2029

2130
[dev-dependencies]
31+
diff = "0.1"
2232
fixture-tests = { path = "../fixture-tests" }
2333
tokio = { version = "1.37.0", features = ["full", "test-util", "tracing"] }

compiler/crates/schema-print/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111

1212
mod print_schema;
1313
mod printer;
14+
mod shard_printer;
15+
16+
use std::hash::DefaultHasher;
17+
use std::hash::Hash;
18+
use std::hash::Hasher;
1419

1520
pub use print_schema::*;
1621
pub use printer::*;
22+
pub use shard_printer::*;
23+
24+
pub fn calculate_hash<T: Hash>(t: &T) -> u64 {
25+
let mut s = DefaultHasher::new();
26+
t.hash(&mut s);
27+
s.finish()
28+
}

compiler/crates/schema-print/src/print_schema.rs

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@ use fnv::FnvHashMap;
1212
use intern::string_key::StringKey;
1313
use intern::Lookup;
1414
use itertools::Itertools;
15+
use rayon::iter::IntoParallelIterator;
16+
use rayon::iter::ParallelIterator;
1517
use schema::*;
1618

19+
use crate::generate_shard_map;
20+
use crate::generate_typed_shard_map;
1721
use crate::has_schema_definition_types;
1822
use crate::is_schema_of_common_name;
1923
use crate::Printer;
24+
use crate::ShardPrinter;
25+
use crate::TypedShardPrinter;
2026
use crate::DEAULT_SHARD_COUNT;
2127

2228
pub fn print(schema: &SDLSchema) -> String {
@@ -61,6 +67,8 @@ pub fn print_types(schema: &SDLSchema) -> String {
6167

6268
/// Returns a sharded GraphQL SDLSchema
6369
///
70+
/// Prints shards in sequence. No parallelism is used.
71+
///
6472
/// # Arguments
6573
///
6674
/// * `schema` - GraphQL SDLSchema
@@ -108,6 +116,73 @@ pub fn print_types_directives_as_shards(
108116
shards
109117
}
110118

119+
/**
120+
* Prints a sharded GraphQL SDLSchema in parallel
121+
*/
122+
pub fn print_types_directives_as_shards_in_parallel(
123+
schema: &SDLSchema,
124+
shard_count: usize,
125+
type_shard_count_map: FnvHashMap<StringKey, usize>,
126+
) -> FnvHashMap<usize, String> {
127+
let typeshard_count: usize = type_shard_count_map.values().sum();
128+
let base_shard_count = shard_count - typeshard_count;
129+
let shard_map = generate_shard_map(
130+
schema,
131+
base_shard_count,
132+
type_shard_count_map.keys().copied().collect(),
133+
);
134+
let typed_shard_map = generate_typed_shard_map(schema, type_shard_count_map);
135+
136+
// Base shards
137+
let mut shards = shard_map
138+
.into_par_iter()
139+
.map(|(shard_key, shard)| {
140+
let printer = ShardPrinter::new(schema, shard);
141+
// Print directives
142+
let content = if shard_key == 0 {
143+
printer.print_shard_with_directives()
144+
} else {
145+
printer.print_shard()
146+
};
147+
(shard_key, content)
148+
})
149+
.collect::<FnvHashMap<usize, String>>();
150+
151+
// Typed shards (e.g. Query, Mutation, etc)
152+
let mut typed_shards = typed_shard_map
153+
.into_par_iter()
154+
.map(|(type_name, shard_map)| {
155+
let type_shard_count = shard_map.len();
156+
let typed_shard = shard_map
157+
.into_par_iter()
158+
.map(|(shard_key, fields)| {
159+
let printer = TypedShardPrinter::new(
160+
schema,
161+
type_name,
162+
fields,
163+
shard_key == 0,
164+
shard_key == type_shard_count - 1,
165+
);
166+
(shard_key, printer.print_shard())
167+
})
168+
.collect();
169+
(type_name, typed_shard)
170+
})
171+
.collect::<FnvHashMap<StringKey, FnvHashMap<usize, String>>>();
172+
173+
// Drain typed_shards into shards
174+
typed_shards
175+
.iter_mut()
176+
.sorted_by_key(|(k, _)| k.lookup())
177+
.for_each(|(_type_name, type_shards)| {
178+
let curr_shard_count = shards.len();
179+
type_shards.drain().for_each(|(shard_key, type_shard)| {
180+
shards.insert(curr_shard_count + shard_key, type_shard);
181+
});
182+
});
183+
shards
184+
}
185+
111186
pub fn print_type(schema: &SDLSchema, type_: Type) -> String {
112187
let mut result = vec![String::new(); DEAULT_SHARD_COUNT];
113188
write_type(schema, &mut result, type_).unwrap();
@@ -135,7 +210,7 @@ fn write_directive(
135210

136211
fn write_types(schema: &SDLSchema, result: &mut Vec<String>) -> FmtResult {
137212
let mut printer = Printer::new(schema, result);
138-
printer.print_types()
213+
printer.print_all_types()
139214
}
140215

141216
fn write_types_as_shards<'a>(
@@ -145,7 +220,7 @@ fn write_types_as_shards<'a>(
145220
type_shards: &'a mut FnvHashMap<StringKey, Vec<String>>,
146221
) -> FmtResult {
147222
let mut printer = Printer::new_with_shards(schema, shards, shard_count, Some(type_shards));
148-
printer.print_types()
223+
printer.print_all_types()
149224
}
150225

151226
fn write_type(schema: &SDLSchema, result: &mut Vec<String>, type_: Type) -> FmtResult {

compiler/crates/schema-print/src/printer.rs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
use std::collections::hash_map::DefaultHasher;
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
28
use std::collections::BTreeMap;
39
use std::fmt::Result as FmtResult;
410
use std::fmt::Write;
5-
use std::hash::Hash;
6-
use std::hash::Hasher;
711

812
use fnv::FnvHashMap;
913
use intern::string_key::Intern;
@@ -12,9 +16,11 @@ use intern::Lookup;
1216
use itertools::Itertools;
1317
use schema::*;
1418

19+
use crate::calculate_hash;
20+
1521
pub const DEAULT_SHARD_COUNT: usize = 1;
1622

17-
pub(crate) struct Printer<'schema, 'writer> {
23+
pub struct Printer<'schema, 'writer> {
1824
schema: &'schema SDLSchema,
1925
// Each writer here represents a shard
2026
writers: &'writer mut Vec<String>,
@@ -111,14 +117,21 @@ impl<'schema, 'writer> Printer<'schema, 'writer> {
111117
self.print_definition_end()
112118
}
113119

114-
pub fn print_types(&mut self) -> FmtResult {
120+
pub fn print_all_types(&mut self) -> FmtResult {
115121
let ordered_type_map = self.schema.get_type_map().collect::<BTreeMap<_, _>>();
116122
for (_key, value) in ordered_type_map.iter() {
117123
self.print_type(**value)?;
118124
}
119125
Ok(())
120126
}
121127

128+
pub fn print_types(&mut self, types_to_print: &[(StringKey, Type)]) -> FmtResult {
129+
for (_key, value) in types_to_print.iter() {
130+
self.print_type(*value)?;
131+
}
132+
Ok(())
133+
}
134+
122135
pub fn print_type(&mut self, type_: Type) -> FmtResult {
123136
self.update_writer_index_for_type_start(&type_);
124137
match type_ {
@@ -195,7 +208,7 @@ impl<'schema, 'writer> Printer<'schema, 'writer> {
195208
self.print_definition_end()
196209
}
197210

198-
fn print_fields(&mut self, fields: &[FieldID], type_name: impl Lookup) -> FmtResult {
211+
pub fn print_fields(&mut self, fields: &[FieldID], type_name: impl Lookup) -> FmtResult {
199212
if fields.is_empty() {
200213
return Ok(());
201214
}
@@ -218,6 +231,26 @@ impl<'schema, 'writer> Printer<'schema, 'writer> {
218231
write!(self.writer(), "}}")
219232
}
220233

234+
// Prints a set of fields indented by 2 spaces
235+
// Does not handle writing the type definition and open/closing brackets
236+
pub fn print_fields_without_brackets(&mut self, fields: &[FieldID]) -> FmtResult {
237+
if fields.is_empty() {
238+
return Ok(());
239+
}
240+
for field_id in fields {
241+
let field = &self.schema.field(*field_id);
242+
self.print_space()?;
243+
self.print_space()?;
244+
write!(self.writer(), "{}", field.name.item)?;
245+
self.print_args(&field.arguments)?;
246+
let type_string = self.schema.get_type_string(&field.type_);
247+
write!(self.writer(), ": {}", type_string)?;
248+
self.print_directive_values(&field.directives)?;
249+
self.print_new_line()?;
250+
}
251+
Ok(())
252+
}
253+
221254
fn print_args(&mut self, args: &ArgumentDefinitions) -> FmtResult {
222255
if args.is_empty() {
223256
return Ok(());
@@ -311,7 +344,15 @@ impl<'schema, 'writer> Printer<'schema, 'writer> {
311344
Ok(())
312345
}
313346

314-
fn print_definition_end(&mut self) -> FmtResult {
347+
pub fn print_type_declaration(&mut self, type_name: StringKey) -> FmtResult {
348+
writeln!(self.writer(), "type {} {{", type_name)
349+
}
350+
351+
pub fn print_definition_closure(&mut self) -> FmtResult {
352+
write!(self.writer(), "}}")
353+
}
354+
355+
pub fn print_definition_end(&mut self) -> FmtResult {
315356
self.print_new_line()?;
316357
self.print_new_line()
317358
}
@@ -381,9 +422,3 @@ pub fn has_schema_definition_types(schema: &SDLSchema) -> bool {
381422
|| schema.mutation_type().is_some()
382423
|| schema.subscription_type().is_some()
383424
}
384-
385-
pub fn calculate_hash<T: Hash>(t: &T) -> u64 {
386-
let mut s = DefaultHasher::new();
387-
t.hash(&mut s);
388-
s.finish()
389-
}

0 commit comments

Comments
 (0)