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

Unverified Commit ff708def authored by Simon Chan's avatar Simon Chan
Browse files

refactor(struct): 10% performance improvement

parent fa8d251b
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ const state = makeAutoObservable({
    logcat: undefined as Logcat | undefined,
    running: false,
    buffer: [] as LogRow[],
    flushRequested: false,
    list: [] as LogRow[],
    count: 0,
    stream: undefined as ReadableStream<LogMessage> | undefined,
@@ -73,21 +74,20 @@ const state = makeAutoObservable({
                new WritableStream({
                    write: (chunk) => {
                        this.buffer.push(chunk);
                        if (!this.flushRequested) {
                            this.flushRequested = true;
                            requestAnimationFrame(this.flush);
                        }
                    },
                }),
                { signal: this.stopSignal.signal }
            )
            .catch(() => { });
        this.flush();
    },
    flush() {
        if (this.buffer.length) {
        this.list.push(...this.buffer);
        this.buffer = [];
        }
        if (this.running) {
            requestAnimationFrame(this.flush);
        }
        this.flushRequested = false;
    },
    stop() {
        this.running = false;
+2 −1
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ export const AdbSyncLstatResponse =
            get permission() { return this.mode & 0b00001111_11111111; },
        })
        .postDeserialize((object) => {
            if (object.mode === 0 &&
            if (
                object.mode === 0 &&
                object.size === 0 &&
                object.mtime === 0
            ) {
+40 −32
Original line number Diff line number Diff line
@@ -26,38 +26,25 @@ export class BufferedStream {
        this.reader = stream.getReader();
    }

    /**
     *
     * @param length
     * @returns
     */
    public async read(length: number): Promise<Uint8Array> {
    private async readSource() {
        const { done, value } = await this.reader.read();
        if (done) {
            throw new BufferedStreamEndedError();
        }
        return value;
    }

    private async readAsync(length: number, initial?: Uint8Array) {
        let result: Uint8Array;
        let index: number;

        if (this.buffered) {
            let array = this.buffered;
            const offset = this.bufferedOffset;
            if (this.bufferedLength > length) {
                // PERF: `subarray` is slow
                // don't use it until absolutely necessary
                this.bufferedOffset += length;
                this.bufferedLength -= length;
                return array.subarray(offset, offset + length);
            }

            this.buffered = undefined;
            array = array.subarray(offset);
        if (initial) {
            result = new Uint8Array(length);
            result.set(array);
            index = this.bufferedLength;
            length -= this.bufferedLength;
            result.set(initial);
            index = initial.byteLength;
            length -= initial.byteLength;
        } else {
            const { done, value: array } = await this.reader.read();
            if (done) {
                throw new BufferedStreamEndedError();
            }

            const array = await this.readSource();
            if (array.byteLength === length) {
                return array;
            }
@@ -76,11 +63,7 @@ export class BufferedStream {
        }

        while (length > 0) {
            const { done, value: array } = await this.reader.read();
            if (done) {
                throw new BufferedStreamEndedError();
            }

            const array = await this.readSource();
            if (array.byteLength === length) {
                result.set(array, index);
                return result;
@@ -102,6 +85,31 @@ export class BufferedStream {
        return result;
    }

    /**
     *
     * @param length
     * @returns
     */
    public read(length: number): Uint8Array | Promise<Uint8Array> {
        // PERF: Add a synchronous path for reading from internal buffer
        if (this.buffered) {
            const array = this.buffered;
            const offset = this.bufferedOffset;
            if (this.bufferedLength > length) {
                // PERF: `subarray` is slow
                // don't use it until absolutely necessary
                this.bufferedOffset += length;
                this.bufferedLength -= length;
                return array.subarray(offset, offset + length);
            }

            this.buffered = undefined;
            return this.readAsync(length, array.subarray(offset));
        }

        return this.readAsync(length);
    }

    /**
     * Return a readable stream with unconsumed data (if any) and
     * all data from the wrapped stream.
+5 −7
Original line number Diff line number Diff line
@@ -645,13 +645,11 @@ struct.field(

### Relationship between types

A `Struct` is a map between keys and `StructFieldDefinition`s.

A `StructValue` is a map between keys and `StructFieldValue`s.

A `Struct` can create (deserialize) multiple `StructValue`s with same field definitions.

Each time a `Struct` deserialize, each `StructFieldDefinition` in it creates exactly one `StructFieldValue` to be put into the `StructValue`.
* `StructFieldValue`: Contains value of a field, with optional metadata and accessor methods.
* `StructFieldDefinition`: Definition of a field, can deserialize `StructFieldValue`s from a stream or create them from exist values.
* `StructValue`: A map between field names and `StructFieldValue`s.
* `Struct`: Definiton of a struct, a map between field names and `StructFieldDefintion`s. May contain extra metadata.
* Result of `Struct#deserialize()`: A map between field names and results of `StructFieldValue#get()`.

### `StructFieldDefinition`

+5 −0
Original line number Diff line number Diff line
@@ -20,6 +20,11 @@ export abstract class StructFieldValue<
    /** Gets the associated `Struct` instance */
    public readonly struct: StructValue;

    public get hasCustomAccessors(): boolean {
        return this.get !== StructFieldValue.prototype.get ||
            this.set !== StructFieldValue.prototype.set;
    }

    protected value: TDefinition['TValue'];

    public constructor(
Loading