7 ms·
I'm doing similar, it's so much fun, and here are my takeaways: - Ignore socket.io, do pure binary websocket - Do not serialize JSON, or use msgpack or protob
by synthmeat 9y ago
I'm doing similar, it's so much fun, and here are my takeaways:
- Ignore socket.io, do pure binary websocket
- Do not serialize JSON, or use msgpack or protobuf - write your own protocol.
- Write tests for protocol, you need fast iteration. It's super easy to write tests for codec.
- Quadtrees are kinda lousy compared to r-trees.
- Measure everything with realistic load - i.e. I've found out that it's more costly to calculate world entity deltas to send to client, than to send everything in his view.
- Keep client updates under MTU payload. This is basically impossible with JSON.
- Mutability is the way to go for performance.
- Share code with backend and frontend, you'll need it for client prediction.
- Prefer fixed entity speeds.
- Don't log per-frame in production, journalctl will eat up your memory.
- Write game bots to test your load non-synthetically.
- Test on your VPS, you'll be surprised how underperforming CPUs are in most providers. Neighbours are probably serving some CRUD and are very likely not to be as noisy as you are.
Now, all this might not apply depending on exact gameplay mechanics you have, but it works for me. I have Node.js serving 200 clients and 10k entities with vision (can run at or from you) at 20 frames per second that keeps under 100MB RAM with no hiccups. I think I could use something like Golang for some more advanced physics though.
A question to all reading - I'm considering adding an option to mine Monero in my next game. It'd probably be a flip-switch between ads and mining right there on the home screen, with some intelligent throttle/thread decisions depending on the kind of device game is running on. I'd appreciate any feedback regarding the sentiment on that.
- gfysfm 9y ago>Write game bots to test your load non-synthetically. Can you expand a bit more on that? Cool tips, for sure. Personally I'd appreciate a flip-switch between ads and mining, as long as it defaulted to ads.
- synthmeat 9y agoIn my particular game, for core gameplay, I'm just sending the angle and whether the action button is down or up. So I just slapped together a Node.js script to spawn N clients that, according to some simple logic send that input to server. They don't even interpret what server sends back to them, because I'm testing the server-side with them. Bonus is that you can test your algos in extreme circumstances, like send all clients to particular spot on the map, so you can see how it performs with different distributions of locations. This was invaluable to almost all multiplayer games I did. Wrt mining/ads, I'm considering to default to mining if I detect ad-blocker, or you're on Chrome + Desktop PC (not laptops).
- gfysfm 9y ago> Wrt mining/ads, I'm considering to default to mining if I detect ad-blocker, or you're on Chrome + Desktop PC (not laptops). Do what you've gotta do to get paid for your work, but if I found out this was happening it would strongly discourage me from remaining on the website.
- synthmeat 9y agoThank you, that's great feedback and exactly what I'm after. Nag popup after every few sessions to turn on mining or whitelist the site in adblocker would be better compromise then?
- gfysfm 9y agoThat would work for me.
- zdkl 9y agoHonestly this would be a great use for attention grabbing full screen notification (gasp). "We're cool with adblock, but to continue on this site click here to enable mining, here for paid accounts, or just disable adblock and report inappropriate ads so we can forward that to our syndication."
- synthmeat 9y agoYeah, actually I think that'd be great place for full disclosure and help user get opportunity to make as informed decision as possible.
- moron4hire 9y ago"how dare they consume my compute resources to make money?" I mean, what the hell is internet advertising if it's not consuming your compute resources to make money?
- 9y ago
- user5994461 9y ago>>> A question to all reading - I'm considering adding an option to mine Monero in my next game. It'd probably be a flip-switch between ads and mining right there on the home screen, with some intelligent throttle/thread decisions depending on the kind of device game is running on. I'd appreciate any feedback regarding the sentiment on that. Mining => You WILL murder the battery of your users. You WILL cause overheating of the devices. You will also grind the browser to a halt on all hardware of moderate speed or already busy for reading a youtube video in the background. Personally. I'd consider that any website that start mining when opened should go right into an adblock list, if not blocked as malicious entirely.
- synthmeat 9y agoThis is the reason why I'm considering only enabling that feature on Chrome (because of WASM and battery API) and Desktop PC (because of the battery/heat issues). For experiment, I've turned on a miner in one tab of my brother's 7-year old modest PC setup. He went for several hours without noticing it, while doing blender rendering as well as somewhat intensive photoshoping.
- user5994461 9y agoJust because the user doesn't notice or doesn't understand what happens doesn't make it acceptable. Chrome is going toward more and more aggressive CPU throttling of tabs in the background. If mining becomes a thing, we're going to a world where background tabs will stop being rendered at all.
- synthmeat 9y ago> Just because the user doesn't notice or doesn't understand what happens doesn't make it acceptable. I did this on my brother, for data gathering. It'd most certainly not be implemented non-transparently in the end-product. > Chrome is going toward more and more aggressive CPU throttling of tabs in the background. That's why you mine during active game. The more people love it, the more they mine it. It can certainly be made mostly win-win scenario, which is why I aim on, again, transparently experimenting with it.
- CJefferson 9y agoAre you sure about no JSON? My experience is JSON is fairly small, and faster than anything else because it has browser support.
- synthmeat 9y agoFor my use case, replacing JSON with custom binary protocol, some old version being here [1], had savings of about 2 orders of magnitude in bandwidth and at least 1 order of magnitude improvements in server CPU usage. Some significant memory savings too. There's also space for more optimizations to be done, but I consider it viable enough for now. ArrayBuffer and DataView are fairly fast for my standards. [1] https://gist.github.com/synthmeat/d23595db732d366f658a1981e92429b1 https://gist.github.com/synthmeat/d23595db732d366f658a1981e9...
- deleted 9y ago[deleted]
- nullpilot 9y agoNot OP but yes, absolutely. JSON and MsgPack are schemaless, which means they put the schema, including object keys etc on the wire. On every transfer. The problem is less the client, you're right with that. The problem is that server bandwidth and CPU scale up really quickly if you try to do 30fps, no matter what method you use to keep state in sync. If you want any significant amount of players in a realtime game, this will be one of your first bottlenecks, probably before any encoding and decoding. For less realtime-y games, JSON and also socket.io can be perfectly adequate. Protobuf is just insanely slow to encode/decode client side. So that's out too if you want fast paced games. And for slower games it is not worth the effort.
- garkin 9y agoIt's not for client. It's for server and bandwidth.
- bartread 9y agoYou say "Ignore socket.io, do pure binary websocket" and that sort of makes sense to me, along with your advice about not using JSON, but what are you using to do "pure binary websocket"? Do you have any code samples, please? (Don't need to run or compile, just an example would be handy.) Also, can you post a link to your game, please? I'd like to give it a try.
- synthmeat 9y agoYou can find links to both (and then some) in my comments on this submission.
- KGIII 9y agoI'd suggest finding out, in the real world, if it is ads or mining that gets you the greater income. Then, you optimize for that. In either case, when you're having them doing the mining, I'd recommend full disclosure AND I'd recommend some explanatory text that goes into the details of what you're doing and why. Something like, "Click here to learn more about mining." That should do the trick. I'd just put said link below the quick blurb/switch/invite to use mining. If mining generates more income, then you may wish to offer some sort of in-game bonus for those who enable it. You'll have to figure out some way to ensure they really have it enabled, of course. Giving them a reward may entice more users to choose to do mining. Another post mentioned that this would be a battery killer. You responded that you'd only enable it for certain devices/browsers. If you want, you could probably enable it (as a choice) for all devices and browsers BUT I'd absolutely ensure that you made it very clear that doing so would mean a rapid depletion of stored energy on battery powered devices. The reason I'd suggest you do allow it is because many people only use mobile devices and, in some cases, will operate them while they are plugged in. For example, I'm typing this on a tablet that is plugged into an outlet. If mining makes you income, I'd be inclined to want to do mining for you - even while on a mobile device. It'd be even more tempting if there were an in-game reward for it. Sort of related: That might make an interesting funding option. Free games but mandatory mining on behalf of the creator. Obviously, full disclosure is required if one is concerned with ethics. Inside this idea, they might be able to get rewards directly related to how much they mine on the creator's behalf.
- synthmeat 9y agoResponding to all your suggestions would take too much time for me right now, but I can tell you that all are very on-point. Thanks. One interesting trivia though - for few undisclosed games I've checked the data, with following conclusion - they would've made order of magnitude less with mining than with ads. However, if you include currency trend for those periods, they would've made almost the same. :) I think this might be indication of a possible close-future tipping point in favour of this model. We'll see.
- cheapsteak 9y agoThere are so many msgpack and protobuff implantations on npm, does anyone have recommendations on which to use / what the tradeoffs are? https://npmcharts.com/compare/avsc,thrift,msgpack-lite,msgpack,msgpack-js,msgpack5,pbf,protobufjs https://npmcharts.com/compare/avsc,thrift,msgpack-lite,msgpa...
- FunnyLookinHat 9y ago>>> I'm doing similar, it's so much fun Yes, basically this. I think most of us solve the same sort of problems day in and day out with our jobs; it's unbelievably fun to be dropped into a totally new problem space and have that feeling of complete ignorance again.
- 11235813213455 9y agoagreed, or at least sock.js which is exactly websocket API with useful things like reconnect (it's used by webpack) but not socket.io!!
- XCSme 9y agoThose are some very good points, but I think some of them are wrong or do not apply for most uses cases. 1) "Do not serialize JSON, or use msgpack or protobuf - write your own protocol." - Why should you write your own protocol insead of protobuf? If your game has more than 10-20 types of messages/objects than it becomes very hard to implement your own binary encoding for each object. Plus with protobuf is easy to use and the packets generated are really smaller (most likely smaller than your own protocol). 2) "Measure everything with realistic load - i.e. I've found out that it's more costly to calculate world entity deltas to send to client, than to send everything in his view." - Profiling is something that you should always do, with both synthetic and real loads. In your case, my guess is that your diffing code was inefficient or that the load was so small that both computing the delta and sending the message were almost instant, so comparing them would give inaccurate results. 3) "Prefer fixed entity speeds." - I think this is a game design decision and you shouldn't limit your game to this if you don't have too. Also, I don't think there's any issue with entities being able to have a different speed each tick. And, a question. What VPS are you using? Do you recommend any specific VPS for hosting Node.js game servers?
- synthmeat 9y ago1) Demonstrably not so, in my case. Devising and implementing a protocol flexible enough for me was, along with test-driven implementation of that particular aspect, a joy and more performant solution than any other out of the box. Yes, I've tested against msgpack/protobuf (and I use protobuf in production on other projects) and found it to be less optimal, for both implementation (you're never as flexible as with blank board) and runtime resource usage, across board. 2) Sure, I might go the way of the delta one of these days - it does still smell like good design. That's why I was underwhelmed to see it underperform first time around. 3) Yeah, design and implementation are never separate. Neither is content and presentation. :) DigitalOcean works for me now. Wouldn't mind slightly better CPUs, as even High Compute droplets are not all they're cracked to be.
- XCSme 9y agoJust curious about your own binary protocol. If your object has an int32 value, but the value could actually be represented with only 12 bits, do you send the entire int value (32 bits) or only the 12 bits needed to reconstruct the number? I also used DO for a low-tickrate game (2ticks/second), but it doesn't seem like the servers are able to handle multiple game servers running at 60FPS. If you were to implement the game again, would you rethink your networking so you don't have 2TB of data transfer for only 200 players?
- singhrac 9y agoNice list! These are pretty useful. I found the experience of using protobuf for frontend <-> Go communication to be good, since it forced me to do the work of 'writing my own protocol' but without all the encoding/decoding. There was some issue with naming in protobuf and Go's conventions though. To add my 2 cents: I think mining Monero is actually very reasonable (you seem to have thought through the impact on your users), and you've nailed the most important thing: making it opt-in. I'm fine contributing CPU cycles when playing a game, as long as it's in the foreground and I agreed to it.
- dxhdr 9y ago> I have Node.js serving 200 clients and 10k entities with vision (can run at or from you) at 20 frames per second that keeps under 100MB RAM with no hiccups. What's in the 100MB? Doing some napkin math, take 10k hypothetical game objects that each have as state: pos, vel, acc, rot, ang vel, ang acc, name (32 chars), color, health, mana, armor, level, type, energy, kills, timers, inventory (256 bytes)... etc etc, all together comes in at around 512 bytes each. Even if that's double buffered it's still just 10MB. Curious where all that memory is going!
- merb 9y agogame devs... do not understand the web. well I'm not sure how it could only be 100MB considering that our Angular2/4 Web Application (a big enterprise CRM/ERP) uses 400 MB (no joke).
- synthmeat 9y agoTo be perfectly honest, I haven't profiled and have been fairly cavalier about it. Seemed good, and most importantly, stable enough - it's not bottleneck. Like you've noticed, it definitely has low-hanging fruits to pick up there, yeah.
- tokenizerrr 9y agoPlease tell me what your game is. Even considering abusing my hardware for mining is enough reason for me to avoid anything you create.
- FilterSweep 9y ago> I've found out that it's more costly to calculate world entity deltas to send to client, than to send everything in his view. If you don't mind me asking, Why is this the case? I would have assumed world entity deltas is probably how I'd approach things first...