Skip to content
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

Mono interpreter has a general limit of 64k for offsets and indexes #46622

Open
3 tasks
BrzVlad opened this issue Jan 6, 2021 · 14 comments
Open
3 tasks

Mono interpreter has a general limit of 64k for offsets and indexes #46622

BrzVlad opened this issue Jan 6, 2021 · 14 comments

Comments

@BrzVlad
Copy link
Member

BrzVlad commented Jan 6, 2021

The interpreter instruction stream is an array of ushort. This data type is used to store most of the common data, from opcode, offsets, static data indexes etc. In some uncommon scenarios, for large methods, we can hit this limit.

  • Most instructions have source and destination offsets. Methods with many locals can have this space overflowed. Currently we throw Unable to run method: locals size too big.. Tests hitting this are JIT/jit64/opt/cse/HugeArray1 and JIT/Regression/JitBlue/GitHub_21990
  • Some instructions contain embedded offsets that are expected to fit in an ushort (for example MINT_LDFLD, MINT_STFLD). Test hitting this JIT/Regression/JitBlue/Runtime_34170
  • A method has more than 64k data_items. [interp] Support methods that need more than 64k data items #59221
@BrzVlad BrzVlad added this to the Future milestone Jan 6, 2021
@BrzVlad BrzVlad self-assigned this Jan 6, 2021
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jan 6, 2021
@ghost
Copy link

ghost commented Jan 6, 2021

Tagging subscribers to this area: @BrzVlad
See info in area-owners.md if you want to be subscribed.

Issue Details

When encountering a method with a large enough local space, the compiler will throw Unable to run method: locals size too big.

Author: BrzVlad
Assignees: BrzVlad
Labels:

area-Codegen-Interpreter-mono

Milestone: Future

@Eddie-Hartman
Copy link

@BrzVlad @javiercn I believe that I am currently running into this issue. The odd thing is that it doesn't occur when running locally on Chrome or Edge in Debug or Release mode, but occurs when the app is deployed. It also occurs locally and when deployed in Firefox.

