Home

Awesome

hsynz

release license PRs Welcome +issue Welcome

Build Status

english | 中文版

hsynz is a library for delta update using sync algorithm, like zsync.
rsync over http(s); implement the sync algorithm on client side, and server side only need http(s) cdn. support compressor zstd & libdeflate & zlib, support large file & directory(folder), support muti-thread.

Recommended scenarios: Very large number of older versions or where older versions are not available (not saved or modified, etc.) so that all deltas cannot be calculated in advance.

The server uses hsync_make to process the latest version of the data once, generating a summary info file(hsyni) of the new version of the data in chunks, and optionally compressing the new version of the data in chunks to get the release file(hsynz), which would be the hsynz equivalent if the new version of the original file were not compressed.

The client first downloads the hsyni file from the server or another user's share, calculates the updated blocks it needs to download based on its old version, and learns the location of these blocks in hsynz based on the information in hsyni, selects a communication method to download them on demand from the server's hsynz file, and merges the downloaded blocks with the existing data locally to get the latest version of the data.

hsync_demo provides a test client demo for local file testing.
hsync_http provides a download client demo with http(s) support for sync update from a server that provides an http(s) file download service(e.g CDN, support HTTP/1.1 muti range Requests).
Tip: You can also customise other communication methods for sync.


Compare with zsync


Releases/Binaries

Download from latest release : Command line app for Windows, Linux, MacOS; and .so lib for Android.
( release files build by projects in path hsynz/builds )

Build it yourself

Linux or MacOS X

$ cd <dir>
$ git clone --recursive https://github.com/sisong/hsynz.git
$ cd hsynz
$ make

Windows

$ cd <dir>
$ git clone --recursive https://github.com/sisong/hsynz.git

build hsynz/builds/vc/hsynz.sln with Visual Studio

libhsynz.so for Android


hsync_make command line usage:

hsync_make: [options] newDataPath out_hsyni_file [out_hsynz_file]
  newDataPath can be file or directory(folder),
  if newDataPath is a file & no -c-... option, out_hsynz_file can empty.
options:
  -s-matchBlockSize
      matchBlockSize>=128, DEFAULT -s-2k, recommended 1024,4k,...
  -b-safeBit
      set allow patch fail hash clash probability: 1/2^safeBit;
      safeBit>=14, DEFAULT -b-24, recommended 20,32...
  -p-parallelThreadNumber
    DEFAULT -p-4;
    if parallelThreadNumber>1 then open multi-thread Parallel mode;
  -c-compressType[-compressLevel]
      set out_hsynz_file Compress type & level, DEFAULT uncompress;
      support compress type & level:
        -c-zlib[-{1..9}[-dictBits]]     DEFAULT level 9
            dictBits can 9--15, DEFAULT 15.
        -c-gzip[-{1..9}[-dictBits]]     DEFAULT level 9
            dictBits can 9--15, DEFAULT 15.
            compress by zlib, out_hsynz_file is .gz file format.
        -c-ldef[-{1..12}]           DEFAULT level 12 (dictBits always 15).
            compress by libdeflate, compatible with zlib's deflate encoding.
        -c-lgzip[-{1..12}]          DEFAULT level 12 (dictBits always 15)
            compress by libdeflate, out_hsynz_file is .gz file format.
        -c-zstd[-{10..22}[-dictBits]]   DEFAULT level 21
            dictBits can 15--30, DEFAULT 24.
  -C-checksumType
      set strong Checksum type for block data, DEFAULT -C-xxh128;
      support checksum type:
        -C-xxh128
        -C-md5
        -C-sha512
        -C-sha256
        -C-crc32
            WARNING: crc32 is not strong & secure enough!
  -n-maxOpenFileNumber
      limit Number of open files at same time when newDataPath is directory;
      maxOpenFileNumber>=8, DEFAULT -n-48, the best limit value by different
        operating system.
  -g#ignorePath[#ignorePath#...]
      set iGnore path list in newDataPath directory; ignore path list such as:
        #.DS_Store#desktop.ini#*thumbs*.db#.git*#.svn/#cache_*/00*11/*.tmp
      # means separator between names; (if char # in name, need write #: )
      * means can match any chars in name; (if char * in name, need write *: );
      / at the end of name means must match directory;
  -f  Force overwrite, ignore write path already exists;
      DEFAULT (no -f) not overwrite and then return error;
      if used -f and write path is exist directory, will always return error.
  --patch
      swap to hsync_demo mode.
  -v  output Version info.
  -h or -?
      output Help info (this usage).

hsync_http command line usage:

