-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not store JSON Yul ASTs and Yul CFG in CompilerStack
#15451
Conversation
Hmm... tests seem to be failing due to different native locations in the optimized AST: - "nativeSrc": "58:298:0",
+ "nativeSrc": "58:315:0",
"nodeType": "YulBlock", - "nativeSrc": "68:282:0",
+ "nativeSrc": "68:299:0",
"nodeType": "YulBlock", - "nativeSrc": "111:27:0",
+ "nativeSrc": "128:27:0",
"nodeType": "YulVariableDeclaration", |
CompilerStack
BenchmarksUsing the improved benchmarking scripts from #15450. IR pipeline
Note: For the last two the numbers do not represent the whole project, because in each there is a contract that fails to compile due to a StackTooDeep error. Legacy pipelineThere should be zero difference here since these artifacts are only generated when IR is requested.
|
An interesting thing is that this overhead of JSON processing did not show up in profiling I did recently: #15179 (comment). I'd expect to see One thing I do see is |
Not sure if it is the problem leading to it, but it may be a problem regardless: contract(_contractName).yulIROptimized with the output of loadGeneratedIR(loadGeneratedIR(loadGeneratedIR(contract(_contractName).yulIROptimized).print()).print()).print() just to see if it stays consistent under repeated loading and printing operations. It doesn't: @@ -1,10 +1,10 @@
/// @use-src 0:"test/cmdlineTests/ast_ir/input.sol"
object "C_2" {
code {
{
- /// @src 0:60:73 "contract C {}"
+ /// @src 0:60:73
let _1 := memoryguard(0x80)
mstore(64, _1)
if callvalue() { revert(0, 0) }
let _2 := datasize("C_2_deployed")
codecopy(_1, dataoffset("C_2_deployed"), _2)
@@ -13,11 +13,11 @@
}
/// @use-src 0:"test/cmdlineTests/ast_ir/input.sol"
object "C_2_deployed" {
code {
{
- /// @src 0:60:73 "contract C {}"
+ /// @src 0:60:73
revert(0, 0)
}
}
data ".metadata" hex"a2646970667358221220b0b8ededf61719cebc357d865ee54b27e1d49d69b9c45f8107b7210d698521d864736f6c63782c302e382e32382d646576656c6f702e323032342e392e32352b636f6d6d69742e34663630383164662e6d6f64005d"
}
|
Also the difference is multiples of |
4f6081d
to
7ff5fbd
Compare
There probably is something to it, the exact 17 char difference is too specific, but at least in the snippet above the cause is just the way you print it.
I'm trying to debug it but, oddly, after rebasing this I cannot reproduce this difference locally. The test passes for me somehow. I haven't tried it before the rebase, so I'm not sure if it's just not reproducible on my machine in general or if it's the rebase that changed something... EDIT: It still fails in CI so it's not the rebase. |
7ff5fbd
to
c23cac8
Compare
I think I figured it out. Looks like my previous fix for native locations (#15457) did not properly account for code snippets in debug info and I did not notice that. TBH it's quite hard to notice when these offsets are wrong in test output and verifying them all manually is not feasible - which is the reason why we had the original issue in the first place. New fix: #15457. |
c23cac8
to
2360c54
Compare
995da44
to
614f312
Compare
614f312
to
4216aa7
Compare
2360c54
to
c78a8d2
Compare
- The JSON artifacts take a lot of memory so always generating them is very wasteful. - Even when requested, they are only relevant while the current contract is being copmiled. We only really want to store the serialized JSON that will be returned to the user. - This actually also speeds up compilation quite a bit.
c78a8d2
to
9ccc44a
Compare
I did some more benchmarking and profiling on top of this. First I ran our profiling ( I also checked how long each part of the pipeline takes now:
The numbers are from running full compilation with only specific outputs selected, except for "Optimizer steps", which is the time I got from profiling optimization steps in #15465 (comment). The same in relative terms:
Conclusions
|
Depends on #15457.Merged.This fixes excessive memory usage due to JSON representation of Yul ASTs and Yul CFG being always calculated from IR, even if not requested as an output.
The PR fixes the problem by changing
CompilerStack
so that these artifacts are only prepared when requested by CLI orStandardCompiler
. This requires reparsing the IR from scratch each time (and the PR does not go out of its way to ensure it's parsed only once if multiple ASTs are requested), but Yul parsing is generally fast and these artifacts are not needed in the typical Solidity development workflow anyway.Effects
This has a huge impact on memory usage and also non-negligible impact on running time.
For example when compiling Uniswap using our external benchmarks, disabling generation of this data makes it go from 143 s and 5 GB RAM down to 115 s and 1.5 GB RAM.
I've been noticing the aggressive RAM usage for a while now, to the point that I had to be careful when running the external benchmarks - compiling Eigenlayer or Sablier sometimes required more than 30 GB RAM and would crash on my machine.