Skip to content

Commit 5825e91

Browse files
committed
Auto merge of #140319 - Zoxc:dep-graph-index-chunks, r=<try>
Group dep nodes by chunks with sequential indices and only store the first index at the start of the chunk
2 parents f60a0f1 + 46a7d19 commit 5825e91

1 file changed

Lines changed: 94 additions & 60 deletions

File tree

compiler/rustc_query_system/src/dep_graph/serialized.rs

Lines changed: 94 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,20 @@ impl SerializedDepGraph {
198198

199199
// `node_max` is the number of indices including empty nodes while `node_count`
200200
// is the number of actually encoded nodes.
201-
let (node_max, node_count, edge_count) =
202-
d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
201+
let (node_max, node_count, edge_count, chunk_count) =
202+
d.with_position(d.len() - 4 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
203203
debug!("position: {:?}", d.position());
204204
let node_max = IntEncodedWithFixedSize::decode(d).0 as usize;
205205
let node_count = IntEncodedWithFixedSize::decode(d).0 as usize;
206206
let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize;
207-
(node_max, node_count, edge_count)
207+
let chunk_count = IntEncodedWithFixedSize::decode(d).0 as usize;
208+
(node_max, node_count, edge_count, chunk_count)
208209
});
209210
debug!("position: {:?}", d.position());
210211

211212
debug!(?node_count, ?edge_count);
212213

213-
let graph_bytes = d.len() - (3 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position();
214+
let graph_bytes = d.len() - (4 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position();
214215

215216
let mut nodes = IndexVec::from_elem_n(
216217
DepNode { kind: D::DEP_KIND_NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) },
@@ -232,36 +233,45 @@ impl SerializedDepGraph {
232233
let mut edge_list_data =
233234
Vec::with_capacity(graph_bytes - node_count * size_of::<SerializedNodeHeader<D>>());
234235

235-
for _ in 0..node_count {
236-
// Decode the header for this edge; the header packs together as many of the fixed-size
237-
// fields as possible to limit the number of times we update decoder state.
238-
let node_header =
239-
SerializedNodeHeader::<D> { bytes: d.read_array(), _marker: PhantomData };
236+
for _ in 0..chunk_count {
237+
let mut current_index = d.read_u32();
240238

241-
let index = node_header.index();
239+
loop {
240+
// Decode the header for this edge; the header packs together as many of the fixed-size
241+
// fields as possible to limit the number of times we update decoder state.
242+
let node_header =
243+
SerializedNodeHeader::<D> { bytes: d.read_array(), _marker: PhantomData };
242244

243-
let node = &mut nodes[index];
244-
// Make sure there's no duplicate indices in the dep graph.
245-
assert!(node_header.node().kind != D::DEP_KIND_NULL && node.kind == D::DEP_KIND_NULL);
246-
*node = node_header.node();
245+
if node_header.node().kind == D::DEP_KIND_NULL {
246+
break;
247+
}
248+
249+
let index = SerializedDepNodeIndex::from_u32(current_index);
250+
current_index += 1;
247251

248-
fingerprints[index] = node_header.fingerprint();
252+
let node = &mut nodes[index];
253+
// Make sure there's no duplicate indices in the dep graph.
254+
assert!(node.kind == D::DEP_KIND_NULL);
255+
*node = node_header.node();
249256

250-
// If the length of this node's edge list is small, the length is stored in the header.
251-
// If it is not, we fall back to another decoder call.
252-
let num_edges = node_header.len().unwrap_or_else(|| d.read_u32());
257+
fingerprints[index] = node_header.fingerprint();
253258

254-
// The edges index list uses the same varint strategy as rmeta tables; we select the
255-
// number of byte elements per-array not per-element. This lets us read the whole edge
256-
// list for a node with one decoder call and also use the on-disk format in memory.
257-
let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize);
258-
// The in-memory structure for the edges list stores the byte width of the edges on
259-
// this node with the offset into the global edge data array.
260-
let edges_header = node_header.edges_header(&edge_list_data, num_edges);
259+
// If the length of this node's edge list is small, the length is stored in the header.
260+
// If it is not, we fall back to another decoder call.
261+
let num_edges = node_header.len().unwrap_or_else(|| d.read_u32());
261262

262-
edge_list_data.extend(d.read_raw_bytes(edges_len_bytes));
263+
// The edges index list uses the same varint strategy as rmeta tables; we select the
264+
// number of byte elements per-array not per-element. This lets us read the whole edge
265+
// list for a node with one decoder call and also use the on-disk format in memory.
266+
let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize);
267+
// The in-memory structure for the edges list stores the byte width of the edges on
268+
// this node with the offset into the global edge data array.
269+
let edges_header = node_header.edges_header(&edge_list_data, num_edges);
263270

264-
edge_list_indices[index] = edges_header;
271+
edge_list_data.extend(d.read_raw_bytes(edges_len_bytes));
272+
273+
edge_list_indices[index] = edges_header;
274+
}
265275
}
266276

267277
// When we access the edge list data, we do a fixed-size read from the edge list data then
@@ -312,10 +322,9 @@ impl SerializedDepGraph {
312322
/// * In whatever bits remain, the length of the edge list for this node, if it fits
313323
struct SerializedNodeHeader<D> {
314324
// 2 bytes for the DepNode
315-
// 4 bytes for the index
316325
// 16 for Fingerprint in DepNode
317326
// 16 for Fingerprint in NodeInfo
318-
bytes: [u8; 38],
327+
bytes: [u8; 34],
319328
_marker: PhantomData<D>,
320329
}
321330

@@ -325,7 +334,6 @@ struct Unpacked {
325334
len: Option<u32>,
326335
bytes_per_index: usize,
327336
kind: DepKind,
328-
index: SerializedDepNodeIndex,
329337
hash: PackedFingerprint,
330338
fingerprint: Fingerprint,
331339
}
@@ -347,7 +355,6 @@ impl<D: Deps> SerializedNodeHeader<D> {
347355
#[inline]
348356
fn new(
349357
node: &DepNode,
350-
index: DepNodeIndex,
351358
fingerprint: Fingerprint,
352359
edge_max_index: u32,
353360
edge_count: usize,
@@ -369,11 +376,10 @@ impl<D: Deps> SerializedNodeHeader<D> {
369376
let hash: Fingerprint = node.hash.into();
370377

371378
// Using half-open ranges ensures an unconditional panic if we get the magic numbers wrong.
372-
let mut bytes = [0u8; 38];
379+
let mut bytes = [0u8; 34];
373380
bytes[..2].copy_from_slice(&head.to_le_bytes());
374-
bytes[2..6].copy_from_slice(&index.as_u32().to_le_bytes());
375-
bytes[6..22].copy_from_slice(&hash.to_le_bytes());
376-
bytes[22..].copy_from_slice(&fingerprint.to_le_bytes());
381+
bytes[2..18].copy_from_slice(&hash.to_le_bytes());
382+
bytes[18..].copy_from_slice(&fingerprint.to_le_bytes());
377383

378384
#[cfg(debug_assertions)]
379385
{
@@ -390,9 +396,8 @@ impl<D: Deps> SerializedNodeHeader<D> {
390396
#[inline]
391397
fn unpack(&self) -> Unpacked {
392398
let head = u16::from_le_bytes(self.bytes[..2].try_into().unwrap());
393-
let index = u32::from_le_bytes(self.bytes[2..6].try_into().unwrap());
394-
let hash = self.bytes[6..22].try_into().unwrap();
395-
let fingerprint = self.bytes[22..].try_into().unwrap();
399+
let hash = self.bytes[2..18].try_into().unwrap();
400+
let fingerprint = self.bytes[18..].try_into().unwrap();
396401

397402
let kind = head & mask(Self::KIND_BITS) as u16;
398403
let bytes_per_index = (head >> Self::KIND_BITS) & mask(Self::WIDTH_BITS) as u16;
@@ -402,7 +407,6 @@ impl<D: Deps> SerializedNodeHeader<D> {
402407
len: len.checked_sub(1),
403408
bytes_per_index: bytes_per_index as usize + 1,
404409
kind: DepKind::new(kind),
405-
index: SerializedDepNodeIndex::from_u32(index),
406410
hash: Fingerprint::from_le_bytes(hash).into(),
407411
fingerprint: Fingerprint::from_le_bytes(fingerprint),
408412
}
@@ -418,11 +422,6 @@ impl<D: Deps> SerializedNodeHeader<D> {
418422
self.unpack().bytes_per_index
419423
}
420424

421-
#[inline]
422-
fn index(&self) -> SerializedDepNodeIndex {
423-
self.unpack().index
424-
}
425-
426425
#[inline]
427426
fn fingerprint(&self) -> Fingerprint {
428427
self.unpack().fingerprint
@@ -451,15 +450,10 @@ struct NodeInfo {
451450
}
452451

453452
impl NodeInfo {
454-
fn encode<D: Deps>(&self, e: &mut MemEncoder, index: DepNodeIndex) {
453+
fn encode<D: Deps>(&self, e: &mut MemEncoder) {
455454
let NodeInfo { ref node, fingerprint, ref edges } = *self;
456-
let header = SerializedNodeHeader::<D>::new(
457-
node,
458-
index,
459-
fingerprint,
460-
edges.max_index(),
461-
edges.len(),
462-
);
455+
let header =
456+
SerializedNodeHeader::<D>::new(node, fingerprint, edges.max_index(), edges.len());
463457
e.write_array(header.bytes);
464458

465459
if header.len().is_none() {
@@ -483,7 +477,6 @@ impl NodeInfo {
483477
fn encode_promoted<D: Deps>(
484478
e: &mut MemEncoder,
485479
node: &DepNode,
486-
index: DepNodeIndex,
487480
fingerprint: Fingerprint,
488481
prev_index: SerializedDepNodeIndex,
489482
colors: &DepNodeColorMap,
@@ -496,7 +489,7 @@ impl NodeInfo {
496489
let edge_max =
497490
edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
498491

499-
let header = SerializedNodeHeader::<D>::new(node, index, fingerprint, edge_max, edge_count);
492+
let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count);
500493
e.write_array(header.bytes);
501494

502495
if header.len().is_none() {
@@ -529,6 +522,9 @@ struct LocalEncoderState {
529522
encoder: MemEncoder,
530523
node_count: usize,
531524
edge_count: usize,
525+
chunk_count: usize,
526+
527+
in_chunk: bool,
532528

533529
/// Stores the number of times we've encoded each dep kind.
534530
kind_stats: Vec<u32>,
@@ -538,6 +534,7 @@ struct LocalEncoderResult {
538534
node_max: u32,
539535
node_count: usize,
540536
edge_count: usize,
537+
chunk_count: usize,
541538

542539
/// Stores the number of times we've encoded each dep kind.
543540
kind_stats: Vec<u32>,
@@ -565,6 +562,8 @@ impl<D: Deps> EncoderState<D> {
565562
remaining_node_index: 0,
566563
edge_count: 0,
567564
node_count: 0,
565+
chunk_count: 0,
566+
in_chunk: false,
568567
encoder: MemEncoder::new(),
569568
kind_stats: iter::repeat_n(0, D::DEP_KIND_MAX as usize + 1).collect(),
570569
})
@@ -573,6 +572,31 @@ impl<D: Deps> EncoderState<D> {
573572
}
574573
}
575574

575+
#[inline]
576+
fn end_chunk(&self, local: &mut LocalEncoderState) {
577+
if !local.in_chunk {
578+
return;
579+
}
580+
local.in_chunk = false;
581+
582+
NodeInfo {
583+
node: DepNode { kind: D::DEP_KIND_NULL, hash: Fingerprint::ZERO.into() },
584+
fingerprint: Fingerprint::ZERO,
585+
edges: EdgesVec::new(),
586+
}
587+
.encode::<D>(&mut local.encoder);
588+
}
589+
590+
#[inline]
591+
fn start_chunk(&self, local: &mut LocalEncoderState, first_index: u32) {
592+
if local.in_chunk {
593+
self.end_chunk(local);
594+
}
595+
local.in_chunk = true;
596+
local.chunk_count += 1;
597+
local.encoder.emit_u32(first_index);
598+
}
599+
576600
#[inline]
577601
fn next_index(&self, local: &mut LocalEncoderState) -> DepNodeIndex {
578602
if local.remaining_node_index == 0 {
@@ -587,6 +611,8 @@ impl<D: Deps> EncoderState<D> {
587611
// Check that we'll stay within `u32`
588612
local.next_node_index.checked_add(COUNT).unwrap();
589613

614+
self.start_chunk(local, local.next_node_index);
615+
590616
local.remaining_node_index = COUNT;
591617
}
592618

@@ -643,10 +669,13 @@ impl<D: Deps> EncoderState<D> {
643669

644670
#[inline]
645671
fn flush_mem_encoder(&self, local: &mut LocalEncoderState) {
646-
let data = &mut local.encoder.data;
647-
if data.len() > 64 * 1024 {
648-
self.file.lock().as_mut().unwrap().emit_raw_bytes(&data[..]);
649-
data.clear();
672+
if local.encoder.data.len() > 64 * 1024 {
673+
self.end_chunk(local);
674+
self.file.lock().as_mut().unwrap().emit_raw_bytes(&local.encoder.data[..]);
675+
local.encoder.data.clear();
676+
if local.remaining_node_index > 0 {
677+
self.start_chunk(local, local.next_node_index);
678+
}
650679
}
651680
}
652681

@@ -658,7 +687,7 @@ impl<D: Deps> EncoderState<D> {
658687
record_graph: &Option<Lock<DepGraphQuery>>,
659688
local: &mut LocalEncoderState,
660689
) {
661-
node.encode::<D>(&mut local.encoder, index);
690+
node.encode::<D>(&mut local.encoder);
662691
self.flush_mem_encoder(&mut *local);
663692
self.record(
664693
&node.node,
@@ -690,7 +719,6 @@ impl<D: Deps> EncoderState<D> {
690719
let edge_count = NodeInfo::encode_promoted::<D>(
691720
&mut local.encoder,
692721
node,
693-
index,
694722
fingerprint,
695723
prev_index,
696724
colors,
@@ -719,6 +747,8 @@ impl<D: Deps> EncoderState<D> {
719747
let results = broadcast(|_| {
720748
let mut local = self.local.borrow_mut();
721749

750+
self.end_chunk(&mut *local);
751+
722752
// Prevent more indices from being allocated on this thread.
723753
local.remaining_node_index = 0;
724754

@@ -730,6 +760,7 @@ impl<D: Deps> EncoderState<D> {
730760
node_max: local.next_node_index,
731761
node_count: local.node_count,
732762
edge_count: local.edge_count,
763+
chunk_count: local.chunk_count,
733764
}
734765
});
735766

@@ -740,11 +771,13 @@ impl<D: Deps> EncoderState<D> {
740771
let mut node_max = 0;
741772
let mut node_count = 0;
742773
let mut edge_count = 0;
774+
let mut chunk_count = 0;
743775

744776
for result in results {
745777
node_max = max(node_max, result.node_max);
746778
node_count += result.node_count;
747779
edge_count += result.edge_count;
780+
chunk_count += result.chunk_count;
748781
for (i, stat) in result.kind_stats.iter().enumerate() {
749782
kind_stats[i] += stat;
750783
}
@@ -762,6 +795,7 @@ impl<D: Deps> EncoderState<D> {
762795
IntEncodedWithFixedSize(node_max.try_into().unwrap()).encode(&mut encoder);
763796
IntEncodedWithFixedSize(node_count.try_into().unwrap()).encode(&mut encoder);
764797
IntEncodedWithFixedSize(edge_count.try_into().unwrap()).encode(&mut encoder);
798+
IntEncodedWithFixedSize(chunk_count.try_into().unwrap()).encode(&mut encoder);
765799
debug!("position: {:?}", encoder.position());
766800
// Drop the encoder so that nothing is written after the counts.
767801
let result = encoder.finish();

0 commit comments

Comments
 (0)