coral-xyz / anchor

⚓ Solana Sealevel Framework
https://anchor-lang.com
Apache License 2.0
3.36k stars 1.25k forks source link

Account Constraints affect stack size usage #2915

Closed nabeel99 closed 2 months ago

nabeel99 commented 2 months ago

I wasnt sure if this is a bug or an intended feature.

Problem: Faced with large stack variables i tried boxing it but still to no avail, i randomly removed constraints and saw a good % reduction in stack offset size , which made me experiment by adding and removing constraints and seeing there effect, i dont understand why does adding constraints affect stack size ? since even if i comment out the handler function stack size does not get affected so why is it specifically constraints affect stack size ?

nabeel99 commented 2 months ago

@acheroncrypto hoping you would have some insight, since it puzzles me as to when i add let test: [i32; 1024] = [0; 1024]; inside the handler function it dsnt cause the stack offset size to increase but constraints do ?

acheroncrypto commented 2 months ago

Constraints are essentially macros that expand to more Rust code. Some constraints result in a lot of code (e.g. init), which means you can easily go over the limit of the current stack frame if you use many constraints.

@acheroncrypto hoping you would have some insight, since it puzzles me as to when i add let test: [i32; 1024] = [0; 1024]; inside the handler function it dsnt cause the stack offset size to increase but constraints do ?

That's because the Rust compiler strips out any code that's not being used in the resulting binary. Also, sometimes you don't event get stack offset warnings on builds, but you get memory access errors in runtime instead.

nabeel99 commented 2 months ago

Constraints are essentially macros that expand to more Rust code. Some constraints result in a lot of code (e.g. init), which means you can easily go over the limit of the current stack frame if you use many constraints.

@acheroncrypto hoping you would have some insight, since it puzzles me as to when i add let test: [i32; 1024] = [0; 1024]; inside the handler function it dsnt cause the stack offset size to increase but constraints do ?

That's because the Rust compiler strips out any code that's not being used in the resulting binary. Also, sometimes you don't event get stack offset warnings on builds, but you get memory access errors in runtime instead.

Hey @acheroncrypto first of all thanks for clarifying. The solana 4kb stack frame limit is per function call, in a single Accounts structure , do all of the constraints in all the accounts present there share this single one stack frame or anchor optimizes each account and its constraints are given seperate stack frame to basically avoid hitting stack limits for large structs since i already boxed them, and am still offset by 3.9k bytes, is the solution to manually do the constraints in seperate functions or fork anchor and try to impl the optimization i talked abt above, seperating constraints into seperate function for each account in the giant accounts struct, since i have a lot of constraints on some of them.

nabeel99 commented 2 months ago

Btw i dont think there is but on the offchance am wrong, does there exist a way to log stack usage to enable easier experimentation, since the solution to my problem of it being offset by a significant factor seems manually solvable by handrolling some of the stuff anchor codegen is doing in anchor derive accounts. And offload into seperate functioms but to do it with a fast dev feed backloop any way to observe stack usage would do wonders.

nabeel99 commented 2 months ago

@acheroncrypto i dont remeber where i read this, but i remember armani recommending composite structs i.e seperate it into multiple derive accounts and embed into a final derive accounts , it was quite back not sure if the internal codegen then uses seperate functions to circumvent this issue.

nabeel99 commented 2 months ago

Closing this in favour of #2920 , anyone who comes across this issue, if you want to use anchor, one possible solution is to use composite structs.