Skip to content

Commit 513f8e5

Browse files
committed
[README] Add JNI overhead invocation observations.
1 parent ca9e4f1 commit 513f8e5

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ To run a specific test fixture, set the FIXTURE variable:
107107

108108
## Notes
109109

110+
### JDK and Global References
111+
110112
The JDK VM supports an effectively unlimited number of global references.
111113
While Dalvik craps out after creating ~64k GREFs, consider the following
112114
on the JDK:
@@ -127,3 +129,45 @@ I killed the above loop after reaching 25686556 instances.
127129

128130
I'm not sure when the JDK would stop handing out references, but it's probably
129131
bound to process heap limits (e.g. depends on 32-bit vs. 64-bit process).
132+
133+
### JNI Invocation Overhead
134+
135+
[tests/PerformanceTests/TimingTests.cs](tests/PerformanceTests/TimingTests.cs)
136+
contains various tests to investigate the overheads involved in using JNI to
137+
invoke Java methods. In particular, see the
138+
`Java.Interop.PerformanceTests.JniMethodInvocationOverheadTiming.MethodInvocationTiming()`
139+
tests, invokes a JNI method `count` times and attempts to "normalize" that to
140+
invoking an equivalent, non-inlined, C# method.
141+
142+
[Commit c60f6093][c60f6093] observed that Android appeared to be much faster
143+
than the JVM at these tests. This observation appears to have been wrong.
144+
More interesting is that the "JNI method invocation overhead," defined as
145+
what this test is attempting to measure (which may be wrong!), varies
146+
based on the number of method invocations.
147+
148+
[c60f6093]: https://github.com/xamarin/Java.Interop/commit/c60f6093
149+
150+
For example, if we look at just the summary information of one test
151+
as we vary the value of `count`, the number of times we invoke the
152+
Java method via JNI or the C# method, we see that there is a nonlinear
153+
relationship between the count and the overhead:
154+
155+
count= 10: Method Invoke: static void i3: JNI is 5x managed
156+
count= 100: Method Invoke: static void i3: JNI is 10x managed
157+
count= 500: Method Invoke: static void i3: JNI is 22x managed
158+
count= 1000: Method Invoke: static void i3: JNI is 63x managed
159+
count= 10000: Method Invoke: static void i3: JNI is 474x managed
160+
count=100000: Method Invoke: static void i3: JNI is 808x managed
161+
162+
Particularly troubling is the *huge* jump between count=1000 and
163+
count=10000. Count=1000000 is provided for comparison with the JVM,
164+
which provides the following results:
165+
166+
count=1000000: Method Invoke: static void i3: JNI is 413x managed [JVM]
167+
168+
We don't know why there's a jump, but this is in fact somewhat encouraging:
169+
if you're only calling methods in a one-off fashion -- as is frequently
170+
the case in Xamarin.Android -- then the overhead isn't actually that bad,
171+
on a per-method invoke basis. It appears to only get really bad when
172+
invoking the same method repetitively, *a lot*, which I believe shouldn't
173+
be *that* common a use case (outside of image manipulation?).

0 commit comments

Comments
 (0)