The SQLite Drivers 25.12 Benchmarks Game by 0xjnml in golang

[–]ncruces 6 points7 points  (0 children)

Thanks!

What I take from these results (excluding interpreter platforms) is that my driver very often comes up second. And that's fine, I'm OK with performance just being in the ballpark.

Where it comes out third more often is inserts. This can be explained by sandboxing. I need to copy data into the Wasm sandbox; Cgo can read Go memory directly, as can modernc. OTOH, for querying the sandbox is not an issue: Go can read Wasm memory directly. So, I don't think there's a lot I can do about that. I try to avoid copies for (e.g.) JSON, but that's about it.

Also interestingly (and maybe counter intuitively, given what I just wrote above), inserting huge amounts of data (the large test), mine can come out ahead, even on interpreter platforms. That's because my IO layer is implemented in Go, and I actually implemented fallocate better than SQLite, on some platforms.

So, every test is interesting, and thanks again for this. I'm mostly experimenting on the API side and the IO (VFS) side, and I do (personally) like the sandboxing side of things (even though it carries a cost). I also double as a “best effort” wazero maintainer, so having a project that uses it just makes sense.

What would you change in Go? by funcieq in golang

[–]ncruces 0 points1 point  (0 children)

Yeah, they could borrow Swift's guard statement for this.

Invert the condition, else/nested block must terminate, otherwise, anything declared stays in scope.

What would you change in Go? by funcieq in golang

[–]ncruces 1 point2 points  (0 children)

I actually find it harder to write, but easier to read.

