Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-12802] Android: Reduce JNI bridge calls used for string,object hashes

GitHub Issuen/a
TypeStory
PriorityLow
StatusOpen
ResolutionUnresolved
Affected Version/sRelease 3.0.0
Fix Version/sn/a
ComponentsAndroid
Labelsn/a
ReporterBlain Hamon
AssigneeUnknown
Created2013-02-21T08:08:37.000+0000
Updated2018-02-28T20:03:39.000+0000

Description

In investigating android performance hits, I noticed a LOT of calls to the JNI bridge in order to determine and convert between Java and v8 data types. In adding JNI-dedicated functionality to KrollDict, we can significantly reduce the bridge hits with 5 methods, an enum, and an array: An enum of data types, one of which is a meta-type to indicate 'done' An array of strings of common values and keys. Index 0 is NULL. On C++, there may also be a sparse lookup table to allow for quick conversion from a string into an array index. long getNextJNIEntry() On first call, it stashes on the Java side an array of keys and returns the first 'entry' for that key. Each subsequent call goes to the next key and returns the 'entry' for that key. After the last key is used, the 'done' meta-type is returned. This removes the need to get a key count or track indexes. The returned long maps to three values that are maskable: 0xFFFF FFFF 0000 0000 is value if int type, value string index if in string table 0x0000 0000 FFFF 0000 is key string index if in table (0 otherwise) 0x0000 0000 0000 FFFF is data type As such, this can shortcut many values as well as remove the need for many keys or string conversions, as well as remove all introspection bridge hits. String getJNIKey() Object getJNIObject() double getJNIDouble() These fetch values from the current 'entry', the nature of which is dependent on the data type. For example, date actually uses the getDouble as milliseconds. void putJNIValue(int keyInt, String keyString, int dataType, double valueDouble, Object valueObject); Defaults are 0/null. If keyInt is nonzero, keyString is ignored (should be null) and the lookup is used. The reason for having a single setter is that it reduces the number of method signatures needed, and the combinatorics of value/keys would require 4 methods instead. In doing it this way, we should be able to reduce the number of JNI bridge calls used in converting values to and from Java by at least an order of magnitude. Addendum: The same optimizations can be tooled to method call arrays and to event type strings. Addendum addendum: Before I go to sleep and forget it, this does not allow for reentrancy, but that's probably alright. After all, were a hash to contain itself directly or indirectly, our current conversion would be caught in an infinite loop. Also, look further into V8 and what string format is the fastest. Considering the conversion is between Java and v8, it may not ever live as char*.

Comments

  1. Blain Hamon 2013-03-06

    Those playing the home game, https://github.com/BlainHamon/titanium_mobile/compare/timob-12802
  2. Ingo Muschenetz 2013-10-08

    Based on comments, it appears this may not actually be a bottleneck. Deferring.

JSON Source