Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js echo server #96

Closed
GavinRay97 opened this issue Nov 20, 2022 · 5 comments
Closed

Node.js echo server #96

GavinRay97 opened this issue Nov 20, 2022 · 5 comments
Labels
Done Done

Comments

@GavinRay97
Copy link
Contributor

I wrote this for you, I had forgot you asked about it.
Here is one which takes the same flags as yours, I did not implement streaming because I do not understand much about streaming.

// flags.ts
export const flags = {
    SHOW_STATISTICS_INTERVAL: Number(process.env.SHOW_STATISTICS_INTERVAL || 1),
    CLIENT_MODE: "ping-pong",
    CLIENT_CONNECTION_NUM: Number(process.env.CLIENT_CONNECTION_NUM || 100),
    IP: process.env.IP || "127.0.0.1",
    PORT: Number(process.env.PORT || 9527),
    BUF_SIZE: Number(process.env.BUF_SIZE || 512),
    VCPU_NUM: Number(process.env.VCPU_NUM || 1), // TODO: Node is single-threaded, so this is not useful
}

You can run it with yarn dev:server and yarn dev:client after doing yarn install for dependencies 👍

Code_-_Insiders_yeqjIOQJUA.mp4
@beef9999
Copy link
Collaborator

beef9999 commented Nov 20, 2022

It's QPS is 192K, throughput is 750Mb/s. I'd like to update it into my data sheet.

I'm not an expert here, please correct me if I'm wrong. So typescript is the project name and nodejs is the language? And what is its concurrency modle ? Coroutine ? Async callback ?

@GavinRay97
Copy link
Contributor Author

Sure, Node.js is a runtime which uses Chrome V8 engine to allow JavaScript to execute on server.
It provides API's for interacting with network/filesystem etc.

TypeScript is a type-system for JavaScript -- it gets removed at runtime, and compiled into JavaScript.

TypeScript code (with types) --> transpile --> JavaScript code --> Node.js runs JS code --> executes on V8 C++ engine

I mostly use TypeScript as it makes the code easier to read/maintain,
It has no performance impact and disappears after compiling👍


And what is its concurrency modle ? Coroutine ? Async callback ?

It is async callback, the low-level net package in Node.js has event-listeners which fire callback functions when operations happen like data received, socket opened, connection acquired etc.

The server code is tiny, it just echos back out what it received:

function server() {
    const server = net.createServer()
    server.on("connection", (socket) => {
        socket.on("data", (data) => {
            console.count("server received ops")
            socket.write(data)
        })
    })
    server.listen(flags.PORT, flags.IP, () => {
        console.log(`server listening on ${flags.IP}:${flags.PORT}`)
    })
}

And then the callbacks are registered when the ClientSocket class is created here:
(I made some notes in comments below, for instance right now a static buffer is allocated, I'm not sure if this is supposed to be re-allocated every time)

class ClientSocket {
    // Should this be re-allocated every operation?
    // If so, this needs to be removed, see <---- down below
    private static buf: Buffer = Buffer.alloc(flags.BUF_SIZE)

    constructor() {
        this.socket = new net.Socket()
        this.sentOpsTotal = 0
        this.receivedOpsTotal = 0
        this.sentBytesTotal = 0
        this.receivedBytesTotal = 0
        this.lastOpStartTime = performance.timeOrigin
    }

	// Handlers for what should happen when data is received are registered as callbacks here
    async connect() {
        return new Promise((resolve, reject) => {
            this.socket.connect(flags.PORT, flags.IP, () => {
                resolve(this)
            })
            this.socket.on("data", (data) => {
                this.receivedOpsTotal++
                this.receivedBytesTotal += data.length
                // this.socket.write(Buffer.alloc(flags.BUF_SIZE))   <------
                this.socket.write(ClientSocket.buf)
                this.sentOpsTotal++
                this.sentBytesTotal += data.length
                this.lastOpStartTime = performance.now()
            })
            this.socket.on("error", (err) => {
                reject(err)
            })
        })
    }
}

@beef9999
Copy link
Collaborator

I was using my own client to test against your server, in order to reduce variables.

@GavinRay97
Copy link
Contributor Author

Oh LOL, that makes a more sense doesn't it?

You may want to try commenting out this line
console.count("server received ops")

And see if it makes any difference btw

@beef9999 beef9999 added the Done Done label Nov 20, 2022
@beef9999
Copy link
Collaborator

Closed for #97

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Done Done
Projects
None yet
Development

No branches or pull requests

2 participants