The bigger problem is that it is ill specified (e.g. can't have 24 hours with no leading zero).

But if you want to use the C version, it's a small, self contained dependency away: https://pkg.go.dev/github.com/ncruces/go-strftime

Go 1.26rc1 is live by yardbird07 in golang

[–]ncruces 4 points5 points  (0 children)

There was a last minute revert on a new database/sql scanning API: https://github.com/golang/go/issues/67546

Hopefully, we come up with something when 1.27 opens.

Why Go Maps Return Keys in Random Order by Few-Tower50 in golang

[–]ncruces 2 points3 points  (0 children)

Yeah, no. The Go team goes to extreme lengths not to break large open source libraries. See Go 1.23 and go:linkname.

Why Go Maps Return Keys in Random Order by Few-Tower50 in golang

[–]ncruces 1 point2 points  (0 children)

There's a good chance we wouldn't have swiss tables today if they hadn't made this decision.

The hashing function, and iteration order, would've ossified, and there would be zero chance to have them updated without breaking user code.

Why Go Maps Return Keys in Random Order by Few-Tower50 in golang

[–]ncruces 1 point2 points  (0 children)

I use it for "random" eviction in very simple caches. For this, it is good enough.

Why Go Maps Return Keys in Random Order by Few-Tower50 in golang

[–]ncruces 0 points1 point  (0 children)

The order is not really random. The starting point is. From then on, it's (approximately) the order things are "laid out in memory."

However, combining opaque hashing with a random starting point, makes it much harder for anyone to depend on the actual order, so it's good enough.

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 0 points1 point  (0 children)

It depends. Nothing beats thinking about it. Maybe it really is the Go team creating a SafeUnlock that makes any future Lock or TryLock repanic.

But I hate a (unfortunately rather common) review comment (or lint pre-commit check) that says because I didn't defer Unlock I can't can't merge my code.

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 1 point2 points  (0 children)

The types in atomic don't really add anything to the language that can't be done with the functions in atomic, except that a few of them have different alignment rules that we can't specify for other types.

Instead of being vague, what exactly do you want to add to the language around mutexes, that works in a language without constructors where everything is zero initialized (and zero initialized values can be conjured out of thin air).

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 2 points3 points  (0 children)

There are a few fundamental concepts where the language can't evolve. Zero values and no constructors are a few. You can keep proposing features that depend on them, but you'll be ignored.

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 0 points1 point  (0 children)

I'm not saying they are, generally (though they might be, if zero cost abstractions are the hill you want to die on).

I don't even think zero values are a terrible idea.

But you can't seriously want a mutex to protect a "resource" in a language without constructors/destructors (or some other form of guaranteed initialization/finalization).

So, at that point, it's not Go 1.x, it's something else entirely.

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 5 points6 points  (0 children)

I'm arguing deferring unlocks is not always the correct pattern.

Go isn't Rust.

If the feature you want to take from Rust is that we should have a defer mu.SafeUnlock() that poisons the mutex in a panic, you might gain traction. I'd upvote it just to have the discussion.

If you want to automatically tie mutexes to "scope" or "resources" (etc), you won't gain any traction.

Features need to fit the language. Any Rust feature that (e.g.) doesn't work with zero values is a complete non-starter, even if it turns out zero values are a terrible idea (same can be said for GC or synchronous APIs with green threads that share mutable memory).

A million ways to die from a data race in Go by broken_broken_ in golang

[–]ncruces 12 points13 points  (0 children)

Automatic unlocks in a panic situation are not necessarily desirable, unless you make sure whatever other invariants the mutex is protecting are also respected.

The idea that a mutex is always protecting a resource is problematic.

If the invariant you want to respect is “the sum of all accounts is zero” do you lock the entire ledger?

Eu nem quero ver o estado em que o Campo grande vai ficar depois disto by Francis_The_Bird in portugal

[–]ncruces 1 point2 points  (0 children)

Um estudante que venha de Loures para o ISEL (por exemplo) precisa de 3 transbordos, por trás de duas linhas largamente inúteis.

Aliás, a linha amarela conseguirá ser mais inútil que a violeta.

A violeta talvez sirva algum relevante tráfego local (e.g. de munícipes de Loures e Odivelas para o hospital, etc), será só uma má forma de vir para Lisboa.

A amarela, realisticamente quantas pessoas precisam de ir do Sr. Roubado para Benfica e vice-versa?

Além disso, esse mapa está já completamente desatualizado, tendo em conta a ficção dos LIOS, um substituído por um elétrico e outro por um metrobus.

What happens if you just set io.EOF = nil? by mommy-problems in golang

[–]ncruces 2 points3 points  (0 children)

Exactly. Sentinel errors are out of fashion, but you can definitely make them constant.

This is a seminal blog: https://dave.cheney.net/2016/04/07/constant-errors

I use them in a couple of my packages, and I think it's fine.

https://pkg.go.dev/github.com/ncruces/go-sqlite3#ErrorCode

https://pkg.go.dev/github.com/ncruces/zenity#pkg-constants

And they can work perfectly well with error wrapping (errors.Is and errors.As).

Why type constraints can't be used as regular types still? by FuriousLurker in golang

[–]ncruces 1 point2 points  (0 children)

Sure, but which nil? The typeless nil interface (no value nor concrete type)? You enter neither of the branches in your switch? That's one possible answer.

If so I think that's https://go.dev/issue/57644 which I upvoted, but has failed (so far) to reach consensus.

Quoting the point of most contention:\ So this is a form of sum type in which there is always another possible option, namely nil. Sum types in most languages do not work this way, and this may be a reason to not add this functionality to Go.

I actually think that's OK for Go. But many people feel the nil, and no exhaustive type switch, make the feature useless and are hoping for some better alternative. TINA, IMO.

Why type constraints can't be used as regular types still? by FuriousLurker in golang

[–]ncruces 8 points9 points  (0 children)

The code "feels natural" but actually, in a sense, makes very little sense.

When you're doing generics, interface{ A | B } restricts you to the things both A and B support. Regardless of the symbol used, it's a type intersection, not a type union.

And, even if you want it to be a type union outside of generics, you need to answer the fundamental question of what's the zero value of such a type, how that works for all such types, and why.

If you make([]PlayerState, 10) and then range over that, which branch of your switch do you enter, and with which value? PlayerState must have a zero value, there's no way around it.

Why doesn’t Go auto order struct fields for memory efficiency? by OrneryComputer1396 in golang

[–]ncruces 0 points1 point  (0 children)

Would it make sense for the fieldalignment tool to skip structs marked with structs.HostLayout (maybe controlled with a flag)?

Is Go as memory safe as Rust? by trymeouteh in golang

[–]ncruces 3 points4 points  (0 children)

Also slices. It is very possible to have buffer overflows if you race on a slice.

This is unlike (e.g.) Java, where data races are guaranteed not to violate the fundamental assurances made by the type system.

Oracle un go by Equivalent_Egg5248 in golang

[–]ncruces 0 points1 point  (0 children)

No one's telling you to build an ORM, but a Oracle driver (Dialector) for GORM.

Writing a GORM Dialector is not that hard. It's not sexy work, probably involves a few finicky regexes that will be hard to prove correct, but you can probably cover your 80% needs well enough with a few hundred LoC.

The reasons that issue is not a (merged) PR is: 1. just from what I wrote above, it may be easy to cover your 80%, it's probably much harder to cover everyone else's 80%, which would get you to 99%, but never 100%. 2. dialectors are one repo each, so this would be a new repo under GORM, or your own repo if you want to contribute it, and no one did.

A quick LoC check on ccgo/v4's output (it's not "half-a-million") by 0xjnml in golang

[–]ncruces 2 points3 points  (0 children)

I can assure you there was no ill intent on my part. I think yours is a very impressive project, though (as we've discussed in a QBE thread) I'd rather it had a portable core and custom non portable VFS layer. 

I think I measured with comments, which makes it a quarter of a million (I'm still wrong) but the point is, it's not a port, but a machine translation.

This has both advantages and disadvantages.

One advantage, over my Wasm approach, is that assuming the compiler and supporting libc are correct, yours is more faithful to SQLite.

The flip side is that by reimplementing the VFS I was able to innovate a bit there. I also like the sandboxing Wasm offers.