download   : [options] -dl#hsyni_file_url hsyni_file
local  diff: [options] oldPath hsyni_file hsynz_file_url -diff#outDiffFile
local patch: [options] oldPath hsyni_file -patch#diffFile outNewPath
sync  infos: [options] oldPath hsyni_file [-diffi#cacheTempFile]
sync  patch: [options] oldPath [-dl#hsyni_file_url] hsyni_file hsynz_file_url [-diffi#cacheTempFile] 
  oldPath can be file or directory(folder),
  if oldPath is empty input parameter ""
options:
  -dl#hsyni_file_url
    download hsyni_file from hsyni_file_url befor sync patch;
  -diff#outDiffFile
    create diffFile from ranges of hsynz_file_url befor local patch;
  -diffi#cacheTempFile
    saving diffInfo to cache file for optimize speed when continue sync patch;
  -patch#diffFile
    local patch(oldPath+diffFile) to outNewPath;
  -cdl
    continue download data from breakpoint;
    DEFAULT continue download mode is closed;
  -r-stepRangeNumber
    DEFAULT -r-32, recommended 16,20,...
    limit the maximum number of .hsynz data ranges that can be downloaded
    in a single request step;
    if http(s) server not support muti-ranges request, must set -r-1
  -p-parallelThreadNumber
    DEFAULT -p-4;
    if parallelThreadNumber>1 then open multi-thread Parallel mode;
    NOTE: now download data always used single-thread.
  -n-maxOpenFileNumber
      limit Number of open files at same time when oldPath is directory;
      maxOpenFileNumber>=8, DEFAULT -n-24, the best limit value by different
        operating system.
  -g#ignorePath[#ignorePath#...]
      set iGnore path list in oldPath directory; ignore path list such as:
        #.DS_Store#desktop.ini#*thumbs*.db#.git*#.svn/#cache_*/00*11/*.tmp
      # means separator between names; (if char # in name, need write #: )
      * means can match any chars in name; (if char * in name, need write *: );
      / at the end of name means must match directory;
  -f  Force overwrite, ignore write path already exists;
      DEFAULT (no -f) not overwrite and then return error;
      not support oldPath outNewPath same path!
      if used -f and outNewPath is exist file:
        if patch output file, will overwrite;
        if patch output directory, will always return error;
      if used -f and outNewPath is exist directory:
        if patch output file, will always return error;
        if patch output directory, will overwrite, but not delete
          needless existing files in directory.
  -v  output Version info.
  -h or -?
      output Help info (this usage).

hsync_demo command line usage:

This cmdline is used for local sync tests, replacing the actual URL remote file with local file, see the hsync_http usage.


hsynz vs zsync:

case list(download from OneDrive):

newFile <-- oldFilenewSizeoldSize
17-Zip_22.01.win.tar <-- 7-Zip_21.07.win.tar59089925748224
2Chrome_107.0.5304.122-x64-Stable.win.tar <-- 106.0.5249.119278658560273026560
3cpu-z_2.03-en.win.tar <-- cpu-z_2.02-en.win.tar87183368643072
4curl_7.86.0.src.tar <-- curl_7.85.0.src.tar2627584026030080
5douyin_1.5.1.mac.tar <-- douyin_1.4.2.mac.tar407940608407642624
6Emacs_28.2-universal.mac.tar <-- Emacs_27.2-3-universal.mac.tar196380160257496064
7FFmpeg-n_5.1.2.src.tar <-- FFmpeg-n_4.4.3.src.tar8052736076154880
8gcc_12.2.0.src.tar <-- gcc_11.3.0.src.tar865884160824309760
9git_2.33.0-intel-universal-mavericks.mac.tar <-- 2.31.07330252870990848
10go_1.19.3.linux-amd64.tar <-- go_1.19.2.linux-amd64.tar468835840468796416
11jdk_x64_mac_openj9_16.0.1_9_openj9-0.26.0.tar <-- 9_15.0.2_7-0.24.0363765760327188480
12jre_1.8.0_351-linux-x64.tar <-- jre_1.8.0_311-linux-x64.tar267796480257996800
13linux_5.19.9.src.tar <-- linux_5.15.80.src.tar12696371201138933760
14Minecraft_175.win.tar <-- Minecraft_172.win.tar166643200180084736
15OpenOffice_4.1.13.mac.tar <-- OpenOffice_4.1.10.mac.tar408364032408336896
16postgresql_15.1.src.tar <-- postgresql_14.6.src.tar151787520147660800
17QQ_9.6.9.win.tar <-- QQ_9.6.8.win.tar465045504464837120
18tensorflow_2.10.1.src.tar <-- tensorflow_2.8.4.src.tar275548160259246080
19VSCode-win32-x64_1.73.1.tar <-- VSCode-win32-x64_1.69.2.tar364025856340256768
20WeChat_3.8.0.41.win.tar <-- WeChat_3.8.0.33.win.tar505876992505018368

test PC: Windows11, CPU R9-7945HX, SSD PCIe4.0x4 4T, DDR5 5200MHz 32Gx2
Program version: hsynz 1.1.1, zsync 0.6.2 (more programs's testing see HDiffPatch)
test Program:
zsync run make with zsyncmake -b 2048 -o {out_newi} {new},
client sync diff&patch by zsync -i {old} -o {out_new} {newi} (all files are local)
zsync -z run make with zsyncmake -b 2048 -z -u {new.gz} -o {out_newi} {new}
hsynz run make with hsync_make -s-2k {new} {out_newi} [{-c-?} {out_newz}],
client sync diff&patch by hsync_demo {old} {newi} {newz} {out_new} (all files are local)
hsynz p1 run make without compressor & out_newz , add -p-1
hsynz p8 run make without compressor & out_newz , add -p-8
hsynz p1 -zlib run make with -p-1 -c-zlib-9 (run hsync_demo with -p-1)
hsynz p8 -zlib run make with -p-8 -c-zlib-9 (run hsync_demo with -p-8)
hsynz p1 -gzip run make with -p-1 -c-gzip-9 (run hsync_demo with -p-1)
hsynz p8 -gzip run make with -p-8 -c-gzip-9 (run hsync_demo with -p-8)
hsynz p1 -ldef run make with -p-1 -c-ldef-12 (run hsync_demo with -p-1)
hsynz p8 -ldef run make with -p-8 -c-ldef-12 (run hsync_demo with -p-8)
hsynz p1 -lgzip run make with -p-1 -c-lgzip-12 (run hsync_demo with -p-1)
hsynz p8 -lgzip run make with -p-8 -c-lgzip-12 (run hsync_demo with -p-8)
hsynz p1 -zstd run make with -p-1 -c-zstd-21-24 (run hsync_demo with -p-1)
hsynz p8 -zstd run make with -p-8 -c-zstd-21-24 (run hsync_demo with -p-8)

test result average:

Programcompressmake memspeedsync memmax memspeed
zsync52.94%1M353.9MB/s7M23M34MB/s
zsync -z20.67%1M14.8MB/s12M37M28MB/s
hsynz p151.05%5M2039.5MB/s5M19M307MB/s
hsynz p851.05%21M4311.9MB/s12M27M533MB/s
hsynz p1 zlib20.05%6M17.3MB/s6M22M273MB/s
hsynz p8 zlib20.05%30M115.1MB/s13M29M435MB/s
hsynz p1 gzip20.12%6M17.3MB/s6M22M268MB/s
hsynz p8 gzip20.12%30M115.0MB/s13M29M427MB/s
hsynz p1 ldef19.57%15M7.8MB/s6M22M272MB/s
hsynz p8 ldef19.57%96M57.0MB/s13M29M431MB/s
hsynz p1 lgzip19.64%15M7.9MB/s6M22M267MB/s
hsynz p8 lgzip19.64%96M56.9MB/s13M29M419MB/s
hsynz p1 zstd14.96%532M1.9MB/s24M34M264MB/s
hsynz p8 zstd14.95%3349M10.1MB/s24M34M410MB/s

input Apk Files for test:

case list:

appnewFile <-- oldFilenewSizeoldSize
1<img src="https://github.com/sisong/sfpatcher/raw/master/img/cn.wps.moffice_eng.png" width="36">cn.wps.moffice_eng_13.30.0.apk <-- 13.29.09590491894914262
2<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.achievo.vipshop.png" width="36">com.achievo.vipshop_7.80.2.apk <-- 7.79.9127395632120237937
3<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.adobe.reader.png" width="36">com.adobe.reader_22.9.0.24118.apk <-- 22.8.1.235872735143727087718
4<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.alibaba.android.rimet.png" width="36">com.alibaba.android.rimet_6.5.50.apk <-- 6.5.45195314449193489159
5<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.amazon.mShop.android.shopping.png" width="36">com.amazon.mShop.android.shopping_24.18.2.apk <-- 24.18.07632885876287423
6<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.baidu.BaiduMap.png" width="36">com.baidu.BaiduMap_16.5.0.apk <-- 16.4.5131382821132308374
7<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.dragon.read.png" width="36">com.dragon.read_5.5.3.33.apk <-- 5.5.1.324511265843518658
8<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.ebay.mobile.png" width="36">com.ebay.mobile_6.80.0.1.apk <-- 6.79.0.16120258761123285
9<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.eg.android.AlipayGphone.png" width="36">com.eg.android.AlipayGphone_10.3.0.apk <-- 10.2.96122073135119046208
10<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.google.android.apps.translate.png" width="36">com.google.android.apps.translate_6.46.0.apk <-- 6.45.04889296748843378
11<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.google.android.googlequicksearchbox.png" width="36">com.google.android.googlequicksearchbox_13.38.11.apk <-- 13.37.10190539272189493966
12<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.jingdong.app.mall.png" width="36">com.jingdong.app.mall_11.3.2.apk <-- 11.3.0101098430100750191
13<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.netease.cloudmusic.png" width="36">com.netease.cloudmusic_8.8.45.apk <-- 8.8.40181914846181909451
14<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.reddit.frontpage.png" width="36">com.reddit.frontpage_2022.36.0.apk <-- 2022.34.05020511947854461
15<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.sankuai.meituan.takeoutnew.png" width="36">com.sankuai.meituan.takeoutnew_7.94.3.apk <-- 7.92.27496589374833926
16<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.sankuai.meituan.png" width="36">com.sankuai.meituan_12.4.207.apk <-- 12.4.2059361373293605911
17<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.sina.weibo.png" width="36">com.sina.weibo_12.10.0.apk <-- 12.9.5156881776156617913
18<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.smile.gifmaker.png" width="36">com.smile.gifmaker_10.8.40.27845.apk <-- 10.8.30.27728102403847101520138
19<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.ss.android.article.news.png" width="36">com.ss.android.article.news_9.0.7.apk <-- 9.0.65444400353947221
20<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.ss.android.ugc.aweme.png" width="36">com.ss.android.ugc.aweme_22.6.0.apk <-- 22.5.0171683897171353597
21<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.taobao.taobao.png" width="36">com.taobao.taobao_10.18.10.apk <-- 10.17.0117218670117111874
22<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.tencent.mm.png" width="36">com.tencent.mm_8.0.28.apk <-- 8.0.27266691829276603782
23<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.tencent.mobileqq.png" width="36">com.tencent.mobileqq_8.9.15.apk <-- 8.9.13311322716310529631
24<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.tencent.mtt.png" width="36">com.tencent.mtt_13.2.0.0103.apk <-- 13.2.0.00459734274797296757
25<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.tripadvisor.tripadvisor.png" width="36">com.tripadvisor.tripadvisor_49.5.apk <-- 49.32874449828695346
26<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.twitter.android.png" width="36">com.twitter.android_9.61.0.apk <-- 9.58.23614184035575484
27<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.ubercab.png" width="36">com.ubercab_4.442.10002.apk <-- 4.439.100026992323264284150
28<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.ximalaya.ting.android.png" width="36">com.ximalaya.ting.android_9.0.66.3.apk <-- 9.0.62.3115804845113564876
29<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.xunmeng.pinduoduo.png" width="36">com.xunmeng.pinduoduo_6.30.0.apk <-- 6.29.13089683330951567
30<img src="https://github.com/sisong/sfpatcher/raw/master/img/com.youdao.dict.png" width="36">com.youdao.dict_9.2.29.apk <-- 9.2.28110624682110628778
31<img src="https://github.com/sisong/sfpatcher/raw/master/img/org.mozilla.firefox.png" width="36">org.mozilla.firefox_105.2.0.apk <-- 105.1.08307846483086656
32<img src="https://github.com/sisong/sfpatcher/raw/master/img/tv.danmaku.bili.png" width="36">tv.danmaku.bili_7.1.0.apk <-- 7.0.0104774723104727005

changed test Program:
zsync ... make -b 2048 changed to -b 1024
hsynz ... make -s-2k changed to -s-1k

test result average:

Programcompressmake memspeedsync memmax memspeed
zsync62.80%1M329.8MB/s6M12M76MB/s
zsync -z59.56%1M19.8MB/s8M19M56MB/s
hsynz p162.43%4M1533.5MB/s4M10M236MB/s
hsynz p862.43%18M2336.4MB/s12M18M394MB/s
hsynz p1 zlib58.67%5M22.7MB/s4M11M243MB/s
hsynz p8 zlib58.67%29M138.6MB/s12M19M410MB/s
hsynz p1 gzip58.95%5M22.6MB/s4M11M242MB/s
hsynz p8 gzip58.95%29M138.9MB/s12M19M407MB/s
hsynz p1 ldef58.61%14M23.7MB/s4M11M242MB/s
hsynz p8 ldef58.61%96M149.1MB/s12M19M413MB/s
hsynz p1 lgzip58.90%14M23.6MB/s4M11M240MB/s
hsynz p8 lgzip58.90%96M149.1MB/s12M19M405MB/s
hsynz p1 zstd57.74%534M2.7MB/s24M28M234MB/s
hsynz p8 zstd57.74%3434M13.4MB/s24M28M390MB/s

Contact

housisong@hotmail.com