CDC File Transfer
github.com
github.com
It is interesting what the result will be (average saving on deduplication) if it is applied globally to a large-scale blob storage, such as Amazon S3 or Google Drive (we need metadata storage about chunks, and the chunks can be deduplicated).
PS. I don't use this algorithm in ClickHouse, but it always remains tempting.
Do you have a suggestion on what to read on the topic since then?
I don't keep up with these things. A quick search came up with the following but I haven't read it yet.
Fan Ni and Song Jiang, "RapidCDC: Leveraging Duplicate Locality to Accelerate Chunking in CDC-based Deduplication Systems", in Proceedings of 2019 ACM Symposium on Cloud Computing (ACM SoCC'19), Santa Cruz, CA, November, 2019.
Yes this is truly promising but beware of dragons. Under current legal doctrine, blobs need some form of chain of custody. You can’t just deliver chunks to whomever has a hash (unless you’re decentralized, and you can move this problem to your users). Why? Because this is how bittorrent works, and we all know the legal dangers there. Encryption helps against eavesdropping, but not against an adversary who already has the hash and simply wants to prove you are distributing pirated material or even CSAM. You may be able to circumvent this to shift blame back on the user, in some cases. For instance, say you are re-syncing dangerous goods that you initially uploaded over Dropbox, then Dropbox can probably blame you, even though they are technically distributing. But that requires Dropbox to be reasonably confident that “you” (ie the same legal entity) had those chunks in the first place.
https://en.wikipedia.org/wiki/Illegal_number https://ansuz.sooke.bc.ca/entry/23 https://shkspr.mobi/blog/2022/11/illegal-hashes/
Off topic: I see downvotes on my parent comment, please let me know if I said something bad to help me improve.
Files become piracy when there is evidence of intentional copyright infringement, for example when the chunk is part of a valid MPEG4 file and the MPEG4 file is titled "Wednesday_S2E4_FullHD_NetflixRip.MP4"
It solves the link-rot issues that occur due to moving institutions, it allows huge storage for essentially free (ever tried to store 9 TB of training data or CERN data on Dropbox?), and it scales extremely beautifully.
It's really the absolute perfect solution for reproducible research in large data studies.
Later on I used it and vmware to build a proof of concept for a future model of computing where data was never lost. (it would snapshot the vm and add it to the storage system daily or hourly. look ma, infinite undo at a system level!)
The next version of the algorithm was going to use what I now know is essentially rolling hash (I called it "self delimiting data blocks"), but then the company went under.
> but there were some patents on it.
The patent system is quite silly and internally inconsistent. I'm older now, and suspect someone thought of saving disk space through coalescion of identical blocks before I did in 06/07 but not according to the USPTO!
Mine was at the block device level. The advantage is you can format it to whatever file system of your choice, with read/write support and deduplication just works.
Same! :) Originally I wrote it with an interface kinda similar to `tar` -- you add or extract huge blobs to/from what I called a coalesced archive. I could re-image a machine about 8x faster than Norton Ghost.
After $WORK went under, I kept the code and toyed around with it, making it speak NBD so instead of extracting a huge blob from the archive to a destination block device you could also access it directly. I feel like I never Properly solved write support though.
I'm curious, did you think of anything better than refcounting the data blocks and then keeping a list when the count goes to zero, then adding the next unique block to the zero list? That's all I could think of, and it adds at _least_ one additional layer of indirection which I didn't like bc it would have a performance impact.
> EMC had a disk based deduplication storage at the time. NetAppliance had a competing product. They had patents in the area.
I know this _NOW_ but certainly didn't know back then. :) And still doesn't take away the fact that according to the USPTO, "compression via coalescion" is miiiiine. ;-)
Again, I interpret this NOT as evidence of "how clever I am", but as evidence of how silly and broken the patent system is.
For reclaiming deleted blocks, I just had a garbage collection phase to run from time to time. Like you've mentioned on refcount, I've considered it but it amplified writes 2X~3X and worse they were random access writes. Garbage collection was not so bad since it's only going through the virtual file control blocks containing the content-address-hash.
The storage layout was: file block -> virtual file control block -> dedup-data-block. The virtual file control block contained the dedup block hash entries where one control block hosted N file blocks. GC only needed to scan the control blocks to find out which dedup-data-blocks were in use.
Freed dedup-data-blocks remained in place and were linked to the free list; the first couple bytes of the free block were cooped to store the pointer to the next free block.
At the end, brand new file write performance degraded about 10% compared to normal file write, which I considered acceptable. M block writes -> M dedup block writes + M/N control block writes + M/K db index updates, where N was the number of hash entries hosted in the control block and K is the number of hashes stored in one db index page. Repeated file writes were much faster due to deduplication.
Love it. Those were some very expensive ashes. I hope more comes from them too.
But I firmly believe that no project is wasted especially one that pushed the boundaries of what is commonly done. All the people working there learnt something. They might apply their new found knowledge to other fields or future carriers. The money invested is not lost but converted into bigger brains.
I look at VC money in much the same way. It's not great when a startup fails. But a lot is learnt.
2. This is a really neat project, and super expensive ashes to rise from Stadia.
3. This is targeted at Windows to Linux, but given the speed advantages that it has over rsync couldn’t this be Linux to Linux? That said, I’d be afraid to use this over rsync just from the body of experience and knowledge that exists about rsync.
I thought cultdeadcow. Tool for transferring t-files.
- 1-2 sentence summary of the project
- History (why we built this and didn't just use existing tools)
- What we've built, including what it does and how it compares to other tools (rsync in this case).
- How to install and use it
And the whole thing is full of images and animations showing the tool in action, and explaining enough of its internals.
I consider myself good at documentation, but I'm taking notes. This is excellent.
https://github.com/google/cdc-file-transfer/blob/main/fastcd...
[0] https://github.com/google/cdc-file-transfer/blob/main/docs/l...
"scp always copies full files, there is no "delta mode" to copy only the things that changed, it is slow for many small files, and there is no fast compression."
my thinking was: If you want to send diffs.. why not just use git?
It does compression and chunks and all that. Maybe the defaults perform poorly for binary files? But couldn't you fix that with a custom diff algo? (if it's somehow not appropriate, it'd still be nice to port whatever secret sauce they use here to git..)
This tool exists to send/receive files, and the diffing is an implementation detail used to achieve a high level of performance. It would make more sense for git to use this library under the hood as you mentioned.
Damn..
Then I guess even using this under the hood would be essentially a rewrite or how git fundamentally works internally
It's kind of weird actually - at the architectural level we interact with, we talk in terms of diffs - both in terms of display and what we put in.
At the next level down (content addressable store) git is storing whole files, and the git tooling translates the diffs we communicate about down into whole files for each commit.
Then at the next level down, git puts files together in packfiles (when the repo is packed) which is a compression system to make use of the fact that most files are just tweaks of other files. So, once again it's diffs.
I don't know if git sends or receives deltas though, I think it does?
> To help this situation, we developed two tools, cdc_rsync
Why not use rsync?
(It does seem they ended up faster than rsync, so perhaps that's "why", but that seems more like a post-hoc justification.)
The "we use variable chunk windows" bit is intriguing, but the example GIF sort of just pre-supposes that the local & remote chunks match up. That could have happened in the rsync case/GIF, but that wasn't the case considered, so it's an oranges/apples comparison. (Or, how is it that the local manages to be clairvoyant enough to choose the same windows?)
Yes! In content defined chunking, the chunk boundaries depend on the content, in our case a 64 byte window. If the local and the remote files have the same 64 byte sequence anywhere, and that 64 byte sequence has some magic pattern of 0s and 1s, they will both have chunk boundaries there. A chunk is the range of data between two chunk boundaries, so if N consecutive chunk boundaries match, then N-1 consecutive chunks match.
It's less sophisticated but it uses the same core idea and the implementation is super simple
I didn't appreciate the scope of this problem until a friend of mine visited from the valley. I live in semirural Canada, and they were floored by the speed and low latency of the fibre connection I have.
I sort of took it for granted that people would spend the extra twenty bucks or so to make work from home a painless experience, or at least ask their employer to fund a better connection.
It caused me to reach out, and I found many wfh peers with terrible connections, low powered laptops, and few second monitors. And proper desks? The exception.
My family is mostly in trades, and so spending a little cash to improve my tools felt like common sense. Apparently it isn't.
I think you took for granted the mere availability of fiber as an option.
30Mbps DSL is the best option I have, other than Starlink. And I live in San Jose!
I live in a tiny town on Vancouver Island and I have gigabit symmetric, for a very reasonable price. When I lived in Vancouver that simply wasn't an option.
But somehow that counts as a fiber deployment :/
I'd also try to rule out everything on your side, house wiring, routers, switches. Basically try to speed test it with the line they wired directly to the outside.
And upgrade any old network hardware.
Unless you're talking all they offer is 30Mbps. Then that's an ISP problem.
My family lives in old South Seattle neighborhoods and has excellent fiber.
I had something like 100mpbs co-axial 21 years ago in West Seattle.
What is the problem with San Jose?
I would pay $200/month extra for fiber.
The telcos were all given deals with assurances that they would bring rural America to something resembling what their urban counterparts have, but they've remained stagnant for some time now.
Starlink has finally given those people hope of seeing reasonable connectivity options. I would add in that T-Mobile Home Internet, and the likes, are doing so too, but on not as grand of a scale.
I could go to 1000mbps, but then I’m limited to 25mbps upload which is just terrible
The fiber is also used for TV etc., with several providers on the same fiber, so I imagine that the fiber provider gets income from the competing TV providers as well. Could be part of the why. As for myself, I only need and only pay for actual internet.
I've had 1Gb/1Gb fiber for many years now, and lately fiber arrives in the most unexpected areas (long distances, few residents). It (the deployment, not the monthly) used to be more costly, but it's not anymore. And no public money involved. I know that it used to be, as an experiment, a couple of decades or more ago, but only in certain areas.
Sometimes this can even be a problem in cities when the available infrastructure is at the limit. It's quite possible to move to an area, after having checked that good internet is available and suddenly the provider says no when signing up.
Thankfully, Starlink came out, and I was able to get like 50/20 for $110/mo on a month-to-month + $500 fixed.
rsync doesn't even have a great protocol specification... maybe it's a new tool...
How is the content defined? Where I'd try to begin is with a single pass that looks for runs of 'null' ('\0') bytes, even one long, as potential boundary ends. During that pass also look for 'magic signatures' for known stream types like already compressed content streams (all the more so to just not try compressing anyway). The CDC might also be aware of some file structures, zip, 7z, tar, etc; and have a dedicated segment creation algorithm for them. At a low level, the two ends should exchange a list of segment offsets, lengths, checksum (partial?) and maybe some short fragment of bytes to check. (E.G. 4 byte chunks at various powers of 2 offsets or major chunk starts.) Where the two ends have differences in chunks existing they might also expend some minor additional effort to investigate if the chunks that were identified on the other side exist locally; in case the two versions are using different filters or happened to reach different conclusions.
uint64_t hash = 0;
uint64_t magic_pattern = 0b001000010000100001000...;
for (size_t n = 0; n < data.size(); ++n) {
hash = (hash << 1) + random_table[data[n]];
if ((hash & magic_pattern) == 0) {
SetChunkBoundaryAt(n);
}
}
In practice, there's more bells and whistles, but that's the gist of it. By tweaking the numbers of 1's in magic_pattern you can influence the average chunk size (distance between two boundaries). With every additional 1, your chunk size halves. There's no special handling of compressed file types. You'd probably want to do that at a much higher level, e.g. just check for extensions.Sounds promising.
Though main goal has been keeping data usage low rather than speed up.
I have been implementing a file system replacement project for several years. It is designed to handle hundreds of millions of files within a single container; put contextual meta-data tags on them; and enable lightning fast searches for things based off file type and/or tags. (https://www.youtube.com/watch?v=dWIo6sia_hw)
One of the ideas (not yet fully implemented) was to break up large files at the file system level. You might have a 50 GB file of data that looks exactly like a normal file to any application accessing it, but in reality it might be 10 separate chunks of 5 GB each. If you add or delete any bytes within any individual chunk, it only adjusts that specific chunk. For example, deleting 100 bytes at offset 6 GB causes the second chunk to shrink by 100 bytes. All the chunks following it are unaffected. The file still looks to be 100 bytes smaller to the application, but it doesn't realize that a chunk in the middle was just reduced in size instead of all the bytes after the change being shifted down.
This feature would also make it easier to copy large files from one system to another. Data could be transferred one chunk at a time. If the copy was interrupted, only missing chunks would need to be copied when the process was restarted.
For example, a 6 GB file might be made up of 3 separate 2 GB chunks. An application might delete 20 bytes from the front of the file. This causes the first chunk to now be 2 GB - 20 bytes. The other 2 chunks are unchanged.
Current file systems do not allow this where a file can have a block somewhere in its interior that is just a partial block.
Because it would be costly for uncertain benefit?
If instead you chunk based off of local content (conceptually like chunking text into sentences at periods, but its a binary thing on has an upper size limit and lower size limit and I couldn't find the algorithm specification) so that after an insertion or deletion in a small number of bytes you start getting the same chunks as before.
This drastically reduces the cost of identifying unmodified chunks.
https://rsync.samba.org/tech_report/node3.html
Your description of content defined chunking is exactly right though. There are a number of techniques for doing it. FastCDC is one of them, although not the one used in rsync.
https://en.wikipedia.org/wiki/Rolling_hash
EDIT: Corrected in the comments below. Fixed sized chunks searched for at any offset with a rolling hash. The rsync algorithm description is here.
So a change partway through the file doesn't force rsync to actually re-transfer all of the subsequent unmodified chunks, but it does incur a computational cost to find them since it has to search through all possible offsets.
Say, we have 1GB file and we detected an extra byte at the head of our local copy. Great, what next? We can't replicate this on the receiving end without recopying the file, which is exactly what happens - rsync recreates target file from pieces of its old copy and differences received from the source. Every byte is copied, it's just that some of them are copied locally.
In that light, sync tools that operate with fixed-size blocks have one very big advantage - they allow updating target files in-place and limiting per-sync IO to writes of modified blocks only. This works exceptionally well for DBs, VMs, VHDs, file system containers, etc. It doesn't work well for archives (tars, zips), compressed images (jpgs, resource packs in games) and huge executables.
In other words - know your tools and know your data. Then match them appropriately.
Technically if you update a zip on the remote machine it'll work fine (the data gets appended in an update and the central directory record is always at the end of the zip.
I recall that tar has no end market at all so you can just append a new entry to it as well and when unpacked it'll overwrite the file from earlier in the archive. So they would work fine with rsync unless the tar is also compressed.
The tradeoff between zip and tar.{gz,xz,z} is that zip entries are compressed in the individual file context whereas in a compressed tar the entire archive is compressed in the same context. This may be a slight win for archives with many small files with similar structure.
Also, most modern compression tools have an "rsyncable" option that makes the archives play more nicely with rsync.
They both seem like very cool projects, so may the best Got win!
We are currently working on supporting Windows to Windows. Linux to Linux has lower priority as rsync already provides all functionality, it's just a bit slower on fast connections. On slow connections, rsync and cdc_rsync perform very similarly as the sync speed is dominated by the network.
"It employs an array of 256 random 64-bit integers to map the values of the byte contents in the sliding window"
I presume using something else would skew the distribution of selected chunks. I don't know if that would help or hinder.
In my very limited experience, a picture of Rick Astley as the constants gave a similar distribution™ of chunks over a mixture of documentation files and Linux ISOs.
It would be intersting to know how this compares to rclone copy or sync, because it uses threading, rsync doesn't.
[1]: https://rclone.org/
hash = (hash << 1) + random_table[data[n]];
bool chunk_boundary = (hash & magic_pattern) == 0;
per byte. That's only a few ops and very cache friendly. The random table only has 256 entries, 8 bytes each, so it easily fits into L1.So far I started using --link-dest for rsync, as explained in https://lincolnloop.com/insights/detecting-file-moves-rename... and used in https://github.com/dparoli/hrsync/blob/master/hrsync#L52
For my multiple backups to a backup host where I'm using rsync, restic really doesn't work (having 100+ systems backed up to the same destination).
Am I reading this right that onboarding your game to Stadia as a developer involved essentially rsyncing data directly to a Linux cloud instance?
That's.....
[1]Local-first software: You own your data, in spite of the cloud:
Linux to Linux is also an option if there is demand, but currently it's Windows to Linux only.
However, even though the games did not ship on Linux proper, the work that went in to supporting stadia had a profound effect on the games ability to work under WINE.
People often overlook Stadia as putting significant pressure on devs to support Linux, and give a lot of credit to Valve, but the reality is that both are responsible.
Whether this specific design choice alone killed Stadia, no one can say -- but it was probably one of the most important factors in its demise.
I play all my games on Linux, and in general, there are extremely few games I haven't gotten to run. Many just work out of the box through Proton, games not on Steam usually work out of the box with Lutris. This suggests to me that the Linux thing wasn't necessarily a big issue, if Google was willing to put in some work to get existing Windows games to work. AFAIK, they didn't do this and instead required games to run natively on Linux, which would significantly reduce the size of their games library (after all, why would a company invest time into porting their games to a Google product that's going to be shut down?).
Whether the US is even a market that's ready for game streaming is another question. Are there enough people with a high quality, low latency Internet connection that's close enough to a Stadia data center, who are interested in playing demanding games, but don't have the money for hardware yet can afford a monthly subscription on top of a high per-game price? Maybe it would be interesting if it worked like other subscription services and the subscription itself gave you access to games. I think Spotify would have flopped if you had to buy albums at their retail price in addition to the monthly subscription.
Nvidia allow this (kinda - some publishers do not allow their games to be played which is annoying), and I happily pay for it.
Frustratingly, it was not easy to know at a glance that this was what was happening, but there were times (many times, actually) where my chromecast ultra at home was performing much better with Stadia than my gaming PC
Better to embed a CRDT inside sqlite that can understand the semantics of sqlite's data, like cr-sqlite is doing:
Speaking of Courgette, though, I suggest looking into Zucchini which is faster and often produces smaller patches: https://news.ycombinator.com/item?id=29028534 (sorry for linking to my own comment but I haven't found any good explanation or benchmarks from Google)
I see how you put together the two .exe files but what is required on the linux side of things ?
https://en.wikipedia.org/wiki/Google_Wave
https://incubator.apache.org/projects/wave.html
Apache Wave was retired in 2018, but the source remains at least.
I may add this (and it fits somewhat nicely with file transfer..)
Why the sudden need to add an "h"?
Still, "syncing" is supposed to be shorthand for "synchronizing", which has the "h" you feel comes out of nowhere. So I guess both makes sense, but I don't use that form myself nor have seen anyone else use it in the wild.
It then goes on to talk about how much like rsync their new "cdc_rsync" tool is.
I get that the long version uses an h, but why include the silent h when making a shorthand? It sort of defeats the purpose of making a shorthand.
And if that Tarsnap presentation is from 2013, and FastCDC was published in 2016 [1] according to Wikipedia [2], then presumably Tarsnap didn't invent FastCDC either.
[1] https://www.usenix.org/system/files/conference/atc16/atc16-p...
[2] https://en.wikipedia.org/wiki/Rolling_hash#Gear_fingerprint_...
Only goes to show how TCP is not as reliable as it should
And I'm not sure what that has anything to do with TCP not as reliable. TCP has real problems on the modern Internet but the first part does not imply the second part.
Might I say, even if you get the same IP back from the router
Still nothing to do with TCP.
Also, this kind of partial file transfer protocol is still needed because what if a host crashes? Even if we completely solve the mobile IP problem we would still rely on both ends of the connection tracking state. That state is lost due to a crash or power failure.
Interesting you say that as I thought they explained their motivation pretty clearly. Is there a tool they missed that already does the job?
[1] https://www.usenix.org/system/files/conference/atc16/atc16-p...