Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fast FieldInfo reflection#98199

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
steveharter merged 12 commits intodotnet:mainfromsteveharter:FastFieldAccess2
Feb 14, 2024
Merged

Conversation

steveharter
Copy link
Contributor

@stevehartersteveharter commentedFeb 9, 2024
edited
Loading

This makesFieldInfo.SetValue andGetValue faster; the most improvements are:

  • ~9x faster for getting a reference type on a static field
  • ~6x faster for getting a reference type on an instance field
  • ~6x faster for setting a primitive type on a static field
  • ~4x faster for setting a primitive type on an instance field
  • ~3x faster for setting a reference type on a static field
  • ~2x faster for setting a reference type on an instance field

The cases for setting a value type in a static field are not improved since they follow the existing "slow path" to the runtime due to special logic including "box into" where we box the value type into an existing boxed object (non-primitive static value types are stored that way) and other special logic such as nullability. There are also other "slow paths" for cases where static variables are not fixed in memory, but these are somewhat rare cases.

This was done without using IL-emit; raw memory operations are used. This means there is no warm-up time and works on platforms that do not support emit.

This helps align field performance with fast property performance work (which is IL-emit based) that was done inv7 andv8. For example:

  • A property getter currently returns a reference type in ~8ns.
  • The same operation for a field getwas ~24ns which is 3x slower than the getter and thus a bit out of line;now with the PR, it is ~4ns which is 2x faster than the getter.

In the future, the "FieldAccessor" class added here can be exposed publicly and methods added that do not require boxing\unboxing.

New benchmarks were added indotnet/performance#3863.

Click for benchmarks
| Method                 | Job        | Toolchain                 | Mean      | Error     | StdDev    | Median    | Min       | Max       | Ratio | RatioSD | Gen0   | Allocated | Alloc Ratio ||----------------------- |----------- |-------------------------- |----------:|----------:|----------:|----------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|| Field_Get_int          | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 33.587 ns | 0.2600 ns | 0.2305 ns | 33.632 ns | 33.172 ns | 33.865 ns |  1.00 |    0.00 | 0.0022 |      24 B |        1.00 || Field_Get_int          | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 36.796 ns | 0.3367 ns | 0.2985 ns | 36.769 ns | 36.469 ns | 37.439 ns |  1.10 |    0.01 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_GetStatic_int    | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 31.082 ns | 0.2469 ns | 0.2189 ns | 31.092 ns | 30.681 ns | 31.403 ns |  1.00 |    0.00 | 0.0022 |      24 B |        1.00 || Field_GetStatic_int    | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 40.721 ns | 0.4257 ns | 0.3555 ns | 40.684 ns | 40.081 ns | 41.492 ns |  1.31 |    0.02 | 0.0023 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_Get_class        | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  |  4.067 ns | 0.0652 ns | 0.0578 ns |  4.049 ns |  4.007 ns |  4.196 ns |  1.00 |    0.00 |      - |         - |          NA || Field_Get_class        | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 24.524 ns | 0.1935 ns | 0.1616 ns | 24.550 ns | 24.277 ns | 24.890 ns |  6.02 |    0.08 |      - |         - |          NA ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_GetStatic_class  | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  |  2.582 ns | 0.0155 ns | 0.0137 ns |  2.584 ns |  2.560 ns |  2.610 ns |  1.00 |    0.00 |      - |         - |          NA || Field_GetStatic_class  | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 23.314 ns | 0.1366 ns | 0.1211 ns | 23.311 ns | 23.113 ns | 23.591 ns |  9.03 |    0.07 |      - |         - |          NA ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_Get_struct       | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 36.907 ns | 0.5991 ns | 0.5604 ns | 36.717 ns | 36.259 ns | 38.036 ns |  1.00 |    0.00 | 0.0022 |      24 B |        1.00 || Field_Get_struct       | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 42.983 ns | 0.3850 ns | 0.3413 ns | 42.990 ns | 42.385 ns | 43.473 ns |  1.17 |    0.02 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_GetStatic_struct | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 32.613 ns | 0.3827 ns | 0.3393 ns | 32.534 ns | 32.089 ns | 33.224 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 || Field_GetStatic_struct | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 49.550 ns | 0.5162 ns | 0.4829 ns | 49.586 ns | 48.833 ns | 50.682 ns |  1.52 |    0.02 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_Set_int          | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  |  8.492 ns | 0.2633 ns | 0.2926 ns |  8.354 ns |  8.159 ns |  9.155 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 || Field_Set_int          | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 36.042 ns | 0.2227 ns | 0.2083 ns | 35.982 ns | 35.614 ns | 36.390 ns |  4.23 |    0.16 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_SetStatic_int    | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  |  7.025 ns | 0.0746 ns | 0.0661 ns |  7.008 ns |  6.945 ns |  7.170 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 || Field_SetStatic_int    | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 41.886 ns | 0.3051 ns | 0.2854 ns | 41.981 ns | 41.416 ns | 42.310 ns |  5.97 |    0.06 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_Set_class        | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 16.439 ns | 0.1553 ns | 0.1297 ns | 16.473 ns | 16.176 ns | 16.677 ns |  1.00 |    0.00 | 0.0022 |      24 B |        1.00 || Field_Set_class        | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 36.227 ns | 0.5184 ns | 0.4849 ns | 36.005 ns | 35.649 ns | 37.190 ns |  2.21 |    0.03 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_SetStatic_class  | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 15.404 ns | 0.1883 ns | 0.1761 ns | 15.388 ns | 15.147 ns | 15.713 ns |  1.00 |    0.00 | 0.0022 |      24 B |        1.00 || Field_SetStatic_class  | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 47.866 ns | 0.3628 ns | 0.3216 ns | 47.870 ns | 47.301 ns | 48.449 ns |  3.11 |    0.04 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_Set_struct       | Job-KTJOJZ | \FIELD_AFTER\corerun.exe  | 29.592 ns | 0.2402 ns | 0.2129 ns | 29.603 ns | 29.322 ns | 30.117 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 || Field_Set_struct       | Job-HGOSQE | \FIELD_BEFORE\corerun.exe | 31.048 ns | 0.2436 ns | 0.2279 ns | 31.092 ns | 30.488 ns | 31.332 ns |  1.05 |    0.01 | 0.0022 |      24 B |        1.00 ||                        |            |                           |           |           |           |           |           |           |       |         |        |           |             || Field_SetStatic_struct | Job-OBFLPU | \FIELD_AFTER\corerun.exe  | 38.023 ns | 0.4172 ns | 0.3902 ns | 37.993 ns | 37.409 ns | 38.663 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 || Field_SetStatic_struct | Job-BQNCGS | \FIELD_BEFORE\corerun.exe | 38.558 ns | 0.3617 ns | 0.3206 ns | 38.526 ns | 38.109 ns | 39.295 ns |  1.01 |    0.01 | 0.0023 |      24 B |        1.00 |