I'm currently looking for a workaround I can use and not to get this fixed in the runtime itself as I need a fix soon. My situation is that I'm running a Blazor WASM app with EntityFrameworkCore using this library. My migration is seeding information for U.S. counties for a lookup table, and therefore has thousands of insert statements like so:

            migrationBuilder.InsertData(
                table: "CountyLookup",
                columns: new[] { "CountyCode", "StateCode", "CountyName" },
                values: new object[,]
                {
                    { 1, 1, "Autauga County" },
                    { 3, 1, "Baldwin County" },
                    { 5, 1, "Barbour County" },

I would prefer to keep this generated rather than manually providing an insert into script so that this data may be easily updated with future migrations (it's being built from another file).

I've tried breaking it up into inserts of say 50 at a time rather than all at once, hoping that would reduce the amount of locals, but that didn't work.

  1. Do you have any other suggestions?
  2. Is this potentially fixed in .net 8?
  3. Do you know why it works fine running locally, but fails when deployed?

@BrzVlad
Copy link
Member Author

BrzVlad commented Nov 2, 2023

What is the exact error that you are hitting ? Locals size too big ?

@Eddie-Hartman
Copy link

Eddie-Hartman commented Nov 2, 2023

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Unable to run method 'void DataProject.Migrations.BridgeDbContextNS.Addingcountylookuptable:Up (Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)': locals size too big.
System.InvalidProgramException: Unable to run method 'void DataProject.Migrations.BridgeDbContextNS.Addingcountylookuptable:Up (Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)': locals size too big.
   at Microsoft.EntityFrameworkCore.Migrations.Migration.BuildOperations(Action`1 buildAction)
   at Microsoft.EntityFrameworkCore.Migrations.Migration.get_UpOperations()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.GenerateUpSql(Migration migration, MigrationsSqlGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.<>c__DisplayClass16_2.<GetMigrationCommandLists>b__2()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateAsync(String targetMigration, CancellationToken cancellationToken)
   at SqliteWasmHelper.SqliteWasmDbContextFactory`1.<CreateDbContextAsync>d__15[[DataProject.Data.BridgeDbContext, DataProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at SNBI_Collector.Pages.Index.FetchInitialData()
   at SNBI_Collector.Pages.Index.OnInitializedAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )

If it would help at all, you can see it live here: snbicollector.com

I'm happy to turn on verbose logging in the runtime if you could tell me how to do that. I can see in transform.c I could potentially get more info once that level of logging is enabled.

@BrzVlad
Copy link
Member Author

BrzVlad commented Nov 2, 2023

Is there any chance I could get an isolated project for reproducing this ?

@Eddie-Hartman
Copy link

Creating an isolated case is certainly a possibility, but would take some time to spin up. If you are potentially open to it, I'm fine with setting up a call and potentially sending over what I currently have to expedite the process. I could send you a meeting invite however you prefer (google meet, teams, etc), but I could send a teams invite to your gmail if that's good for you.

If you'd prefer I send a different more open source repo for reproducibility, that would take some time and I'd have to focus on fixing my problem at hand first.

@BrzVlad
Copy link
Member Author

BrzVlad commented Nov 2, 2023

Could you try adding in your wasm project <WasmDebugLevel>-1</WasmDebugLevel>. Not sure if this has the effect I'm hoping but worth giving it a try. Feel free to mail me directly and we can figure something out.

@Eddie-Hartman
Copy link

Eddie-Hartman commented Nov 2, 2023

@BrzVlad I kind of surprised myself and was able to set up a repo for reproducing the issue pretty quickly: https://github.com/Eddie-Hartman/LocalsSize
Clone, run, then open the URL in Firefox because again, the error does NOT appear locally for whatever reason when using Chrome or Edge locally.
Let me know if there is anything else I can do to help. I'll try the WasmDebugLevel above in the meantime and see if I can find anything.

@Eddie-Hartman
Copy link

I walked away from this for a while, but came back and tried to debug a bit more. I really don't understand the above. Adding that to my project file does not add additional logging.

I also tried some other search results such as:

<WasmNativeDebugSymbols>true</WasmNativeDebugSymbols>
<WasmNativeStrip>false</WasmNativeStrip>

which didn't work either and:
https://github.com/dotnet/runtime/blob/main/src/mono/wasm/debugger/debugger.md
which seems like a rabbit hole I don't want to go down unless I know that's the correct way to debug this.

Please let me know how to proceed.

@BrzVlad
Copy link
Member Author

BrzVlad commented Nov 3, 2023

The point of WasmDebugLevel was not to add verbose logging for investigation but rather I expected it to disable all optimizations on the interpreter, which is the configuration when running from VS. My understanding is that it didn't fix anything ? I somewhat suspect tiering to be at the root cause of this issue.

I can't run your sample because it fails with:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: TypeInitialization_Type, Microsoft.Data.Sqlite.SqliteConnection
System.TypeInitializationException: TypeInitialization_Type, Microsoft.Data.Sqlite.SqliteConnection
 ---> System.Reflection.TargetInvocationException: Arg_TargetInvocationException
 ---> System.DllNotFoundException: e_sqlite3

Could you share a folder publish of the sample ?

@Eddie-Hartman
Copy link

Yeah when I added that it didn't seem to have any effect. It still failed. I emailed you an invite to a call if you'd like to join. I'm debugging the repo for reproducing the issue now to see if there is anything I can do to get that working for you. Weird that it runs just fine on my machine.

@Eddie-Hartman
Copy link

@Eddie-Hartman
Copy link

I was able to get a workaround working thanks to the devs in the discord in the webassembley channel. I had it broken up into different methods calls, but I needed to specifically do it like so:

InsertCountyData1(migrationBuilder);
InsertCountyData2(migrationBuilder);

Rather than having a method where I was passing the data in as arguments.

Thanks to @vargaz @BrzVlad @lambdageek and @kg for your help!

@BrzVlad
Copy link
Member Author

BrzVlad commented Nov 5, 2023

The culprit for the above scenario was indeed tiering, with untiered version not being able to properly compact the space for the locals. This scenario will be handled in the future by #94381.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants