{"id":26194630,"url":"https://github.com/lucacappelletti94/syn-performance","last_synced_at":"2026-03-15T12:07:18.127Z","repository":{"id":278357752,"uuid":"935308946","full_name":"LucaCappelletti94/syn-performance","owner":"LucaCappelletti94","description":"Small crate to measure the time requirements of syn parsing with different usages.","archived":false,"fork":false,"pushed_at":"2025-02-19T11:10:41.000Z","size":26,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-10T03:55:47.113Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LucaCappelletti94.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-19T08:35:52.000Z","updated_at":"2025-02-20T15:16:08.000Z","dependencies_parsed_at":"2025-02-19T11:35:34.933Z","dependency_job_id":null,"html_url":"https://github.com/LucaCappelletti94/syn-performance","commit_stats":null,"previous_names":["lucacappelletti94/syn-performance"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucaCappelletti94%2Fsyn-performance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucaCappelletti94%2Fsyn-performance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucaCappelletti94%2Fsyn-performance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucaCappelletti94%2Fsyn-performance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LucaCappelletti94","download_url":"https://codeload.github.com/LucaCappelletti94/syn-performance/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243141186,"owners_count":20242817,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-12T01:59:28.491Z","updated_at":"2025-12-24T12:15:03.970Z","avatar_url":"https://github.com/LucaCappelletti94.png","language":"HTML","readme":"# Measuring the performance of syn using different strategies\n\nSmall crate to measure the time requirements of [`syn`](https://docs.rs/syn/latest/syn/) parsing with different usages.\n\n## Experiment\n\nThe experiment consist in generating the implementation of the following trait for some types:\n\n```rust\n/// Trait to measure the performance of parsing\npub trait Foo {\n    /// Returns the number of attributes in the struct\n    fn number_of_attributes() -\u003e usize;\n    /// Returns the number of fields in the struct\n    fn number_of_optional_fields() -\u003e usize;\n}\n```\n\nwere the abstract struct which will also be needed to implement will be defined as:\n\n```rust\n/// Attribute struct\npub struct Attribute {\n    /// Name of the attribute\n    pub name: String,\n    /// Type of the attribute\n    pub optional: bool,\n}\n\nlet my_struct = vec![\n    Attribute { name: \"field1\".to_string(), optional: false },\n    Attribute { name: \"field2\".to_string(), optional: true },\n    Attribute { name: \"field3\".to_string(), optional: false },\n];\n```\n\nAnd measuring how much time the procedure generating the [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) takes. We implement the generation procedure following different strategies:\n\n1. **Quote, using [`syn`](https://docs.rs/syn/latest/syn/) with full features**: The naive implementation generates the [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) by using the [`quote!`](https://docs.rs/quote/latest/quote/) macro to generate the\n   implementation of the trait for each type. This is the most straightforward way to generate the code, but\n   it is not the most efficient one. Specifically, we will enable all the features of [`syn`](https://docs.rs/syn/latest/syn/) to see whether the\n   performance is significantly affected by the features enabled. This implementation is found in the\n   [`using-syn-full`](using-syn-full) crate.\n2. **Quote, using [`syn`](https://docs.rs/syn/latest/syn/) with minimal features**: The naive implementation generates the [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) by using the [`quote!`](https://docs.rs/quote/latest/quote/) macro to generate the\n   implementation of the trait for each type. This time, we will enable only the features that are strictly\n   necessary to generate the code. This implementation is found in the [`using-syn-partial`](using-syn-partial) crate.\n3. **Manual generation**: The manual implementation generates the [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) by using the [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) API directly. A priori, we expect this\n   implementation to be the most efficient one, as it avoids the overhead of the [`quote!`](https://docs.rs/quote/latest/quote/) macro. We still enable\n   all the features of [`syn`](https://docs.rs/syn/latest/syn/) to see whether the performance is significantly affected by the features enabled.\n   This implementation is found in the [`using-no-parsing-full-syn`](using-no-parsing-full-syn) crate.\n4. **Manual generation with minimal features**: In order to actually make use of all of the tokens necessary for the Manual generation,\n   it is necessary to enable the `full` feature set of [`syn`](https://docs.rs/syn/latest/syn/), and therefore we cannot, at this time, make a crate which uses\n   the \"minimal\" features set.\n\n## Results\n\nIn this section, we present the results of the experiment. We measure both the time necessary to build each of the\ncrates, the sizes of the generated binaries, and the time necessary to execute the code-generation code.\nWe use respectively [`cargo build --timings`](https://doc.rust-lang.org/cargo/reference/timings.html), `ls -lh target/debug/` and [`cargo bench`](https://doc.rust-lang.org/cargo/commands/cargo-bench.html). The benches are found specifically in the [`syn-bencher/benches`](syn-bencher/benches) directory.\n\n### Build times\n\nYou can find the `timings` reports in the [`timings`](timings) directory. Here follows the table illustrating the build\ntimes for each of the crates, both in debug and release mode. Note that since the first `cargo build` command also loads\nthe documents in memory, the first run takes longer than the subsequent ones - for this reason, we have run the `cargo build --timings`\ncommand twice for each crate. Between all of the `cargo build` runs, we have run `cargo clean` to ensure that the build times\nare not affected by the previous builds, as otherwise the build times become extremely small as effectively there is nothing\nmore to be built. We only report the results of the second run, which is free of the overhead of loading the documents in memory.\n\n| Crate | Debug (s) | Release (s) |\n|-------|-----------|-------------|\n| [`using-syn-full`](using-syn-full) | [0.9](timings/using-syn-full.debug.html) | [1.5](timings/using-syn-full.release.html) |\n| [`using-syn-partial`](using-syn-partial) | [0.9](timings/using-syn-partial.debug.html) | [1.1](timings/using-syn-partial.release.html) |\n| [`using-no-parsing-full-syn`](using-no-parsing-full-syn) | [0.9](timings/using-no-parsing-full-syn.debug.html) | [1.6](timings/using-no-parsing-full-syn.release.html) |\n\nSurprisingly enough, the build times are not significantly different between the different strategies. Even more surprisingly, the crate with the largest build time requirements is the one that uses the [`syn`](https://docs.rs/syn/latest/syn/) APIs directly without use of the [`quote!`](https://docs.rs/quote/latest/quote/) macro.\n\n### Binary sizes\n\nIn this section, we present the sizes of the generated binaries for each of the crates. The sizes are measured using the `ls -lh` command, for both the debug and release builds. No particular build flags are used to optimize for size.\n\n| Crate | Size (debug) | Size (release) |\n|-------|--------------|----------------|\n| [`using-syn-full`](using-syn-full) | 793KB | 272KB |\n| [`using-syn-partial`](using-syn-partial) | 793KB | 273KB |\n| [`using-no-parsing-full-syn`](using-no-parsing-full-syn) | 1.5MB | 387KB |\n\nUnexpectedly, we find again that the crate that uses the [`syn`](https://docs.rs/syn/latest/syn/) APIs directly without the [`quote!`](https://docs.rs/quote/latest/quote/) macro generates the largest binary. This is surprising, as we would expect the crate that uses the [`quote!`](https://docs.rs/quote/latest/quote/) macro to generate the largest binary, as it includes the [`quote!`](https://docs.rs/quote/latest/quote/) macro itself.\n\n### Execution times\n\nIn this section, we present the execution times for the code-generation code. The benchmarks are run using the `cargo bench` command, and are based on [`criterion`](https://docs.rs/criterion/latest/criterion/). The benchmarks are found in the [`syn-bencher/benches`](syn-bencher/benches) directory.\n\n| Crate | Time (ms) |\n|-------|-----------|\n| [`using-syn-full`](using-syn-full) | 8.44 |\n| [`using-syn-partial`](using-syn-partial) | 8.63 |\n| [`using-no-parsing-full-syn`](using-no-parsing-full-syn) | 9.42 |\n\nAgain, unexpectedly, the crate that uses the [`syn`](https://docs.rs/syn/latest/syn/) APIs directly without the [`quote!`](https://docs.rs/quote/latest/quote/) macro generates the slowest code-generation code. This is surprising, as we would expect the crate that uses the [`quote!`](https://docs.rs/quote/latest/quote/) macro to generate the slowest code-generation code, as it includes the [`quote!`](https://docs.rs/quote/latest/quote/) macro itself.\n\n## Conclusions\n\nOur experiments compared different approaches to generating Rust code with Syn, measuring build times, binary sizes, and execution times. The results we obtained were somewhat unexpected.\n\nBuild times were similar across strategies, with manual [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) handling (`using-no-parsing-full-syn`) taking the longest, contradicting expectations. Binary size analysis showed that this approach also produced the largest binaries, despite assumptions that [`quote!`](https://docs.rs/quote/latest/quote/) would be more bloated.\n\nExecution of [`criterion`](https://docs.rs/criterion/latest/criterion/)-based benchmarks revealed that manual [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) construction was the slowest, challenging the idea that avoiding [`quote!`](https://docs.rs/quote/latest/quote/) improves efficiency. Instead, manually managing tokens introduced overhead.\n\nOverall, using [`quote!`](https://docs.rs/quote/latest/quote/) with [`syn`](https://docs.rs/syn/latest/syn/)—even with all features—provides a balanced trade-off between build time, binary size, and runtime performance. Manual [`TokenStream`](https://docs.rs/proc-macro2/latest/proc_macro2/struct.TokenStream.html) handling does not offer clear advantages and may introduce inefficiencies. Future work should investigate why direct token manipulation results in larger, slower binaries and explore alternative optimizations.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucacappelletti94%2Fsyn-performance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucacappelletti94%2Fsyn-performance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucacappelletti94%2Fsyn-performance/lists"}