Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6eb27ef9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cache least recently used output buffer."

parents b6d3eecb 19f8adfb
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -64,9 +64,13 @@ public class FastDataPerfTest {
        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        while (state.keepRunning()) {
            os.reset();
            final FastDataOutput out = new FastDataOutput(os, BUFFER_SIZE);
            final FastDataOutput out = FastDataOutput.obtain(os);
            try {
                doWrite(out);
                out.flush();
            } finally {
                out.release();
            }
        }
    }

+7 −2
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
            throw new UnsupportedOperationException();
        }

        mOut = new FastDataOutput(os, BUFFER_SIZE);
        mOut = FastDataOutput.obtain(os);
        mOut.write(PROTOCOL_MAGIC_VERSION_0);

        mTagCount = 0;
@@ -138,8 +138,10 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {

    @Override
    public void flush() throws IOException {
        if (mOut != null) {
            mOut.flush();
        }
    }

    @Override
    public void startDocument(@Nullable String encoding, @Nullable Boolean standalone)
@@ -157,6 +159,9 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
    public void endDocument() throws IOException {
        mOut.writeByte(END_DOCUMENT | TYPE_NULL);
        flush();

        mOut.release();
        mOut = null;
    }

    @Override
+50 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Optimized implementation of {@link DataOutput} which buffers data in memory
@@ -41,23 +42,26 @@ import java.util.Objects;
public class FastDataOutput implements DataOutput, Flushable, Closeable {
    private static final int MAX_UNSIGNED_SHORT = 65_535;

    private static final int BUFFER_SIZE = 32_768;

    private static AtomicReference<FastDataOutput> sOutCache = new AtomicReference<>();

    private final VMRuntime mRuntime;
    private final OutputStream mOut;

    private final byte[] mBuffer;
    private final long mBufferPtr;
    private final int mBufferCap;

    private OutputStream mOut;
    private int mBufferPos;

    /**
     * Values that have been "interned" by {@link #writeInternedUTF(String)}.
     */
    private HashMap<String, Short> mStringRefs = new HashMap<>();
    private final HashMap<String, Short> mStringRefs = new HashMap<>();

    public FastDataOutput(@NonNull OutputStream out, int bufferSize) {
        mRuntime = VMRuntime.getRuntime();
        mOut = Objects.requireNonNull(out);
        if (bufferSize < 8) {
            throw new IllegalArgumentException();
        }
@@ -65,6 +69,48 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
        mBuffer = (byte[]) mRuntime.newNonMovableArray(byte.class, bufferSize);
        mBufferPtr = mRuntime.addressOf(mBuffer);
        mBufferCap = mBuffer.length;

        setOutput(out);
    }

    /**
     * Create a new FastDataOutput object or retrieve one from cache.
     */
    public static FastDataOutput obtain(@NonNull OutputStream out) {
        FastDataOutput instance = sOutCache.getAndSet(null);
        if (instance != null) {
            instance.setOutput(out);
            return instance;
        }
        return new FastDataOutput(out, BUFFER_SIZE);
    }

    /**
     * Put a FastDataOutput object back into the cache.
     * You must not touch the object after this call.
     */
    public void release() {
        if (mBufferPos > 0) {
            throw new IllegalStateException("Lingering data, call flush() before releasing.");
        }

        mOut = null;
        mBufferPos = 0;
        mStringRefs.clear();

        if (mBufferCap == BUFFER_SIZE) {
            // Try to return to the cache.
            sOutCache.compareAndSet(null, this);
        }
    }

    /**
     * Re-initializes the object for the new output.
     */
    private void setOutput(@NonNull OutputStream out) {
        mOut = Objects.requireNonNull(out);
        mBufferPos = 0;
        mStringRefs.clear();
    }

    private void drain() throws IOException {
@@ -83,6 +129,7 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
    @Override
    public void close() throws IOException {
        mOut.close();
        release();
    }

    @Override