Go port of SQLite without CGo
gitlab.com
gitlab.com
https://words.filippo.io/easy-windows-and-linux-cross-compil...
I debated doing the pure-Go SQLite thing, but musl-cross worked just fine for me, and kept things simpler.
1. https://github.com/ClickHouse/sysroot/
2. https://github.com/ClickHouse/ClickHouse/blob/master/cmake/f... and the `CMAKE_TOOLCHAIN_FILE` variable.
export GOARCH=arm64
export CC=zig cc -target aarch64-linux-musl
export CXX=zig cc -target aarch64-linux-musl CC="/path/to/cross/compiler" CGO_CFLAGS=—I/path/to/sdk/header/files/include" CGO_LDFLAGS="-L/path/to/sdk/obj/files/lib”
I suppose with .so files, you might have to specify "-Wl,-rpath" if the SDK libraries don’t reside under /usr/lib or /usr/local/lib on the target system. But I haven’t actually tried any of this yet, so I could be wrong. Are there any gotchas that I’m missing?You're missing all the tooling and OS specific steps required to produce a proper package.
That repository won't compile Swift, but it does compile objective C.
Either way, you don't need to be able to compile Swift/Obj C to link to a library that was written in Swift/Obj C.
No one should touch servers directly, unless for down tracking stuff or remote development, in which case, they also don't need to cross compile.
No devs on production servers unless for tracking down issues, or servers configured for remote development.
Which in both cases, don't require cross compilation to start with.
The downside is that people (especially the ones who are just joining the workforce) are less efficient with the command line and more dependant on GUI. For example some of the junior devs do not know git cli anymore and rely on the VSCode plugin to interact with git. This becomes an issue when there is a bug in the plugin and you should use the CLI.
I know SCM tooling since the RCS days, and couldn't be bothered to master git implementation details to fix broken repos.
Unfortunely we are stuck with git for the time being.
I just really like to understand the tools that I use. Maybe it is a waste of time.
The developer should alao maintain their software and deploy it. Has IMHO a lot of advantages
Linux OEM vendors will appreciate it.
I got into UNIX development back when the whole team shared a development server and we used telnet and X Windows for our "IDE".
No one was running SPARC, RISC System/6000, PA-RISC, MIPS, Eclipse MV locally.
When everyone keeps worshipping UNIX, maybe it is time to learn how grey beards used to develop for it.
> No, and why should I?
These two statements are in direct conflict. CPU architecture is as much part of “matching the server” as operating system.
When I built software for SPARC, I was also running SPARC locally…
GOOS= GOARCH= CGO_ENABLED=1 go build \
-tags osusergo,netgo,sqlite_omit_load_extension \
-ldflags="-extldflags=-static"
[0]: https://www.arp242.net/static-go.htmlI look at it like a neat exercise but not really something to use in production. (I actually use it in tests though.)
Pretty sure the lead dev said something along those lines when he did an episode of Corecursive?
Only the TCL and SQL Logic Test are publicly available; it's one of the ways that the SQLite developers get paid.
it's got quirks but it's powerful and performs well
https://datastation.multiprocess.io/blog/2022-05-12-sqlite-i...
There’ll more opportunities for more optimizations since they move to SSA ir since 1.5 and in turn compile time will definitely go down
On one hand it makes you wonder how much could be squeezed out of Go and how many basic things they're still leaving out of the compiler. On the other it tells part of the story of why Go compiles fast with the backdrop that despite this lack of work by the compiler people use Go productively all day and deliver services they are happy with from a performance perspective.
[0] - https://go.dev/doc/go1.17#compiler (2021-08)
If you get high-level language constructs right, you'll get great performance by default, even with a simple compiler:
- structs instead of objects
- value types
- exposed pointers
- straightforward allocation semantics
Most compilers out there are busy fighting bad language designs. There's only so much a compiler can do when faced with fat objects hidden behind a spider web of pointers. So they have to do these microoptimizations to claw back at least some performance.
Linters and IDEs get slow when they check for errors, tests run slow, feedback drags, and all your workflows that took advantage of Go's fast compile times are now long enough that your flow and mental context disappear.
I'm way more lenient with other languages since the tooling and ecosystem are built around long build times. Your workflows compensate. But Go's tooling and ecosystem assume it compiles fast and treat things more like a scripting language. When that expectation is violated it hurts and everything feels like it's broken.
I guess you just need to compile the .a once and then just reuse it?
If you're rebuilding it every single time, your build is set up wrong.
https://gitlab.com/cznic/libc/-/blob/v1.22.2/libc_openbsd_am...
Always seemed silly that one of the most popular storage technologies couldn't be accessed with pure Go.
I don't know why Google didn't pay someone to do this or do it themselves. Surely they use Go and sqlite together.
This is it. They have internal datastores that they use for nearly everything. They might be using SQLite somewhere for something, but I really doubt this would even land near the bottom of their priority list.
Your comment truly does SQLite a disservice. SQLite is probably one of the most impressive pieces of software to have ever graced this earth.
Would you run sqlite in kubernetes? (if so... whyyyyyyy?)
That is why the go ecosystem tends to reimplement everything in go.
With this SQLite implementation I can stick it in my server (as a background, near real time mirror of memory state to disk) without worrying that the main loop will get clogged or my real time path will be hurt.
I use glabarez’ wrapper which makes it have an API like other Go databases: https://github.com/glebarez/sqlite/ and hey have been very responsive to issues I raised.
I have been running load tests against it for a few weeks, and it is quite solid.
When I noticed the SHA3 extension was missing (https://gitlab.com/cznic/sqlite/-/issues/139) it was noted it could be very easily patched client-side which is handy, as well as adding functionality into the core library to handle it.
Performance wise I haven't done intensive benchmark tests yet, but from my local experiments last year it performed ~1.5-2x slower than the CGO version for some queries (it is especially noticeable with LIKE expressions on large string data), but as mentioned previously, for most use cases it is already good enough.
Here are the most recent benchmarks I could find (I think from one of the maintainers of the lib) comparing the CGO version and the pure Go port - https://docs.google.com/spreadsheets/d/1YOP1D_ZhuR-ednQhTH6S...
Using that for https://www.octobench.com/ and I'm very happy.
Every program needs to do syscalls at some point, so that’s built in. It is not “in fact worse”.
Rephrasing my question, why wouldn’t you just use the SQLite library from Go, instead of cross-compiling it from C to Go? It sounds like the non-enthusiast “reimplement everything in my favorite language” answer is that Go’s FFI is a pain, even for C.
I see a bunch of huge Go files with architecture names.
Edit: Look around the source for "ccgo". Like https://gitlab.com/cznic/sqlite/-/blob/master/doc.go#L202 and look for "ccgo" in the closed issues.