• Stars
    star
    29
  • Rank 860,307 (Top 17 %)
  • Language
    C#
  • License
    Other
  • Created over 10 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

| Public | 100% C# implementation of remote delta compression based on the rsync algorithm

Octodiff is a 100% managed implementation of remote delta compression. Usage is inspired by rdiff, and like rdiff the algorithm is based on rsync. Octodiff was designed to be used in Octopus Deploy, an automated deployment tool for .NET developers.

Octodiff can make deltas of files by comparing a remote file with a local file, without needing both files to exist on the same machine. It does this in three phases:

  1. Machine A reads the basis file, and computes a signature of all the chunks in the file
  2. Machine B uses the signature and the new file, to produce a delta file, specifying what changes need to be made
  3. Machine A applies the delta file to the basis file, which produces an exact copy of the new file

Of course, the benefit is that instead of transferring the entire new file to machine A, we just transfer a small signature, and a delta file containing the differences. We're trading off CPU usage for potentially large bandwidth savings.

Octodiff is an executable, but can also be referenced and used as any .NET assembly.

Signatures

Usage: Octodiff signature <basis-file> [<signature-file>] [<options>]

Arguments:

      basis-file             The file to read and create a signature from.
      signature-file         The file to write the signature to.

Options:

      --chunk-size=VALUE     Maximum bytes per chunk. Defaults to 2048. Min of
                             128, max of 31744.
      --progress             Whether progress should be written to stdout

Example:

octodiff signature MyApp.1.0.nupkg MyApp.1.0.nupkg.octosig --progress

This command calculates the signature of a given file. As per the rsync algorithm, the signature is calculated by reading the file into fixed-size chunks, and then calculating a signature of each chunk. The resulting signature file contains:

  • Metadata about the signature file and algorithms used
  • Hash of the file that the signature was created from (basis file hash)
  • A list of chunk signatures, each 26 bytes long, consisting of:
    • The length of the chunk (short)
    • Rolling checksum (uint) - calculated using Adler32
    • Hash (20 bytes) - calculated using SHA1

Given that the default chunk size is 2048 bytes, and this is turned into a 26 byte signature, the resulting file is about 1.3% of the size of the original. For example, a 306MB file creates a 3.9MB signature file. The signature of a 300mb file can be calculated in ~3 seconds using ~6mb of memory on a 2013 Macbook Pro. Memory usage during signature calculation should remain constant no matter the size of the file.

Deltas

Usage: Octodiff delta <signature-file> <new-file> [<delta-file>] [<options>]

Arguments:

      signature-file         The file containing the signature from the basis
                             file.
      new-file               The file to create the delta from.
      delta-file             The file to write the delta to.

Options:

      --progress             Whether progress should be written to stdout

Example:

octodiff delta MyApp.1.0.nupkg.octosig MyApp.1.1.nupkg MyApp.1.0_to_1.1.octodelta --progress

This command creates a delta, that specfies how the basis-file (using just the information in its signature file) can be turned into the new-file. First, the signature file is read into memory. Then we scan the new file, looking for chunks that we find in the signature. You can learn more about the process in the rsync algorithm.

The delta file contains:

  • Metadata about the signature file and algorithms used
  • Hash of the file that the original signature was created from (basis file hash)
  • A series of instructions to re-create the new-file which reference the basis file.

Instructions are either copy commands (read offset X, length Y from the basis file) or data commands (add this data). Example:

  1. Copy 0x0000 to 0x8C00
  2. Data: 5C 9F D9 C7...
  3. Copy 0x8C31 to 0x93C0

The delta file uses a binary file format to keep encoding overhead to a minimum - copy instructions start with 0x60 and then the start offset and length; data commands are 0x80 followed by the length of the data and then the data to copy.

For debugging, you can use the following command to print an explanation of what is in a given delta file:

octodiff explain-delta MyApp.1.0_to_1.1.octodelta

Patching

Usage: Octodiff patch <basis-file> <delta-file> <new-file> [<options>]