<\details>

danmoseley, samsosa, buyaa-n, and ericstj reacted with hooray emojiAlgorithmsAreCool, En3Tho, am11, samsosa, KirillKornienko, PaulusParssinen, saul, buyaa-n, and GerardSmit reacted with rocket emoji
@stevehartersteveharter self-assigned thisFeb 9, 2024
@ghost
Copy link

Tagging subscribers to this area: @dotnet/area-system-reflection
See info inarea-owners.md if you want to be subscribed.

Issue Details

Verifying tests

Author:steveharter
Assignees:steveharter
Labels:

area-System.Reflection,tenet-performance

Milestone:-

Copy link
Contributor

@buyaa-nbuyaa-n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

JFYI there is anopen question in the PR, otherwise LGTM.

@steveharter
Copy link
ContributorAuthor

steveharter commentedFeb 13, 2024
edited
Loading

@jkotas I noticed that the runtime wraps exceptions thrown inFieldInfo.GetValue\SetValue() (such asTypeInitializationException) withTargetInvocationException however that is not done by Mono and NativeAOT.

Unlike invoking a static method, calling GetField\SetField doesn't run any code (fields don't have code) except for the possibility of indirectly calling the class initializer.

So unless I hear otherwise, I'll create issue for Mono and NativeAOT to throwTargetInvocationException if the class initializer throws. I'd consider it a low-priority edge case. The other option is to change the Core runtime to match Mono\NativeAOT.

UPDATE: there doesn't appear to be hard rules when the class initializer is called other than "when first accessed", so eitherTypeInitializationException orTargetInvocationException seems fine to me. Leaving as-is.

@stevehartersteveharter merged commitd3ebc97 intodotnet:mainFeb 14, 2024
@stevehartersteveharter deleted the FastFieldAccess2 branchFebruary 14, 2024 20:58
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsMar 16, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@AaronRobinsonMSFTAaronRobinsonMSFTAaronRobinsonMSFT left review comments

@jkotasjkotasjkotas approved these changes

@buyaa-nbuyaa-nbuyaa-n approved these changes

@marek-safarmarek-safarAwaiting requested review from marek-safar

Assignees

@stevehartersteveharter

Labels
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@steveharter@jkotas@AaronRobinsonMSFT@buyaa-n

[8]ページ先頭

©2009-2025 Movatter.jp