Skip to content

[#53] Track SerializeReference instances in analyze - #153

Open
SkowronskiAndrew wants to merge 1 commit into
mainfrom
issue53
Open

SkowronskiAndrew wants to merge 1 commit into
mainfrom
issue53

Conversation

@SkowronskiAndrew

Copy link
Copy Markdown
Collaborator

Summary

Fixes #53.

A [SerializeReference] field stores a C# object ("managed reference") inside the MonoBehaviour or ScriptableObject that holds it. That type has no MonoScript. Its class, namespace and assembly are written into the managed reference registry of every object that holds an instance. So in built content it is hard to see which of these types are used, and where they are used. For example, before you rename a class you want to confirm that the old name is not in any AssetBundle.

analyze now records every instance in a new managed_references table. There are two views over it:

  • managed_reference_view: one row per instance, with the object that holds it.
  • view_managed_reference_types: instance count, holding-object count and total size per type.

Changes

Analyzer

  • The existing TypeTree walk (PPtrAndCrcProcessor) already visits every registry entry for all three registry formats:

    • version 1: entries back to back, ended by a sentinel.
    • version 2: a RefIds array.
    • version 3: the Unity 6.7 frame, which no TypeTree node describes.

    All three paths go through ProcessRefTypeData. That method now calls a second callback with the owning object id, rid, class, namespace, assembly, and the byte size of the instance's data (the type name is not included). Null references get no row.

  • SerializedFileSQLiteWriter writes the rows through a new AddManagedReference command.

  • The data is stored inside the MonoBehaviour and does not depend on refs, so the table is filled whatever skip options are used. With --skip-references --skip-crc the walk is normally skipped completely. It now still runs for objects whose root TypeTree has a registry (checked on the TypeTree, once per object), so those options only cost extra for MonoBehaviours that use [SerializeReference].

Schema

  • Init.sql: managed_references table, managed_reference_view, view_managed_reference_types. user_version goes from 9 to 10.
  • Finalize.sql: index on managed_references(object).

Documentation

  • analyzer-schema.md: a new "SerializeReference tables and views" section, entries in the at-a-glance table, and the version 10 row.
  • analyze-examples.md: a "Finding SerializeReference types" example covering the class-rename check, the per-type summary, and a join with script_object_view that shows the owning script's class.
  • command-analyze.md: notes that managed_references is still populated with --skip-references.

Testing

dotnet test: all tests pass. New coverage uses existing fixtures for every registry version:

  • AssetBundles/2019.4 and 2020.3 (v1), 2021.3–2023.1 (v2): Apple/Orange instances, class, assembly and size, with and without --skip-references --skip-crc.
  • PlayerWithTypeTrees (v2) and PlayerWithTypeTreesV26 (v3) contain the same asset. The row is identical in both (rid, type, size 20), which shows the v3 size covers the instance data and not the frame. The v3 case is also run with both skip options, and refs stays empty.
  • AssetBundleTypeTreeVariations/v26/managedreferences.bundle: nested and array instances are recorded once each (9 rows, 9 distinct rids), and the null reference has no row.

I checked the row counts manually against dump output for the same files.

🤖 Generated with Claude Code

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Analyze command - track "SerializeReference" usage

1 participant