Arguments:

      basis-file             The file that the delta was created for.
      delta-file             The delta to apply to the basis file
      new-file               The file to write the result to.

Options:

      --progress             Whether progress should be written to stdout
      --skip-verification    Skip checking whether the basis file is the same
                             as the file used to produce the signature that
                             created the delta.

Example:

octodiff patch MyApp.1.0.nupkg MyApp.1.0_to_1.1.octodelta MyApp.1.1.nupkg --progress

This command recreates the new-file using simply the basis-file and the delta-file.

Applying the delta is the easiest part of the process. We simply open the delta-file, and follow the instructions. When there's a copy instruction, we seek to that offset in the basis-file and copy until we hit the length. When we encounter a data instruction, we append that data. At the end of the process, we have the new-file.

Octodiff embeds a SHA1 hash of the new-file in the delta-file. After patching, Octodiff compares this hash to the SHA1 hash of the resulting patched file. If they don't match, Octodiff returns a non-zero exit code.

Performance

The following section isn't meant to be mathematically accurate, but to give you a rough idea of real-world performance to expect from Octodiff. The tests were done on a Windows 8 VM, running in a 2013 Macbook Pro, with 4 cores and 8GB of memory assigned to the VM. The machine uses an SSD which mean the I/O bound tasks could run significantly slower on non-SSD drives. All measurements were done using simply Windows Task Manager.

Signature creation is relatively easy - we're reading the file in fixed-size chunks and computing a checksum. Memory usage should be constant no matter how big the file is - around 8.2 MB.

  • The signature for an 85 MB file can be calculated in ~832 ms
  • The signature for a 4.4 GB file can be calculated in ~36 seconds

We also compute a SHA1 hash of the entire basis file (this takes around 1/3 of the total time above). The resulting signature file size is always ~1.3% of the basis file size.

Delta creation is the most CPU and memory-intensive aspect of the whole process. First, we assume that we can fit all signatures into memory, which means at a minimum we'll consume at least ~1.3% of the basis file in memory, plus extra to store a dictionary of the chunks and buffers as we read data. Budget for about 5x the signature file size in memory (e.g., for a 57 MB signature file (a 4.4 GB basis file), expect to use 250mb of memory).

  • Delta from a 85 MB file took 5 seconds
  • Delta from a 4.3 GB ISO took 170 seconds

Delta creation takes roughly the same amount of time whether there are many differences or none at all. If there are many differences, the resulting delta file will be much larger, so additional I/O producing it may have an impact.

Patching is the fastest part of the algorithm.

Output and exit codes

If all goes well, Octodiff produces no output. You can use the --progress switch to write progress messages to stdout.

Octodiff uses the following exit codes:

  • 0 - success
  • 1 - environmental problems
  • 2 - corrupt signature or delta file
  • 3 - internal error or unhandled situation
  • 4 - usage problem (you did something wrong, maybe passing the wrong file)

Using OctoDiff classes within your own application

To use the OctoDiff classes to create signature/delta/final files from within your own application, you can use the below example which creates the signature and delta file and then applies the delta file to create the new file.

// Create signature file
var signatureBaseFilePath = @"C:\OctoDiffExample\MyPackage.1.0.0.zip";
var signatureFilePath = @"C:\OctoDiffExample\Output\MyPackage.1.0.0.zip.octosig";
var signatureOutputDirectory = Path.GetDirectoryName(signatureFilePath);
if(!Directory.Exists(signatureOutputDirectory))
	Directory.CreateDirectory(signatureOutputDirectory);
