Skip to content

Commit 83c7003

Browse files
committed
perf: change SCHEMA_STORAGE from Vec to HashMap for O(1) lookups
1 parent 1d5cff6 commit 83c7003

7 files changed

Lines changed: 181 additions & 164 deletions

File tree

crates/vespera_macro/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
8484
pub fn derive_schema(input: TokenStream) -> TokenStream {
8585
let input = syn::parse_macro_input!(input as syn::DeriveInput);
8686
let (metadata, expanded) = schema_impl::process_derive_schema(&input);
87-
SCHEMA_STORAGE.lock().unwrap().push(metadata);
87+
let name = metadata.name.clone();
88+
SCHEMA_STORAGE.lock().unwrap().insert(name, metadata);
8889
TokenStream::from(expanded)
8990
}
9091

@@ -220,7 +221,8 @@ pub fn schema_type(input: TokenStream) -> TokenStream {
220221
// If custom name is provided, register the schema directly
221222
// This ensures it appears in OpenAPI even when `ignore` is set
222223
if let Some(metadata) = generated_metadata {
223-
SCHEMA_STORAGE.lock().unwrap().push(metadata);
224+
let name = metadata.name.clone();
225+
SCHEMA_STORAGE.lock().unwrap().insert(name, metadata);
224226
}
225227
TokenStream::from(tokens)
226228
}

crates/vespera_macro/src/schema_impl.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,15 @@
3030
//! - [`extract_schema_name_attr`] - Extract custom name from `#[schema]` attribute
3131
//! - [`process_derive_schema`] - Process the derive macro input and register the type
3232
33-
use std::sync::{LazyLock, Mutex};
33+
use std::{
34+
collections::HashMap,
35+
sync::{LazyLock, Mutex},
36+
};
3437

3538
use crate::metadata::StructMetadata;
3639

37-
#[cfg(not(tarpaulin_include))]
38-
pub const fn init_schema_storage() -> Mutex<Vec<StructMetadata>> {
39-
Mutex::new(Vec::new())
40-
}
41-
42-
pub static SCHEMA_STORAGE: LazyLock<Mutex<Vec<StructMetadata>>> =
43-
LazyLock::new(init_schema_storage);
40+
pub static SCHEMA_STORAGE: LazyLock<Mutex<HashMap<String, StructMetadata>>> =
41+
LazyLock::new(|| Mutex::new(HashMap::new()));
4442

4543
/// Extract custom schema name from #[schema(name = "...")] attribute
4644
pub fn extract_schema_name_attr(attrs: &[syn::Attribute]) -> Option<String> {

crates/vespera_macro/src/schema_macro/codegen.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ pub fn generate_filtered_schema(
2323
struct_item: &syn::ItemStruct,
2424
omit_set: &HashSet<String>,
2525
pick_set: &HashSet<String>,
26-
schema_storage: &[StructMetadata],
26+
schema_storage: &std::collections::HashMap<String, StructMetadata>,
2727
) -> TokenStream {
2828
let rename_all = extract_rename_all(&struct_item.attrs);
2929

3030
// Build known_schemas and struct_definitions for type resolution
31-
let known_schemas: HashSet<String> = schema_storage.iter().map(|s| s.name.clone()).collect();
31+
let known_schemas: HashSet<String> = schema_storage.keys().cloned().collect();
3232
let struct_definitions: std::collections::HashMap<String, String> = schema_storage
33-
.iter()
33+
.values()
3434
.map(|s| (s.name.clone(), s.definition.clone()))
3535
.collect();
3636

@@ -213,7 +213,7 @@ pub fn schema_to_tokens(schema: &Schema) -> TokenStream {
213213

214214
#[cfg(test)]
215215
mod tests {
216-
use std::collections::HashSet;
216+
use std::collections::{HashMap, HashSet};
217217

218218
use vespera_core::schema::{Reference, Schema, SchemaRef, SchemaType};
219219

@@ -224,7 +224,8 @@ mod tests {
224224
let struct_item: syn::ItemStruct = syn::parse_str("pub struct Empty {}").unwrap();
225225
let omit_set = HashSet::new();
226226
let pick_set = HashSet::new();
227-
let output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &[]).to_string();
227+
let output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &HashMap::new())
228+
.to_string();
228229
assert!(output.contains("properties"));
229230
}
230231

@@ -241,7 +242,8 @@ mod tests {
241242
.unwrap();
242243
let omit_set = HashSet::new();
243244
let pick_set = HashSet::new();
244-
let output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &[]).to_string();
245+
let output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &HashMap::new())
246+
.to_string();
245247
assert!(output.contains("None"));
246248
}
247249

@@ -258,7 +260,7 @@ mod tests {
258260
.unwrap();
259261
let omit_set = HashSet::new();
260262
let pick_set = HashSet::new();
261-
let _output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &[]);
263+
let _output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &HashMap::new());
262264
}
263265

264266
#[test]
@@ -267,7 +269,7 @@ mod tests {
267269
syn::parse_str("pub struct Tuple(i32, String);").unwrap();
268270
let omit_set = HashSet::new();
269271
let pick_set = HashSet::new();
270-
let _output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &[]);
272+
let _output = generate_filtered_schema(&struct_item, &omit_set, &pick_set, &HashMap::new());
271273
}
272274

273275
#[test]

crates/vespera_macro/src/schema_macro/from_model.rs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//!
33
//! Generates async `from_model` implementations for `SeaORM` models with relations.
44
5+
use std::collections::HashMap;
6+
57
use proc_macro2::TokenStream;
68
use quote::quote;
79
use syn::Type;
@@ -80,7 +82,7 @@ pub fn generate_from_model_with_relations(
8082
field_mappings: &[(syn::Ident, syn::Ident, bool, bool)],
8183
relation_fields: &[RelationFieldInfo],
8284
source_module_path: &[String],
83-
_schema_storage: &[StructMetadata],
85+
_schema_storage: &HashMap<String, StructMetadata>,
8486
) -> TokenStream {
8587
// Build relation loading statements
8688
let relation_loads: Vec<TokenStream> = relation_fields
@@ -583,7 +585,7 @@ mod tests {
583585
&field_mappings,
584586
&relation_fields,
585587
&source_module_path,
586-
&[],
588+
&HashMap::new(),
587589
);
588590
let output = tokens.to_string();
589591

@@ -612,7 +614,7 @@ mod tests {
612614
&field_mappings,
613615
&relation_fields,
614616
&source_module_path,
615-
&[],
617+
&HashMap::new(),
616618
);
617619
let output = tokens.to_string();
618620

@@ -655,7 +657,7 @@ mod tests {
655657
&field_mappings,
656658
&relation_fields,
657659
&source_module_path,
658-
&[],
660+
&HashMap::new(),
659661
);
660662
let output = tokens.to_string();
661663

@@ -704,7 +706,7 @@ mod tests {
704706
&field_mappings,
705707
&relation_fields,
706708
&source_module_path,
707-
&[],
709+
&HashMap::new(),
708710
);
709711
let output = tokens.to_string();
710712

@@ -749,7 +751,7 @@ mod tests {
749751
&field_mappings,
750752
&relation_fields,
751753
&source_module_path,
752-
&[],
754+
&HashMap::new(),
753755
);
754756
let output = tokens.to_string();
755757

@@ -785,7 +787,7 @@ mod tests {
785787
&field_mappings,
786788
&relation_fields,
787789
&source_module_path,
788-
&[],
790+
&HashMap::new(),
789791
);
790792
let output = tokens.to_string();
791793

@@ -832,7 +834,7 @@ mod tests {
832834
&field_mappings,
833835
&relation_fields,
834836
&source_module_path,
835-
&[],
837+
&HashMap::new(),
836838
);
837839
let output = tokens.to_string();
838840

@@ -873,7 +875,7 @@ mod tests {
873875
&field_mappings,
874876
&relation_fields,
875877
&source_module_path,
876-
&[],
878+
&HashMap::new(),
877879
);
878880
let output = tokens.to_string();
879881

@@ -914,7 +916,7 @@ mod tests {
914916
&field_mappings,
915917
&relation_fields,
916918
&source_module_path,
917-
&[],
919+
&HashMap::new(),
918920
);
919921
let output = tokens.to_string();
920922

@@ -960,7 +962,7 @@ mod tests {
960962
&field_mappings,
961963
&relation_fields,
962964
&source_module_path,
963-
&[],
965+
&HashMap::new(),
964966
);
965967
let output = tokens.to_string();
966968

@@ -1058,7 +1060,7 @@ pub struct Model {
10581060
&field_mappings,
10591061
&relation_fields,
10601062
&source_module_path,
1061-
&[],
1063+
&HashMap::new(),
10621064
);
10631065

10641066
// Restore CARGO_MANIFEST_DIR
@@ -1145,7 +1147,7 @@ pub struct Model {
11451147
&field_mappings,
11461148
&relation_fields,
11471149
&source_module_path,
1148-
&[],
1150+
&HashMap::new(),
11491151
);
11501152

11511153
// Restore CARGO_MANIFEST_DIR
@@ -1231,7 +1233,7 @@ pub struct Model {
12311233
&field_mappings,
12321234
&relation_fields,
12331235
&source_module_path,
1234-
&[],
1236+
&HashMap::new(),
12351237
);
12361238

12371239
// Restore CARGO_MANIFEST_DIR
@@ -1301,7 +1303,7 @@ pub struct Model {
13011303
&field_mappings,
13021304
&relation_fields,
13031305
&source_module_path,
1304-
&[],
1306+
&HashMap::new(),
13051307
);
13061308

13071309
let output = tokens.to_string();
@@ -1379,7 +1381,7 @@ pub struct Model {
13791381
&field_mappings,
13801382
&relation_fields,
13811383
&source_module_path,
1382-
&[],
1384+
&HashMap::new(),
13831385
);
13841386

13851387
// Restore CARGO_MANIFEST_DIR
@@ -1466,7 +1468,7 @@ pub struct Model {
14661468
&field_mappings,
14671469
&relation_fields,
14681470
&source_module_path,
1469-
&[],
1471+
&HashMap::new(),
14701472
);
14711473

14721474
// Restore CARGO_MANIFEST_DIR
@@ -1562,7 +1564,7 @@ pub struct Model {
15621564
&field_mappings,
15631565
&relation_fields,
15641566
&source_module_path,
1565-
&[],
1567+
&HashMap::new(),
15661568
);
15671569

15681570
// Restore CARGO_MANIFEST_DIR
@@ -1659,7 +1661,7 @@ pub struct Model {
16591661
&field_mappings,
16601662
&relation_fields,
16611663
&source_module_path,
1662-
&[],
1664+
&HashMap::new(),
16631665
);
16641666

16651667
// Restore CARGO_MANIFEST_DIR
@@ -1757,7 +1759,7 @@ pub struct Model {
17571759
&field_mappings,
17581760
&relation_fields,
17591761
&source_module_path,
1760-
&[],
1762+
&HashMap::new(),
17611763
);
17621764

17631765
// Restore CARGO_MANIFEST_DIR
@@ -1911,7 +1913,7 @@ pub struct Model {
19111913
&field_mappings,
19121914
&relation_fields,
19131915
&source_module_path,
1914-
&[],
1916+
&HashMap::new(),
19151917
);
19161918

19171919
// Restore CARGO_MANIFEST_DIR
@@ -2022,7 +2024,7 @@ pub struct Model {
20222024
&field_mappings,
20232025
&relation_fields,
20242026
&source_module_path,
2025-
&[],
2027+
&HashMap::new(),
20262028
);
20272029
let output = tokens.to_string();
20282030

@@ -2089,7 +2091,7 @@ pub struct Model {
20892091
&field_mappings,
20902092
&relation_fields,
20912093
&source_module_path,
2092-
&[],
2094+
&HashMap::new(),
20932095
);
20942096
let output = tokens.to_string();
20952097

@@ -2146,7 +2148,7 @@ pub struct Model {
21462148
&field_mappings,
21472149
&relation_fields,
21482150
&source_module_path,
2149-
&[],
2151+
&HashMap::new(),
21502152
);
21512153
let output = tokens.to_string();
21522154

@@ -2203,7 +2205,7 @@ pub struct Model {
22032205
&field_mappings,
22042206
&relation_fields,
22052207
&source_module_path,
2206-
&[],
2208+
&HashMap::new(),
22072209
);
22082210
let output = tokens.to_string();
22092211

@@ -2287,7 +2289,7 @@ pub struct Model {
22872289
&field_mappings,
22882290
&relation_fields,
22892291
&source_module_path,
2290-
&[],
2292+
&HashMap::new(),
22912293
);
22922294

22932295
unsafe {
@@ -2387,7 +2389,7 @@ pub struct Model {
23872389
&field_mappings,
23882390
&relation_fields,
23892391
&source_module_path,
2390-
&[],
2392+
&HashMap::new(),
23912393
);
23922394

23932395
unsafe {
@@ -2475,7 +2477,7 @@ pub struct Model {
24752477
&field_mappings,
24762478
&relation_fields,
24772479
&source_module_path,
2478-
&[],
2480+
&HashMap::new(),
24792481
);
24802482

24812483
unsafe {
@@ -2570,7 +2572,7 @@ pub struct Model {
25702572
&field_mappings,
25712573
&relation_fields,
25722574
&source_module_path,
2573-
&[],
2575+
&HashMap::new(),
25742576
);
25752577

25762578
unsafe {

0 commit comments

Comments
 (0)