Improve compilation time in standard JSON mode and honor requested output (#461)

# Description

Compilation times for resolc were significantly slower than solc when:
* Multiple files were included in the JSON input file via
`--standard-json`
* And none of the files requested code generation
* (If only a subset of files requested code generation, both resolc and
solc were very slow)

Reason:
* Resolc unconditionally generated bytecode for all contracts, even if
not requested.
* When compiling to PolkaVM bytecode, we need to pass additional flags
(e.g. `irOptimized`) to solc. If these flags were not explicitly
requested, resolc also added these to the requested output since PolkaVM
bytecode was always generated.

## Breaking Changes

The following changes are breaking, but fix the semantics to match its
intended behavior:

* Compiling with `--standard-json` now compiles to PolkaVM bytecode
***only*** for the contracts explicitly requested in the
`outputSelection`.
* Compiling with `--standard-json` now outputs ***only*** the explicitly
requested output (e.g. `evm.assembly`, `evm.bytecode`, `ast`, etc.).

```jsonc
// Example:
{
  "settings": {
    // ...
    "outputSelection": {
      "src/common/GasService.sol": {
        // Contracts in this file will generate bytecode.
        // Only these fields of the JSON output selection will be in the `contracts` output.
        "*": ["abi", "evm.methodIdentifiers", "metadata", "evm.bytecode"],
        // Only this field of the JSON output selection will be in the `sources` output.
        "": ["ast"]
      },
      "src/common/Gateway.sol": {
        // No contracts in this file will generate bytecode.
        "*": ["abi", "evm.methodIdentifiers", "metadata"],
        // No `ast` will be in the `sources` output (only the automatically added `id`,
        // similar to solc as this is not a configurable output selection).
        "": []
      },
    }
  }
}
```

## Performance Improvements

When e.g. the standard JSON input file includes multiple files and
requests output for every contract as per this setting:

```jsonc
{
  "settings": {
    // ...
    "optimizer": { "enabled": true, "runs": 1 },
    "viaIR": true,
    "outputSelection": {
      "src/common/GasService.sol": {
        "*": ["abi", "evm.methodIdentifiers", "metadata", "evm.bytecode"],
      },
      // Rest of files..
    }
  }
}
```

The differences in compilation times depending on whether `evm.bytecode`
is selected in every file, one file, or no files can be seen below:

| Solc Optimizer (runs=1) | ViaIR | Request `abi`,
`evm.methodIdentifiers`, `metadata` | Request `evm.bytecode` | resolc
before | resolc after | solc v0.8.33 |

|:-----------------------:|:-----:|:---------:|:---------:|:-------------:|:------------:|:----------:|
| ✅ | ✅ | All files | All files | `~14.5s` | `~14.5s` | `~13.5s` |
| ✅ | ✅ | All files | One file | `~14.5s` | `~450ms` | `~13.5s` |
| ✅ | ✅ | All files | No files | `~14.5s` | `~390ms` | `~350ms` |

**Observations:**

* `resolc before` is roughly the same no matter the request
  * This is due to unconditionally generating bytecode
* When not requesting bytecode for any contracts:
  * `resolc after` now compiles in ~390ms (vs ~14.5s), similar to `solc`
* Neither `solc` nor `resolc after` generates bytecode when none of the
contracts request it
* When requesting bytecode for all contracts in _only one_ file:
  * `resolc after` now compiles in ~450ms (vs ~14.5s)
* `solc` still compiles in the same time as when requesting bytecode for
all contracts in all files
* This is something they have tried to improve (see
[Solidity#15373](https://github.com/argotorg/solidity/issues/15373) and
[Solidity#15615](https://github.com/argotorg/solidity/issues/15615)),
and the intended behavior seems to now be that bytecode should only be
generated when explicitly requested for each contract.
* Even though PRs have merged to try to fix it, their issue seems to
persist as of v0.8.33.

# Open Questions

* Foundry:
  * [x] Pruning of the AST:
* Just saw [this past
commit](https://github.com/paritytech/revive/pull/385) to not prune the
AST for Foundry compatibility.
    * Can Foundry not explicitly request `"": "ast"`?
    * **Answer:**
* Pruning the AST when not requested should be fine, as long as Foundry
explicitly requests it when needed.
      * Will be tested by Foundry maintainer.

# Review Notes

Changes in `docs/` (~25 files) can be skipped as they are automatically
updated after adding content to `book/` and rebuilding it.

# Resolved Issues

Closes #326

---------

Co-authored-by: xermicus <cyrill@parity.io>
This commit is contained in:
LJandxermicus authored and GitHub committed 2026-01-28 23:04:22 +01:00
1 parent 95ae938ddf
commit a4163512ff
52 files changed
+3827 -187

No files matched your search

+61 -4
View File
@@ -35,7 +35,7 @@
const path_to_root = "../";
const default_light_theme = "light";
const default_dark_theme = "navy";
window.path_to_searchindex_js = "../searchindex-c7304031.js";
window.path_to_searchindex_js = "../searchindex-575cfd18.js";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc-6f3f265e.js"></script>
@@ -175,16 +175,16 @@
<div id="mdbook-content" class="content">
<main>
<h1 id="standard-json-interface"><a class="header" href="#standard-json-interface">Standard JSON interface</a></h1>
<p>The <code>revive</code> compiler is mostly compatible with the <code>solc</code> standard JSON interface. There are a few additional (PVM related) <strong>input</strong> configurations:</p>
<p>The <code>revive</code> compiler is mostly compatible with the <code>solc</code> standard JSON interface. There are a few differences and additional (PVM related) <strong>input</strong> configurations:</p>
<h2 id="the-settingspolkavm-object"><a class="header" href="#the-settingspolkavm-object">The <code>settings.polkavm</code> object</a></h2>
<p>Used to configure PVM specific compiler settings.</p>
<h3 id="settingspolkavmdebuginformation"><a class="header" href="#settingspolkavmdebuginformation"><code>settings.polkavm.debugInformation</code></a></h3>
<p>A boolean value allowing to enable debug information. Corresponds to <code>resolc -g</code>.</p>
<h3 id="the-settingspolkavmmemoryconfig-object"><a class="header" href="#the-settingspolkavmmemoryconfig-object">The <code>settings.polkavm.memoryConfig</code> object</a></h3>
<p>Used to apply PVM specific memory configuration settings.</p>
<h4 id="settingspolkavmmemoryconifgheapsize"><a class="header" href="#settingspolkavmmemoryconifgheapsize"><code>settings.polkavm.memoryConifg.heapSize</code></a></h4>
<h4 id="settingspolkavmmemoryconfigheapsize"><a class="header" href="#settingspolkavmmemoryconfigheapsize"><code>settings.polkavm.memoryConfig.heapSize</code></a></h4>
<p>A numerical value allowing to configure the contract heap size. Corresponds to <code>resolc --heap-size</code>.</p>
<h4 id="settingspolkavmmemoryconifgstacksize"><a class="header" href="#settingspolkavmmemoryconifgstacksize"><code>settings.polkavm.memoryConifg.stackSize</code></a></h4>
<h4 id="settingspolkavmmemoryconfigstacksize"><a class="header" href="#settingspolkavmmemoryconfigstacksize"><code>settings.polkavm.memoryConfig.stackSize</code></a></h4>
<p>A numerical value allowing to configure the contract stack size. Corresponds to <code>resolc --stack-size</code>.</p>
<h2 id="the-settingsoptimizer-object"><a class="header" href="#the-settingsoptimizer-object">The <code>settings.optimizer</code> object</a></h2>
<p>The <code>settings.optimizer</code> object is augmented with support for PVM specific optimization settings.</p>
@@ -192,6 +192,63 @@
<p>A single char value to configure the LLVM optimizer settings. Corresponds to <code>resolc -O</code>.</p>
<h2 id="settingsllvmarguments"><a class="header" href="#settingsllvmarguments"><code>settings.llvmArguments</code></a></h2>
<p>Allows to specify arbitrary command line arguments to LLVM initialization. Used mainly for development and debugging purposes.</p>
<h2 id="the-settingsoutputselection-object"><a class="header" href="#the-settingsoutputselection-object">The <code>settings.outputSelection</code> object</a></h2>
<p>Used to select desired outputs.</p>
<h3 id="the-all--wildcard"><a class="header" href="#the-all--wildcard">The “all” (<code>*</code>) wildcard</a></h3>
<p>Resolc supports the “all” (<code>*</code>) wildcard for the file-level (first-level) and contract-level (second-level) keys. A file-level key can be either the wildcard or a specific file name, whereas the contract-level key can only be the wildcard for robustness reasons.</p>
<p>Thus, output can be requested in 2 ways:</p>
<pre><code class="language-json">// All files and all contracts:
{
"settings": {
"outputSelection": {
"*": {
"*": [/* specific contract-level output fields */],
"": [/* specific file-level output fields */]
}
}
}
}
// Specific files and all their contracts:
{
"settings": {
"outputSelection": {
"path/to/my/file.sol": {
"*": [/* specific contract-level output fields */],
"": [/* specific file-level output fields */]
},
// Rest of files...
}
}
}
</code></pre>
<h3 id="the-contract-level-evm-output-selection"><a class="header" href="#the-contract-level-evm-output-selection">The contract-level <code>evm</code> output selection</a></h3>
<blockquote class="blockquote-tag blockquote-tag-note">
<p class="blockquote-tag-title"><svg viewbox="0 0 16 16" width="18" height="18"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p>
<p>Currently, resolc supports requesting either the full <code>evm</code> output, or one more level of specificity, such as <code>evm.bytecode</code>.</p>
</blockquote>
<p>When requesting code generation, such as <code>evm.bytecode</code> or <code>evm.assembly</code>, the resolc compilation process additionally needs <code>ast</code>, <code>metadata</code>, <code>irOptimized</code>, and <code>evm.methodIdentifiers</code> selectors. These selectors will be automatically added if code generation is needed, but will only be included in the output if explicitly requested.</p>
<pre><code class="language-json">{
"settings": {
"outputSelection": {
"path/to/my/file1.sol": {
// Contracts in this file will generate bytecode.
// Only these fields of the JSON output selection will be in the `contracts` output.
"*": ["abi", "evm.methodIdentifiers", "metadata", "evm.bytecode"],
// Only this field of the JSON output selection will be in the `sources` output.
"": ["ast"]
},
"path/to/my/file2.sol": {
// No contracts in this file will generate bytecode.
"*": ["abi", "evm.methodIdentifiers", "metadata"],
// No `ast` will be in the `sources` output (only the automatically added `id`,
// similar to solc as this is not a configurable output selection).
"": []
},
}
}
}
</code></pre>
</main>