var signatureBuilder = new SignatureBuilder();
using (var basisStream = new FileStream(signatureBaseFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var signatureStream = new FileStream(signatureFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
	signatureBuilder.Build(basisStream, new SignatureWriter(signatureStream));
}

// Create delta file
var newFilePath = @"C:\OctoDiffExample\MyPackage.1.0.1.zip";
var deltaFilePath = @"C:\OctoDiffExample\Output\MyPackage.1.0.1.zip.octodelta";
var deltaOutputDirectory = Path.GetDirectoryName(deltaFilePath);
if(!Directory.Exists(deltaOutputDirectory))
	Directory.CreateDirectory(deltaOutputDirectory);
var deltaBuilder = new DeltaBuilder();
using(var newFileStream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var signatureFileStream = new FileStream(signatureFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var deltaStream = new FileStream(deltaFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
	deltaBuilder.BuildDelta(newFileStream, new SignatureReader(signatureFileStream, new ConsoleProgressReporter()), new AggregateCopyOperationsDecorator(new BinaryDeltaWriter(deltaStream)));
}

// Apply delta file to create new file
var newFilePath2 = @"C:\OctoDiffExample\Output\MyPackage.1.0.1.zip";
var newFileOutputDirectory = Path.GetDirectoryName(newFilePath2);
if(!Directory.Exists(newFileOutputDirectory))
	Directory.CreateDirectory(newFileOutputDirectory);
var deltaApplier = new DeltaApplier { SkipHashCheck = false };
using(var basisStream = new FileStream(signatureBaseFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var deltaStream = new FileStream(deltaFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var newFileStream = new FileStream(newFilePath2, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
{
	deltaApplier.Apply(basisStream, new BinaryDeltaReader(deltaStream, new ConsoleProgressReporter()), newFileStream);
}

Development

You need:

Run Build.cmd to build, test and package the project.

To release to Nuget, tag master with the next major, minor or patch number, TeamCity will do the rest.

Every successful TeamCity build for all branches will be pushed to MyGet.

More Repositories

1

OctoPack

Creates Octopus-compatible NuGet packages
C#
179
star
2

Library

| Public | A repository of step templates and other community-contributed extensions to Octopus Deploy
PowerShell
171
star
3

Issues

| Public | Bug reports and known issues for Octopus Deploy and all related tools
160
star
4

PowerShell-IIS-Examples

Examples showing how to do everything with IIS and PowerShell
C#
85
star
5

install-octopus-cli-action

| Public | :octocat: GitHub Action to Install the Octopus CLI
TypeScript
80
star
6

create-release-action

| Public | :octocat: GitHub Action to Create a Release in Octopus Deploy
TypeScript
77
star
7

Octostache

| Public | The variable substitution syntax for Octopus Deploy
C#
72
star
8

OctopusDSC

| Public | A PowerShell DSC resource for installing Octopus Deploy & Tentacles
PowerShell
71
star
9

ICanHasDotnetCore

Scans uploaded packages.config files or GitHub repository and determines whether the nuget packages target .NETStandard
C#
71
star
10

People

| Public | Describes our culture and our people
58
star
11

OctoTFS

| Public | Octopus extensions for Azure DevOps, TFS, VSTS, and VSO
TypeScript
57
star
12

Octopus-Docker

Scripts to run Octopus Server inside a docker container [WIP]
PowerShell
36
star
13

cli

| Public | Next Generation of the Octopus CLI πŸ™
Go
33
star
14

Octopus-TeamCity

| Public | JetBrains TeamCity plugin to trigger releases on build completion
Java
32
star
15

push-package-action

| Public | :octocat: GitHub Action to Push a Package to Octopus Deploy
TypeScript
31
star
16

octopackjs

A nodejs tool for packaging and pushing projects to an Octopus Deploy instance.
JavaScript
26
star
17

octopus-jenkins-plugin

| Public | Jenkins plugin which integrates with Octopus Deploy
Java
17
star
18

run-runbook-action

| Public | :octocat: GitHub Action to Run a Runbook in Octopus Deploy
TypeScript
17
star
19

TentaclePing

| Public | Diagnostics utility for Tentacle
C#
16
star
20

OctopusDeploy-Api

| Public | Code snippet samples for various operations in the Octopus Deploy REST API
PowerShell
16
star
21

OctopusGrafanaDataSource

| Public |
Go
14
star
22

Calamari

| Public | The core deployment scripts and tools used by Octopus Deploy
C#
13
star
23

CSProjToXProj

Scans a directory and converts .csproj files (and packages.config) to .xproj and project.json and (optionally) updates the solution
C#
13
star
24

go-octopusdeploy

| Public | Go API Client for Octopus Deploy πŸ™
Go
12
star
25

Halibut

| Public | A secure communication stack for .NET using JSON-RPC over SSL.
C#
11
star
26

TenderSmash

A faster, more fluid UI on top of TenderApp
JavaScript
11
star
27

Specs

| Public |
HCL
11
star
28

helm-charts

Helm chart for deploying Octopus Deploy into a Kubernetes cluster
C#
10
star
29

OctopusTentacle

| Public | The secure, lightweight, cross-platform agent for Octopus Server which turns any computer into a worker or deployment target for automated deployments and operations runbooks.
C#
10
star
30

gulp-octo

⛔️ DEPRECATED A gulp wrapper for octopack library to push projects to Octopus Deploy
JavaScript
9
star
31

DirectoryServicesAuthenticationProvider

| Public |
C#
9
star
32

Architecture

A repository of engineering sensible defaults and decisions that apply across Octopus products
9
star
33

Nevermore

| Public | A JSON Document Store library for SQL Server
C#
8
star
34

Octopus-Bamboo

| Public | Octopus plugin for Bamboo
Java
8
star
35

ASP.NET-Deployment-Book

8
star
36

push-build-information-action

| Public | :octocat: GitHub Action to Push Build Information to Octopus Deploy
TypeScript
8
star
37

OpenIDConnectAuthenticationProviders

| Public |
C#
7
star
38

OctopusCLI

| Public | Command line tool for Octopus Deploy
C#
6
star
39

docs

| Public | Octopus Deploy documentation
MDX
6
star
40

AnsibleDemo

6
star
41

NanoPack

A tool to package ASP.NET Core applications into a NanoServer VHD
C#
6
star
42

octofxjs

A sample project to demonstrate packaging and pushing Node.js projects
JavaScript
6
star
43

grunt-octo

A Grunt wrapper for [octopack](https://github.com/OctopusDeploy/octojs) library to push projects to Octopus Deploy
JavaScript
6
star
44

WhoIsCalling

Quick little .NET 4 console app that listens for inbound TCP connections and prints the client IP address/port
C#
5
star
45

Sashimi

| Public |
C#
4
star
46

Shellfish

| Public | Octopus.Shellfish.*, ShellExecutor and other commandline invocation things
C#
4
star
47

ServerExtensibility

| Public |
C#
4
star
48

deploy-release-tenanted-action

| Public | :octocat: GitHub Action to Deploy a Tenanted Release in Octopus Deploy
TypeScript
4
star
49

Hyponome

The OctopusDeploy / Library Pull Request review tool
JavaScript
4
star
50

Sampler

Command line tool to create sample projects in Octopus
C#
4
star
51

Configuration

| Public |
C#
3
star
52

OctopusClients

| Public | Octopus.Client for commanding Octopus servers
C#
3
star
53

Channels.Sample

| Public | Sample projects for the Channels Walkthrough at https://octopus.com/blog/channels-walkthrough
JavaScript
3
star
54

AuthenticationExtensibility

| Public |
C#
3
star
55

OctoFX-training

OctoFX - for training purposes
JavaScript
3
star
56

JiraIntegration

| Public |
C#
3
star
57

opentelemetry-teamcity-plugin

| Public | A TeamCity plugin that contains a build listener to send OpenTelemetry trace data to an external endpoint
Java
3
star
58

octopus-serverspec-extensions

ServerSpec extensions for Octopus Deploy, with support for Tentacles, Workers, Worker Pools, Environments and more
Ruby
3
star
59

deploy-release-action

| Public | :octocat: GitHub Action to Deploy a Release in Octopus Deploy
TypeScript
3
star
60

create-zip-package-action

| Public | :octocat: GitHub Action to Create a Zip Package to Upload to Octopus Deploy
TypeScript
2
star
61

ArquillianInfrastructureTesting

Java
2
star
62

Octopus.Web.Xdt

C#
2
star
63

api-client.ts

| Public | TypeScript API client for Octopus Deploy βœ¨πŸ™πŸš€βœ¨
TypeScript
2
star
64

ArquillianTest

Java
2
star
65

RoslynAnalyzers

| Public | Roslyn analysers used for Octopus Projects
C#
2
star
66

HCLParser

| Public |
HCL
2
star
67

bell-toad-beamish

| Public | Used for testing GitHub Secrets Scanning
2
star
68

OctoProduct

2
star
69

GuestAuthenticationProvider

| Public |
C#
2
star
70

CommandLine

| Public | The command line parsing library used by many of Octopus apps.
C#
2
star
71

TeamCityCloudAgentUpdater

| Public | Simple NodeJS app to update AMI's for TeamCity Cloud Agents
JavaScript
2
star
72

Octopus.Dependencies.AWSCLI

| Public | AWS CLI repack
PowerShell
2
star
73

octo-webpack-plugin

A webpack wrapper for octopack library to push projects to Octopus Deploy
JavaScript
2
star
74

push-build-information-buildkite-plugin

| Public | Buildkite plugin to push build information to Octopus Deploy
Shell
2
star
75

message-contracts.ts

| Public | Shared TypeScript definitions for Octopus Deploy API messages πŸ™
TypeScript
2
star
76

blog

| Public | The Octopus Deploy blog
2
star
77

Sashimi.Terraform

| Public |
C#
2
star
78

UsernamePasswordAuthenticationProvider

| Public |
C#
2
star
79

GitHubIssueTracker

| Public |
C#
2
star
80

Orca

Credential scanning for Github Repositories
Go
2
star
81

util-actions

| Public | A set of utility actions for use in GitHub action workflows
TypeScript
2
star
82

create-release-buildkite-plugin

| Public | Buildkite plugin to create a release through Octopus Deploy
Shell
1
star
83

create-nuget-package-action

| Public | :octocat: GitHub Action to Create a NuGet Package for Octopus Deploy
TypeScript
1
star
84

OctoVersion

| Public | .NET tool for determining version number based on the Git revision graph
C#
1
star
85

ThymeleafSpringDemo

| Public | Simple Spring ThymeLeaf Demo
Shell
1
star
86

vscode-octopusdeploy

| Public | Octopus Deploy for Visual Studio Code πŸ™
TypeScript
1
star
87

step-package-template

| Public | A template to getting started with Octopus Deploy step packages
JavaScript
1
star
88

Versioning

| Public |
C#
1
star
89

homebrew-taps

| Public | The homebrew tap repo for OctopusCli
Ruby
1
star
90

Sashimi.AzureAppService

| Public |
C#
1
star
91

Sashimi.AzureScripting

| Public |
C#
1
star
92

SpringBootStopper

| Public |
Shell
1
star
93

StartTeamCityAgentWhenZIsAvailableService

Service that is used to delay the start of the TCBuildAgent until AWS has attached the ephemeral (SSD) drives
C#
1
star
94

go-octodiff

| Public | 100% Go implementation of remote delta compression based on the rsync algorithm (based on C# OctoDiff)
Go
1
star
95

JavaPropertiesParser

| Public |
C#
1
star
96

OptimumSetupBook

| Public | This repo is used to store the open source book on how to setup an Octopus Deploy Server to scale up and out.
1
star
97

SpringBootWindowsService

| Public |
Shell
1
star
98

Octopus.Dependencies.GoogleCloudCli

| Public |
PowerShell
1
star
99

Time

| Public |
C#
1
star
100

Caching

| Public | A simple but battle hardened in memory cache designed to be registered globally in your IoC container
C#
1
star