Spyke

Replies

Comment on

Is Java not good?

Java has never had a good reputation, lol. But seriously, by every possible measure it has superior competitors:

  • Compared to dynamically-typed or interpreted languages, Java performs better, but it requires a frankly ludicrous amount of extra typing.
  • Compared to AOT compiled languages, it performs poorly except in purely numeric code where it has the advantage of portable -march=native. Other code almost never can be optimized due to the mandatory memory overhead.
  • Compared to any language, Java lacks support for most forms of ownership that people actually intend, and makes them very difficult to implement them yourself. Of the 3 ownership policies it does support, GC is useless (solely a crutch for programmers who are too lazy or too incompetent to specify what they want), Weak is sabotaged by its relation to GC, and Unique is limited to local contexts and does not compose. (I don't consider Phantom and Soft to actually be distinct ownership types, just hooks for GC ownership)
  • In its own niche (static types + JIT + GC), C# is strictly superior as a language, due to supporting value types (although not all C# bothers to use them, at least you have the option of performance). The only disadvantage of C# is in its ecosystem: historically there were a lot of Windows-only libraries; also there were people specifically depending on Java's ecosystem.

Writing your new app in Java is still better than using Electron or something though.

Comment on

*Permanently Deleted*

Stop reinventing the wheel.

Major translation systems like gettext (especially the GNU variant) have decades of tooling built up for "merging" and all sorts of other operations.

Even if you don't want to use their binary format at runtime, their tooling is still worth it.

godot

Comment on

Create non-game apps with Godot Engine

There's tends to be one major difference between games and non-game applications, so toolkits designed for one are often quite unsuitable for the other.

A game generally performs logic to paint the whole window, every frame, with at most some framerate-limiting in "paused" states. This burns power but is steady and often tries hard to reduce latency.

An application generally tries to paint as little of the window as possible, as rarely as possible. Reducing video bandwidth means using a lot less power, but can involve variable loads so sometimes latency gets pushed down to "it would be nice".

Notably, the implications of the 4-way choice between {tearing, vsync, double-buffer, triple-buffer} looks very different between those two - and so does the question of "how do we use the GPU"?

Comment on

Is it really a breaking change if a method changes output after an update?

As a practical matter it is likely to break somebody's unit tests.

If there's an alternative approach that you want people to use in their unit tests, go ahead and break it. If there isn't, but you're only doing such breakage rarely and it's reasonable for their unit tests to be updated in a way that works with both versions of your library, do it cautiously. Otherwise, only do it if you own the universe and you hate future debuggers.

git

Comment on

Why Git is hard

Reply in thread

I've only ever seen two parts of git that could arguably be called unintuitive, and they both got fixes:

  • git reset seems to do 2 unrelated things for some people. Nowadays git restore exists.
  • the inconsistent difference between a..b and a...b commit ranges in various commands. This is admittedly obscure enough that I would have to look up the manual half the time anyway.
  • I suppose we could call the fact that man git foo didn't used to work unintuitive I guess.

The tooling to integrate git submodule into normal tree operations could be improved though. But nowadays there's git subtree for all the people who want to do it wrong but easily.


The only reason people complain so much about git is that it's the only VCS that's actually widely used anymore. All the others have worse problems, but there's nobody left to complain about them.

gamedev

Comment on

Resources on Multiplayer Server Development using Godot 4.0

You've clearly thought about the problem, so the solutions should be relatively obvious. Some less obvious ones:

  • It is impossible to make TCP reliable no matter how hard you try, because anybody can inject an RST flag at any time and cut off your connections (this isn't theoretical, it's actually quite common for long-lived gaming connections). That leaves UDP, for which there are several reliability layers, but most of them are not battle-tested - remember, TCP is most notable for congestion-control! HTTP3 is probably the only viable choice at scale, but beware that many implementations are very bad (e.g. not even supporting recvmmsg/sendmmsg which are critical for performance unlike with TCP; note the extra m)
  • If you don't encrypt all your packets, you will have random middleware mess with their data. Think at least a little about key rotation.
  • To avoid application-centric DoS, make sure the client always does "more" than the server; this extends to e.g. packet sizes.
  • Prefer to ultimately define things in data, not code (e.g. network packet layouts). Don't be afraid to write several bespoke code-generators; many real-world serialization formats in particular have unacceptable tradeoffs. Make sure the core code doesn't care about the details (e.g. make every packet physically variable-length even if logically it is always fixed-length; you can also normalize zero-padding at this level for future compatibility. I advise against delta-compression at this level because that's extra processing you don't need).
  • Make sure the client only has to connect to a single server. If you have multiple servers internally, have a thin bouncer/proxy that forwards packets appropriately. This also has benefits for the inevitable DDoS attacks.
  • Latency is a bitch and has far-ranging effects, though this is highly dependent on not just genre but also UI. For example "hold down a key to move continuously through the world" is problematic whereas "click to move to a location" is not.
  • Beware quadratic complexity, e.g. if every player must send a location update to every player.
  • Think not only about the database, but how to back up the database and how to roll back in case of catastrophe or exploit. An append-only flat file has a lot going for it; only periodic repacking is needed and you can keep the old version for a while with a guarantee that it'll replay to identical state to the initial version of the new file. Of course, the best state is no state at all. You will need to consider the notion of "transaction" at many levels, including scripting (you must give me 20 bear asses for me to give), trading between players, etc.
  • You will have abuse in chat. You will also have cybersex. It's possible to deal with this in a privacy-preserving way by merely signing chat, not logging it, so the player can present evidence only if they wish, but there are a lot of concerns about e.g. replays, selective message subsets, etc.
  • There will be bots, especially if the official client isn't good enough.
  • It's $CURRENTYEAR; write code for IPv6 exclusively. There are sockopts for transparently handling legacy IPv4 clients.
  • Client IP address is private information. It is also the only way to deal with certain kinds of abuse. Sometimes, you just have to block all of Poland.
  • Note that routing in parts of the world is really bad. Sometimes setting up your own dedicated connection chain between datacenters can improve performance by orders of magnitude, rather than letting clients use whatever their ISP says. If nesting proxies be sure to correctly validate IPs.
  • Life is simpler if internal stuff listens on a separate port than external stuff, but still verify your peer. IP whitelisting is useless except for localhost (which, mind, is all of 127.0.0.0/8 for IPv4 - about the only time IPv4 is actually useful rather than a mere mirage).

Comment on

There Is No Thread

Write-up is highly Windows-centric (though not irrelevant elsewhere).

One thing that is regretfully ignored in discussions of async, tasks, green threads, etc. is that there is no support/consideration for native (reliable/efficient) thread-local variables. If you're lucky you'll get a warning about "don't use them".

Comment on

Console Logs : Hello from the other side

Reply in thread

Even logging can sometimes be enough to hide the heisgenbug.

Logging to a file descriptor can sometimes be avoided by logging to memory (which for crash-safety includes the possibility of an mmap'ed file, since the kernel will just take care of them as long as the whole system doesn't go down). But logging from every thread to a single section of memory can also be problematic (even without mutexes, atomics can be expensive and certainly have side-effects) - sometimes you need a separate per-thread log, and combine in the log-reader tool.

Comment on

How feasible is a browser that uses something like Lua, Python or Ruby as its scripting language instead of JS? Also, how stupid is this idea (ignoring any "incompatibility with JS pages" situations)?

There's no point in replacing JS with another dynamically-typed language. JS has received a lot of attempts at depessimization. If you're going to replace it, it would have to be a language with real types (but reflection is still viable as a strictly-superior alternative to dynamic types)

python

Comment on

CLI tools hidden in the Python standard library

It's worth noting that the http.server module is based on socketserver.BaseServer.serve_forever, which is a atrocious.

It uses a busy loop with a delay, so it both burns CPU and is unresponsive.

(The fact that Python has had broken signal handling since 3.5 also hurts - EINTR should never be ignored from blocking calls)

Comment on

Borrow Checker

Reply in thread

What you are missing, of course, is the Rc<Refcell<T>> that you have to stick everywhere to make a nontrivial Rust program. It's like monads in Haskell, parentheses in lisp, verbosity in Java, or warnings in C - they're the magic words you have to incant correctly to make things work in their weird paradigms.

Comment on

[Help] what's one of the easier ways to make a window on linux using x11 and nasm assembly?

1, Don't target X11 specifically these days. Yes a lot of people still use it or at least support it in a backward-compatible manner, but Wayland is only increasing.

2, Don't fear the use of libraries. SDL and GTK, being C-based, should both be feasible from assembly; at most you might want to build a C program that dumps constants (if -dM doesn't suffice) and struct offsets (if you don't want to hard-code them).

linux

Comment on

Linux Terminal Emulators Have The Potential Of Being Much Faster

Speed is far from the only thing that matters in terminal emulators though. Correctness is critical.

The only terminals in which I have any confidence of correctness are xterm and pangoterm. And I suppose technically the BEL-for-ST extension is incorrect even there, but we have to live with that and a workaround is available.

A lot of terminal emulators end up hard-coding a handful of common sequences, and fail to correctly ignore sequences they don't implement. And worse, many go on to implement sequences that cannot be correctly handled.

One simple example that usually fails: \e!!F. More nasty, however, are the ones that ignore intermediaries and execute some unrelated command instead.

I can't be bothered to pick apart specific terminals anymore. Most don't even know what an IR is.

Comment on

Is Java not good?

Reply in thread

I would say that strings are one of the least inefficient things in the JVM. Yes, you pay double cost for ASCII, but the memory is contiguous unlike Object-heavy code where you have to pay double size cost and an indirection. Also, slicing is "free" unlike many other languages (though make sure you copy if the parent is going to die).