Skip to content

Improve the performance of isCircularProxy#1866

Merged
copybara-service[bot] merged 1 commit intomasterfrom
test_721486538
Feb 1, 2025
Merged

Improve the performance of isCircularProxy#1866
copybara-service[bot] merged 1 commit intomasterfrom
test_721486538

Conversation

@copybara-service
Copy link

Improve the performance of isCircularProxy

The map implementation used by MapMaker is fairly old and requires 2 levels of indirection (segments->table). Switching to ConcurrentHashMap would be better but this will still be redundant with logic inside of Proxy so instead we just use that. Based on some simple benchmarks this is about 5X as fast, and should save a bit memory.

A number of alternatives were considered

  • adding a marker interface to the list of proxy interfaces
    This is a completely ideal solution but fails due to our need to support proxying interfaces from all ClassLoaders and it isn't possible to proxy interfaces that cannot mutually 'see' each other. So we would need to 'inject' our interface into the Bootstrap classloader which seems impossible and risky, or create special 'child' classloaders that can bridge it, but this triggers issues with proxying package-private interfaces... sigh.
  • using a ClassValue, bootstrapping the value is tricky and while this is faster than the status quo, it would allocate an entry for every class we queried which could add up in a large application, and the approach in this change is faster.
  • using Proxy.isProxyInstance this works but is slower than an instanceof query.

The map implementation used by `MapMaker` is fairly old and requires 2 levels of indirection (segments->table).  Switching to `ConcurrentHashMap` would be better but this will still be redundant with logic inside of `Proxy` so instead we just use that.  Based on some simple benchmarks this is about 5X as fast, and should save a bit memory.

A number of alternatives were considered

* adding a marker interface to the list of proxy interfaces
  This is a completely ideal solution but fails due to our need to support proxying interfaces from all `ClassLoaders` and it isn't possible to proxy interfaces that cannot mutually 'see' each other.  So we would need to 'inject' our interface into the Bootstrap classloader which seems impossible and risky, or create special 'child' classloaders that can bridge it, but this triggers issues with proxying package-private interfaces... sigh.
* using a `ClassValue`, bootstrapping the value is tricky and while this is faster than the status quo, it would allocate an entry for every class we queried which could add up in a large application, and the approach in this change is faster.
* using `Proxy.isProxyInstance` this works but is slower than an `instanceof` query.

PiperOrigin-RevId: 721984180
@copybara-service copybara-service bot merged commit 41e8c06 into master Feb 1, 2025
@copybara-service copybara-service bot deleted the test_721486538 branch February 1, 2025 03:03
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.

1 participant