Skip to content

Redundant byte array allocations in CPPToJavaSequentialOutStream::Write #69

@alexei-osipov

Description

@alexei-osipov

Current ISequentialOutStream interface wrapper has some inefficiency because it does not re-use allocated byte array.

From CPPToJavaSequentialOutStream.cpp:

    jbyteArray dataArray = jniEnvInstance->NewByteArray(size); // New large byte array allocation
    jniEnvInstance->SetByteArrayRegion(dataArray, 0, (jsize) size, (const jbyte*) data); // Fill it with data

    // public int write(byte[] data);
    jint result = _iSequentialOutStream->write(jniEnvInstance, _javaImplementation, dataArray); // Pass data to Java code (ISequentialOutStream#write(byte[] data))
    if (jniEnvInstance.exceptionCheck()) {
        jniEnvInstance->DeleteLocalRef(dataArray); // Dispose array
        return S_FALSE;
    }
    jniEnvInstance->DeleteLocalRef(dataArray); // Dispose array

Source:

jbyteArray dataArray = jniEnvInstance->NewByteArray(size);
jniEnvInstance->SetByteArrayRegion(dataArray, 0, (jsize) size, (const jbyte*) data);
// public int write(byte[] data);
jint result = _iSequentialOutStream->write(jniEnvInstance, _javaImplementation, dataArray);
if (jniEnvInstance.exceptionCheck()) {
jniEnvInstance->DeleteLocalRef(dataArray);
return S_FALSE;
}
jniEnvInstance->DeleteLocalRef(dataArray);

Problem here that allocation of a large array is relatively costly operation and has some additional performance drawbacks (causes CPU cache thrashing and adds some extra Java GC pressure.

Suggestion:

  1. Change Java interface ISequentialOutStream#write(byte[] data) to ISequentialOutStream#write(byte[] data, int offset, int length) (offset field is not really necessary through, as it always going to be 0).
  2. Instead of immediate array disposal, keep it ("cache") for re-use.
  3. Instead of new array allocation check if existing array has enough capacity for size bytes. If not, dispose existing array and allocate new, big enough for the new data chunk.
  4. Dispose the "cached" array when extraction process completes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions