Live data from Hacker News

Badger – A fast key-value store written natively in Go

open.dgraph.io

91–100 of 101 posts

Re: Badger – A fast key-value store written natively in Go

#91

It's interesting that the main motivation for this was that the Cgo interface to RocksDB wasn't good enough. I hate to turn this into a language war, but it's a big difference between Rust/Nim/etc where you just call C code more or less directly, and Go/Java/etc, which need a shim layer to bridge between C code and their language runtime. And possibly Go has the right approach! Is it better to make C integration as s…

I've thought about this a bit, because I use a lot of Go at work.

The reason calling C code from Go is mostly because Go has a different ABI: it does weird things with the stack, calling conventions, etc. But that doesn't stop you from calling assembly written to that ABI directly from Go. In fact, that is done a lot in the standard library. It is possible to create a wonky, C-like, low-level language that compiles into machine code with the Go ABI. Let's call this language Go-- :). With something like that, it might be possible to translate existing C code into Go--. However, the most likely use for Go-- would be for use in performance-critical sections of your Go code.

Re: Badger – A fast key-value store written natively in Go

#92
post #77

Earlier quoted context omitted.

> agpl is best for control In my personal opinion, AGPL is largely chosen to avoid various cloud providers from profiting significantly from $product, without ever giving back. That's control, but a very specific form of it. I don't personally like AGPLs legalese, it's very very imprecise.

From what I've heard of lawyers in the Free Software world, they most applauf AGPLv3 for its clarity and precision. Maybe it just seems imprecise to a layperson because they don't know the well-defined meaning of various legal terms? (... and confuse these with their fuzzy meaning in ordinary language)

> From what I've heard of lawyers in the Free Software world, they most applauf AGPLv3 for its clarity and precision.

You're sure they were talking AGPLv3 and not [L]GPLv3?

The definitions of what constitutes an interactive program is quite vague (sect 0 and 13). Let's say you have a database server under AGPL (mongo, or say citus). Clearly they support interactive access in some form, but from the perspective of user of an application using said database access is not interactive, nor is it clear how the database could provide such an interactive notice. Various vendors addressed that issue with clarifying notes about their understanding, but that definitely increases doubts of possible users, including their lawyers.

Re: Badger – A fast key-value store written natively in Go

#94

It's interesting that the main motivation for this was that the Cgo interface to RocksDB wasn't good enough. I hate to turn this into a language war, but it's a big difference between Rust/Nim/etc where you just call C code more or less directly, and Go/Java/etc, which need a shim layer to bridge between C code and their language runtime. And possibly Go has the right approach! Is it better to make C integration as s…

I've thought about this a bit, because I use a lot of Go at work. The reason calling C code from Go is mostly because Go has a different ABI: it does weird things with the stack, calling conventions, etc. But that doesn't stop you from calling assembly written to that ABI directly from Go. In fact, that is done a lot in the standard library. It is possible to create a wonky, C-like, low-level language that compiles i…

I'm skeptical that that would enable reuse of existing C code.

If the workflow requires you to modify or annotate the C code, that's a lot of work (and risky) and you might as well just rewrite it in Go.

If the workflow is totally automatic, so you can just use off-the-shelf C code, that's great! But in that case it's effectively just a C compiler, the "Go--" bit seems like a red herring.

It reminds me a bit of "C--", Simon Peyton Jones' suggestion for a low-level target for Haskell and similar languages. It would remove some C functionality that language runtimes don't really need, and add some extra low-level stuff like register globals and tail calls. I don't think that got much traction, but it may have influenced the design of LLVM.

Re: Badger – A fast key-value store written natively in Go

#95
post #14

There is so much negativity in these comments! This project is really cool! I really appreciate the trend to rewrite C/C++ libraries in Go. It has always been really frustrating that hacky library wrappers for other languages leave performance and features on the table because they're either incomplete or just too hard to implement in the host language. For most of the languages out there, it is always better to have…

Can C++ make use of this new Go library? It is my understanding that Go can now create shared libraries. That was my holdup for not adopting Go earlier on... it wasn't a good choice to write libraries in.

You've been able to do that since 1.5

``` go build -o libWithExport.so -buildmode=c-shared myProject ```

Re: Badger – A fast key-value store written natively in Go

#96
post #86
post #59

Earlier quoted context omitted.

(Badger author) We have tried huge prefetch size, using one Goroutine for each key; hence 100K concurrent goroutines doing value prefetching. But, in practice, throughput stabilizes after a very small number of goroutines (like 10). I suspect it's the SSD read latency that's causing range iteration to be slow; unless we're dealing with some slowness inherent to Go. A good way to test it out would be to write fio in G…

To fill the queue on Linux goroutine wont be enough you would need to use libaio directly. sudo apt-get install libaio1 libaio-dev.

Go has no native support for aio. Based on this thread, Goroutines seem to do the same thing, via epolls. https://groups.google.com/forum/#!topic/golang-nuts/AQ8JOHxm...

