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:
parent
c3fce178b6
commit
ee369a1c83
2 changed files with 26 additions and 12 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
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)
|
||||
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)
|
||||
writeBigInt(this.buffer, val, 8, this.pos, true)
|
||||
}
|
||||
|
||||
this.pos += 8
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue