feat(core): int64 write optimization

this optimization gives about 10x performance boost on systems that support BigInt, and about 2x on those that don't
This commit is contained in:
teidesu 2021-05-21 22:15:25 +03:00
parent c3fce178b6
commit ee369a1c83
2 changed files with 26 additions and 12 deletions

View file

@ -2,9 +2,11 @@ import bigInt, { BigInteger } from 'big-integer'
import { inflate } from 'pako'
import { typedArrayToBuffer } from '../buffer-utils'
import readerMap, { ITlBinaryReader } from '@mtcute/tl/binary/reader'
import { ulongToLong } from '../bigint-utils'
import { bufferToBigInt, longToUlong, ulongToLong } from '../bigint-utils'
import { tl } from '@mtcute/tl'
const isNativeBigIntAvailable = typeof BigInt !== 'undefined' && 'readBigInt64LE' in Buffer.prototype
export class BinaryReader implements ITlBinaryReader {
data: Buffer
pos = 0
@ -33,12 +35,19 @@ export class BinaryReader implements ITlBinaryReader {
}
long(unsigned = false): BigInteger {
const lo = this.data.readUInt32LE(this.pos)
const hi = this.data.readUInt32LE(this.pos + 4)
let big: BigInteger
if (isNativeBigIntAvailable) {
const val = this.data.readBigInt64LE(this.pos)
big = bigInt(val)
if (unsigned) big = longToUlong(big)
} else {
big = bufferToBigInt(this.data, this.pos, 8, true)
if (!unsigned) big = ulongToLong(big)
}
this.pos += 8
let big = bigInt(hi).shiftLeft(32).or(lo)
if (!unsigned) big = ulongToLong(big)
return big
}

View file

@ -1,5 +1,5 @@
import { BigInteger } from 'big-integer'
import { longToUlong } from '../bigint-utils'
import { longToUlong, ulongToLong, writeBigInt } from '../bigint-utils'
import writerMap, {
ITlBinaryWriter,
TlBinaryWriterFunction,
@ -11,6 +11,8 @@ type SerializableObject = {
[key: string]: any
}
const isNativeBigIntAvailable = typeof BigInt !== 'undefined' && 'writeBigInt64LE' in Buffer.prototype
export class SerializationCounter implements ITlBinaryWriter {
count = 0
_objectMap = writerMap
@ -145,12 +147,15 @@ export class BinaryWriter implements ITlBinaryWriter {
}
long(val: BigInteger): void {
val = longToUlong(val)
const lo = val.and(0xffffffff).toJSNumber()
const hi = val.shiftRight(32).and(0xffffffff).toJSNumber()
this.buffer.writeUInt32LE(lo, this.pos)
this.buffer.writeUInt32LE(hi, this.pos + 4)
if (isNativeBigIntAvailable) {
val = ulongToLong(val)
// if BigInt is supported, `BigInteger` is just a
// wrapper over native BigInt, stored in `value`
this.buffer.writeBigInt64LE((val as any).value, this.pos)
} else {
val = longToUlong(val)
writeBigInt(this.buffer, val, 8, this.pos, true)
}
this.pos += 8
}