I think the best bet is to build a fio equivalent in Go (shouldn't take more than a couple of hours), and see if it can achieve the same throughput as fio itself. That can help figure out how slow is Go compared to using libaio directly via C.

Re: Badger – A fast key-value store written natively in Go

#97
post #96
post #86

Earlier quoted context omitted.

To fill the queue on Linux goroutine wont be enough you would need to use libaio directly. sudo apt-get install libaio1 libaio-dev.

Go has no native support for aio. Based on this thread, Goroutines seem to do the same thing, via epolls. https://groups.google.com/forum/#!topic/golang-nuts/AQ8JOHxm... I think the best bet is to build a fio equivalent in Go (shouldn't take more than a couple of hours), and see if it can achieve the same throughput as fio itself. That can help figure out how slow is Go compared to using libaio directly via C.

While Network socket in Go are using epolls automatically, file are not. From looking at Badger code for example: fd.ReadAt(buf, offset) would block.

See this issue: https://github.com/golang/go/issues/6817

Re: Badger – A fast key-value store written natively in Go

#98
I threw a simple smoke test on it: walk a directory tree and store each regular file in the tree in the data storage thing. The directory tree wasn't anything radical - just 112MB, 260 keys/values, biggest one was 10MB. Then close the storage thing, open it again and see if we can retrieve the contents. No concurrency, no crash recovery, nothing. Sure, maybe not exactly a typical workload, but let's see how things behave at the extremes first. They do talk about big keys in the blog post.

First impression. Easy to write the code.

Second impression. Fast as hell.

Third impression. Loses data. The last file in the set is consistently corrupted no matter how many times I try. I also tried on different directories. Exact same result everywhere. Last key/value written is truncated.

Hmm. A data storage thing that fails to store data is maybe not exactly invoking feelings of trust, which should be the primary feelings you have about your data storage thing.

Let's just throw it on something bigger. My /usr/lib. It's just 1.4GB. Shouldn't be too hard.

    [ 6546.783474] Killed process 4895 (main) total-vm:497120kB, anon-rss:368384kB, file-rss:0kB, shmem-rss:0kB
Hmm. Do they just store everything in memory forever? Sure, this VM has stupidly little memory. But that's why we have disk. So that we don't have to keep everything in memory. But good. Now we get to test the crash recovery mechanism.

    [ 6823.635967] Killed process 4919 (main) total-vm:677964kB, anon-rss:367980kB, file-rss:0kB, shmem-rss:0kB
Right. I guess there are reasons why experience taught me to let others be the first to use new data storage technology for a few years.

In case someone wonders the test code is here: https://gist.github.com/art4711/9d781b8cf1f9f36df73a9c5c0403...

It may be all wrong, but considering that the "docs" directory contains 6MB of stuff just to display "hello world" twice, I had to write it based on what godoc said.

Re: Badger – A fast key-value store written natively in Go

#99
post #27

Earlier quoted context omitted.

I think what fortytw2 was trying to say is that the AGPL is not a wise choice for software that wants to gain the most popularity and usage as possible since usage of AGPL licensed software is categorically banned (even more so than GPLV3) by a some of companies. As an aside, one can certainly describe something as draconic(or whatever else) if one views it as such; it's just an opinion.

Having just gone through a lengthy review process identifying a suitable license for our soon to be open-source software which has a commercial aspect, and selected AGPLv3, I'm very curious to know what companies have it "categorically banned". We did some research and didn't find that anyone had an issue with it. Whilst AGPL does open up come grey-areas which aren't as well understood as GPL the general reason to us…

There's a perennial discussion of AGPLv3 here on hacker news. A surprising number of projects select it, then revert to something less toxic to corporations.

Re: Badger – A fast key-value store written natively in Go

#100
post #65

Earlier quoted context omitted.

I'm curious if you have any more details here, or comparable benchmarks to share. BoltDB uses B+ trees and you say that a B+ tree approach is worth investigating due to improvements in SSD random write performance, so does BoltDB falsify that hypothesis or do you think it's just not well implemented and the idea still has potential?

We have tried with BoltDB. Its performance is really bad. It is just badly implemented, acquires a global mutex lock across all reads and writes. We wouldn't have written Badger if BoltDB worked for us. RocksDB performs much better and is the most popular and efficient KV store in the market, being used at both Google (Leveldb) and Facebook. Therefore, the benchmarks are against that. Without spending time generating…

> We have tried with BoltDB. Its performance is really bad.

BoltDB author here. I agree with you that Badger would beat Bolt in many performance benchmarks but it's an apples and oranges comparison. LSM tree key/value stores are write-optimized and generally lack transactional support. BoltDB is read-optimized and supports ACID transactions with serializable isolation. Transactions come with a cost but they're really important for most applications.

Regarding benchmarks, LSMs typically excel in random and sequential write performance and do OK with random read performance. LSMs tend to be terrible for sequential scans since levels have to be merged at query time. B+trees are usually terrible at random write performance but can do well with sequential writes that are batched. They tend to have good random read performance and awesome sequential scan performance.

It comes down to using the right tool for the job. If you don't need transactions, Bolt is probably overkill. There's whole section on the BoltDB README about when not to use Bolt:

https://github.com/boltdb/bolt#caveats--limitations

> It is just badly implemented, acquires a global mutex lock across all reads and writes.

You're welcome to your opinion about it being "badly implemented" but the global mutex lock across reads and writes is simply untrue. Writes are serialized so those have a database-wide lock. However, read transactions only briefly take a lock when they start and again when they stop so they can obtain a snapshot of the root node. That gives the transaction a point-in-time snapshot of the entire database for the length of the transaction without blocking other read or write transactions.

Post reply on HN