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 { inflate } from 'pako'
|
||||||
import { typedArrayToBuffer } from '../buffer-utils'
|
import { typedArrayToBuffer } from '../buffer-utils'
|
||||||
import readerMap, { ITlBinaryReader } from '@mtcute/tl/binary/reader'
|
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'
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
const isNativeBigIntAvailable = typeof BigInt !== 'undefined' && 'readBigInt64LE' in Buffer.prototype
|
||||||
|
|
||||||
export class BinaryReader implements ITlBinaryReader {
|
export class BinaryReader implements ITlBinaryReader {
|
||||||
data: Buffer
|
data: Buffer
|
||||||
pos = 0
|
pos = 0
|
||||||
|
@ -33,12 +35,19 @@ export class BinaryReader implements ITlBinaryReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
long(unsigned = false): BigInteger {
|
long(unsigned = false): BigInteger {
|
||||||
const lo = this.data.readUInt32LE(this.pos)
|
let big: BigInteger
|
||||||
const hi = this.data.readUInt32LE(this.pos + 4)
|
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
|
this.pos += 8
|
||||||
|
|
||||||
let big = bigInt(hi).shiftLeft(32).or(lo)
|
|
||||||
if (!unsigned) big = ulongToLong(big)
|
|
||||||
return big
|
return big
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BigInteger } from 'big-integer'
|
import { BigInteger } from 'big-integer'
|
||||||
import { longToUlong } from '../bigint-utils'
|
import { longToUlong, ulongToLong, writeBigInt } from '../bigint-utils'
|
||||||
import writerMap, {
|
import writerMap, {
|
||||||
ITlBinaryWriter,
|
ITlBinaryWriter,
|
||||||
TlBinaryWriterFunction,
|
TlBinaryWriterFunction,
|
||||||
|
@ -11,6 +11,8 @@ type SerializableObject = {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isNativeBigIntAvailable = typeof BigInt !== 'undefined' && 'writeBigInt64LE' in Buffer.prototype
|
||||||
|
|
||||||
export class SerializationCounter implements ITlBinaryWriter {
|
export class SerializationCounter implements ITlBinaryWriter {
|
||||||
count = 0
|
count = 0
|
||||||
_objectMap = writerMap
|
_objectMap = writerMap
|
||||||
|
@ -145,12 +147,15 @@ export class BinaryWriter implements ITlBinaryWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
long(val: BigInteger): void {
|
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)
|
val = longToUlong(val)
|
||||||
const lo = val.and(0xffffffff).toJSNumber()
|
writeBigInt(this.buffer, val, 8, this.pos, true)
|
||||||
const hi = val.shiftRight(32).and(0xffffffff).toJSNumber()
|
}
|
||||||
|
|
||||||
this.buffer.writeUInt32LE(lo, this.pos)
|
|
||||||
this.buffer.writeUInt32LE(hi, this.pos + 4)
|
|
||||||
|
|
||||||
this.pos += 8
|
this.pos += 8
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue