Производительность NodeJS

Предыстория

Я работаю с протоколом Minecraft. И когда возник вопрос о производительности, я достаточно обиделся, потому, что скорость загрузки чанков была очень низкая, я перебирал территорию размером 16777216 блоков, тоесть 256x256x256, и просто устанавливал случайных блок, и это происходило довольно медленно, на создание полностью заполненного случайными блоками чанка, уходило около 3 - 4 секунд. В то время, как скорость загрузки чанков в одиночной игре достигало на глаз около 8 - 10 чанков в секунду, а там используются довольно сложные алгоритмы генерации мира.

Текущая реализация

На данный момент у меня есть пара функций, кодирующая и декодирующая пакет протокола. Выглядит это так

class XPacket extends Packet {
  encode(){ /**/ }
  decode(){ /**/ }
}

Эти методы выполняют в себе цепочку вызовов методов Packet, таким образом кодируя и декодируя данные из/в поля(ей) XPacket.

Packet внутри себя использует специальный буфер, по сути это обычный Buffer, просто расширенный специальными методами:

writeByte(...value: number[]): this { /**/ } 
writeUByte(...value: number[]): this { /**/ }
writeInt(...value: number[]): this { /**/ }
writeUInt(...value: number[]): this { /**/ }

Так же он содержит более сложные методы и аналогичные им для чтения, все они переопределяют буфер с новым значением.

Вот к примеру один из методов:

writeVarint(value: varint): this {
  this.buffer = Buffer.concat([data, new Varint().write(value)])
  return this
}

Varint.ts

export class Varint extends DataType<number> {

  private readonly SEGMENT_BITS = 0x7f
  private readonly CONTINUE_BIT = 0x80
  protected readonly maxLength: number = 32

  read(data: Buffer): [result: number, offset: number] {
    let result = 0
    let offset = 0
    let position = 0
    let currentByte: number

    while (true) {
      currentByte = data.readInt8(offset)
      offset++
      result |= (currentByte & this.SEGMENT_BITS) << position
      if ((currentByte & this.CONTINUE_BIT) === 0) break
      position += 7
      if (position >= this.maxLength)
        throw new Error('Varint is too big')
    }

    return [result, offset]
  }

  write(value: number): Buffer {
    let buf = Buffer.alloc(0)
    while (true) {
      if ((value & ~this.SEGMENT_BITS) == 0) {
        buf = Buffer.concat([buf, Buffer.from([value])])
        break
      }
      buf = Buffer.concat([
        buf,
        Buffer.from([(value & this.SEGMENT_BITS) | this.CONTINUE_BIT])
      ])
      value >>>= 7
    }
    return buf
  }

}

И также один из пакетов к примеру:

export class PlayerPositionAndLookClientPacket extends Packet {

  static type: number = 0x38
  static state: number = PacketState.Play

  // Не обращайте внимания на типы double и т.д. это просто алиасы к              
  // типам number и bigint

  x: double = 0
  y: double = 0
  z: double = 0
  yaw: float = 0
  pitch: float = 0
  flags: byte = 0
  teleportId: varint = 0
  dismount: boolean = false

  constructor() {
    super(PlayerPositionAndLookClientPacket.state, PlayerPositionAndLookClientPacket.type)
  }

  encode(): void {
    this
      .writeDouble(this.x, this.y, this.z)
      .writeFloat(this.yaw, this.pitch)
      .writeByte(this.flags)
      .writeVarint(this.teleportId)
      .writeBoolean(this.dismount)
  }

  decode(): void {
    this.x = this.readDouble()
    this.y = this.readDouble()
    this.z = this.readDouble()
    this.yaw = this.readFloat()
    this.pitch = this.readFloat()
    this.flags = this.readByte()
    this.teleportId = this.readVarint()
    this.dismount = this.readBoolean()
  }

}

Далее я просто склеиваю методом длину пакета с его данными и отправляю клиенту через встроенный пакет net

get data(): Buffer {
  return Buffer.concat([
    new Varint().write(this.buffer.length + 1),
    new Varint().write(this.type),
    this.buffer,
  ])
}

C++ ?

Может быть перенести этот специальный буфер в аддон c++? Но тут есть проблема, я не знаю как, т.к. почти не знаю c++. Но это меньшая из проблем на данный момент.

GPU.js

Нашёл я библиотечку GPU.js, вроде бы как она умеет делать вычисления на GPU. Есть ли в ней смысл. Также она вряд ли запустится на Linux сервере.

NodeJS не для этих целей

Возможно NodeJS для того, что я пытаюсь сделать и вовсе не подходит?

Вообщем я хочу получить ответ, о том, может ли NodeJS выполнять описанное выше быстрее, если да то как?


Ответы (0 шт):