Repository: vercel/next.js
Pull request: perf(turbopack): Remove needless alloc for AQMF

### What?

Trivial `Cow` optimization for AQMF data

### Why?

We can avoid calling `to_vec()` on this data, and according to the profiling result, compression was a memory hog.

Closes PACK-4833

Changed files:
filename: turbopack/crates/turbo-persistence/src/db.rs
patch: @@ -1,5 +1,6 @@
 use std::{
     any::{Any, TypeId},
+    borrow::Cow,
     collections::HashSet,
     fs::{self, File, OpenOptions, ReadDir},
     io::{BufWriter, Write},
@@ -1050,7 +1051,7 @@ impl TurboPersistence {
                     let index_in_meta = ssts_with_ranges[index].index_in_meta;
                     let meta_file = &meta_files[meta_index];
                     let entry = meta_file.entry(index_in_meta);
-                    let aqmf = entry.raw_aqmf(meta_file.aqmf_data()).to_vec();
+                    let aqmf = Cow::Borrowed(entry.raw_aqmf(meta_file.aqmf_data()));
                     let meta = StaticSortedFileBuilderMeta {
                         min_hash: entry.min_hash(),
                         max_hash: entry.max_hash(),

filename: turbopack/crates/turbo-persistence/src/meta_file_builder.rs
patch: @@ -9,15 +9,15 @@ use byteorder::{BE, WriteBytesExt};
 
 use crate::static_sorted_file_builder::StaticSortedFileBuilderMeta;
 
-pub struct MetaFileBuilder {
+pub struct MetaFileBuilder<'a> {
     family: u32,
     /// Entries in the meta file, tuples of (sequence_number, StaticSortedFileBuilderMetaResult)
-    entries: Vec<(u32, StaticSortedFileBuilderMeta)>,
+    entries: Vec<(u32, StaticSortedFileBuilderMeta<'a>)>,
     /// Obsolete SST files, represented by their sequence numbers
     obsolete_sst_files: Vec<u32>,
 }
 
-impl MetaFileBuilder {
+impl<'a> MetaFileBuilder<'a> {
     pub fn new(family: u32) -> Self {
         Self {
             family,
@@ -26,7 +26,7 @@ impl MetaFileBuilder {
         }
     }
 
-    pub fn add(&mut self, sequence_number: u32, sst: StaticSortedFileBuilderMeta) {
+    pub fn add(&mut self, sequence_number: u32, sst: StaticSortedFileBuilderMeta<'a>) {
         self.entries.push((sequence_number, sst));
     }
 

filename: turbopack/crates/turbo-persistence/src/static_sorted_file_builder.rs
patch: @@ -1,4 +1,5 @@
 use std::{
+    borrow::Cow,
     cmp::min,
     fs::File,
     io::{self, BufWriter, Seek, Write},
@@ -72,13 +73,13 @@ pub enum EntryValue<'l> {
 }
 
 #[derive(Debug, Clone)]
-pub struct StaticSortedFileBuilderMeta {
+pub struct StaticSortedFileBuilderMeta<'a> {
     /// The minimum hash of the keys in the SST file
     pub min_hash: u64,
     /// The maximum hash of the keys in the SST file
     pub max_hash: u64,
     /// The AQMF data
-    pub aqmf: Vec<u8>,
+    pub aqmf: Cow<'a, [u8]>,
     /// The key compression dictionary
     pub key_compression_dictionary_length: u16,
     /// The value compression dictionary
@@ -92,8 +93,8 @@ pub struct StaticSortedFileBuilderMeta {
 }
 
 #[derive(Debug, Default)]
-pub struct StaticSortedFileBuilder {
-    aqmf: Vec<u8>,
+pub struct StaticSortedFileBuilder<'a> {
+    aqmf: Cow<'a, [u8]>,
     key_compression_dictionary: Vec<u8>,
     value_compression_dictionary: Vec<u8>,
     blocks: Vec<(u32, Vec<u8>)>,
@@ -102,7 +103,7 @@ pub struct StaticSortedFileBuilder {
     entries: u64,
 }
 
-impl StaticSortedFileBuilder {
+impl<'a> StaticSortedFileBuilder<'a> {
     pub fn new<E: Entry>(
         entries: &[E],
         total_key_size: usize,
@@ -136,7 +137,7 @@ impl StaticSortedFileBuilder {
         for entry in entries {
             debug_assert!(filter.contains_fingerprint(entry.key_hash()));
         }
-        self.aqmf = pot::to_vec(&filter).expect("AQMF serialization failed");
+        self.aqmf = Cow::Owned(pot::to_vec(&filter).expect("AQMF serialization failed"));
     }
 
     /// Computes compression dictionaries from keys and values of all entries
@@ -389,7 +390,7 @@ impl StaticSortedFileBuilder {
 
     /// Writes the SST file.
     #[tracing::instrument(level = "trace", skip_all)]
-    pub fn write(self, file: &Path) -> io::Result<(StaticSortedFileBuilderMeta, File)> {
+    pub fn write(self, file: &Path) -> io::Result<(StaticSortedFileBuilderMeta<'a>, File)> {
         let mut file = BufWriter::new(File::create(file)?);
         // Write the key compression dictionary
         file.write_all(&self.key_compression_dictionary)?;

filename: turbopack/crates/turbo-persistence/src/write_batch.rs
patch: @@ -78,7 +78,7 @@ pub struct WriteBatch<K: StoreKey + Send, const FAMILIES: usize> {
     /// Collectors in use. The thread local collectors flush into these when they are full.
     collectors: [Mutex<GlobalCollectorState<K>>; FAMILIES],
     /// Meta file builders for each family.
-    meta_collectors: [Mutex<Vec<(u32, StaticSortedFileBuilderMeta)>>; FAMILIES],
+    meta_collectors: [Mutex<Vec<(u32, StaticSortedFileBuilderMeta<'static>)>>; FAMILIES],
     /// The list of new SST files that have been created.
     /// Tuple of (sequence number, file).
     new_sst_files: Mutex<Vec<(u32, File)>>,