Skip to content

moosichu/deltacompression

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 

Delta Compression in Unity

This is a Unity Package designed for Unity that allows you to perform binary delta compression given two similar native arrays of bytes.

This package depends on slightly modified versions of the K4os.Compression.LZ4 library by Milosz Krajewski. Instructions on how to setup this package with the correct dependencies can be found below.

This library as has a couple of helper functions for standard LZ4 compression as well.

Setup

Add the following dependencies to your Unity project's manifest.json file:

"com.moosichu.deltacompression": "https://github.com/moosichu/deltacompression.git",
"k4os.compression.lz4": "https://github.com/moosichu/K4os.Compression.LZ4.git#moosichu/unity-support",
"k4os.hash.xxhash": "https://github.com/moosichu/K4os.Hash.xxHash.git#moosichu/unity-support",

This will import the package*, along with the dependencies.

*It's worth noting that you should create your own copy of this repository and reference that as a package if you are using it in production, in-case this repo isn't available to you for whichever reason.

Usage

Below is the code for a sample static function that fills two arrays with random byte and then adds a few random bytes at random intervals to the second array. The second array is then compressed, we print out the compressed size and compression factor, and then decompress it and assert that we have constructed the original array.

As this is a simple library this should be enough to start with, if not the source code has some comments as well.

static void CompressTest()
{
    NativeArray<byte> bytes1 = new NativeArray<byte>(1000_000, Allocator.TempJob);
    NativeArray<byte> bytes2 = new NativeArray<byte>(1000_000, Allocator.TempJob);
    NativeArray<byte> bytes2Copy = new NativeArray<byte>(1000_000, Allocator.TempJob);
    int maximumLength = DeltaCompression.MaximumDeltaCompressionSize(bytes1.Length);
    Debug.Log($"We are compressing {bytes2.Length}, the maximum compressed size it could be is {maximumLength}");

    // CompressedBytesStorage allocates a backing array which will always be big enough to store the
    // the compressed result. After compression has completed you can extract the compressed data with
    // GetBytes()
    CompressedBytesStorage compressedData = new CompressedBytesStorage(bytes1.Length, Allocator.TempJob);
    try
    {
        // Fill a byte array with random numbers
        Unity.Mathematics.Random random = new Unity.Mathematics.Random(1);
        for (int i = 0; i < bytes1.Length; i++)
        {
            bytes1[i] = unchecked((byte)random.NextInt());
        }

        // Copy this to a second array
        bytes1.CopyTo(bytes2);

        // Randomise some bytes in the second array to ensure it does have some
        // differences
        for (int i = 0; i < bytes2.Length; i++)
        {
            bytes2[i] = unchecked((byte)random.NextInt());
            i += (int)(random.NextUInt() % 1000);
        }

        // We create a copy of the byte array we are going to compress, as the
        // compression function will modify the originally slightly in-place as
        // it runs.
        bytes2.CopyTo(bytes2Copy);

        {
            int numBytesDifferent = 0;
            for (int i = 0; i < bytes2.Length; i++)
            {
                if(bytes1[i] != bytes2[i])
                {
                    numBytesDifferent++;
                }
            }
            Debug.Log($"The number of bytes which differ is {numBytesDifferent}");
        }

        // Compress the second byte array
        JobHandle jobHandle = DeltaCompression.DeltaCompress(bytes1, bytes2, compressedData, default);
        jobHandle.Complete();

        NativeSlice<byte> compressedBytes = compressedData.GetBytes();
        Debug.Log($"The compressed size is {compressedBytes.Length}, this is a compression factor of {(float) compressedBytes.Length / (float) bytes2.Length}");

        // Fill the second byte array with random data, just so we know that we will be reconstructing it properly.
        for (int i = 0; i < bytes2.Length; i++)
        {
            bytes2[i] = unchecked((byte)random.NextInt());
        }

        jobHandle = DeltaCompression.DeltaDecompress(bytes1, compressedBytes, bytes2, jobHandle);
        jobHandle.Complete();

        // Assert decompression works.
        for (int i = 0; i < bytes2.Length; i++)
        {
            Debug.Assert(bytes2[i] == bytes2Copy[i]);
        }

        Debug.Log("Compression Success!");
    }
    finally
    {
        compressedData.Dispose();
        bytes2Copy.Dispose();
        bytes2.Dispose();
        bytes1.Dispose();
    }
}

About

Compress a Native Array based on its differences to another one

Topics

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.meta

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages