ALT Linux Team development discussions
 help / color / mirror / Atom feed
From: Alexey Tourbin <at@altlinux.ru>
To: ALT Linux Team development discussions <devel@lists.altlinux.org>
Subject: [devel] rsync_roll
Date: Sun, 25 May 2008 22:30:39 +0400
Message-ID: <20080525183039.GH7996@solemn.turbinal> (raw)
In-Reply-To: <6062a6e60805250131w7de349fqde0064d3e8a1d97d@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 2574 bytes --]

On Sun, May 25, 2008 at 12:31:24PM +0400, Alexander Bokovoy wrote:
> Патч, который брал ты, он отличается от рекомендуемого
> http://ozlabs.org/~rusty/gzip.rsync.patch2, на который ссылаются как
> Джефф, так и Эгмонт.

Что делает этот патч?  Почему "это работает"?
Прошу подсказать, правильно ли я понимаю это дело или нет.

Этот патч оперирует на входном (несжатом) потоке байтов
|--------------------------------------------------------->

Вычисляется "контрольная сумма" (с переполнением) "окна"
размером RSYNC_WIN байтов входного потока.

|--------------------------------------------------------->
   |___________|
     RSYNC_WIN

При добавлении каждого нового байта окно "сдвигается" и вычисляется
новая сумма.

|--------------------------------------------------------->
    -|__________+|
       RSYNC_WIN

Особенность вычисления этой суммы состоит в том, что достаточно
вычесть старый "выбывший" элемент (слева, отмечен знаком минус)
и добавить новый элемент (отмечен знаком плюс).

Когда сумма принимает определённое значение (а именно, когда
sum % RSYNC_WIN == 0) то в конце окна принимается решение
"сборосить блок" и заново инициализировать процедуру сжатия.

|--------------------------------------------------------->
     |_____0_____|
       RSYNC_WIN  \
       		   `reset compression here!
                
Это означает, что в этой точке как бы начинается "новый файл",
который gzip будет жать отдельно; если в двух разных входных
потоках в точке обнуления суммы несжатые данные идут одинаковые,
то и сжатые данные пойдут одинаковые.

Я всё равно плохо понимаю, почему "это работает", то есть как это
способствует повышению rsyncability.

Теперь дальше вопрос, что делает gzip при обнулении суммы?
Он полностью записывает блок?  Но ведь нормальный размер блока 32K,
а размер окна 4K.  Поскольку любое значение суммы по модулю 4096
можно считать равновероятным, то, выходит, что вместо блока 32K
gzip будет делать блоки в среднем по 4K.  Или нет?

Чтобы понять, как работет этот код, мне нужно пере-реализовать его
без привязки к гзипу.  Я приложил файл rsyncable.с, в котором попытался
воспроизвести то, о чём идёт речь.

$ ./rsyncable </etc/info-dir
sync at 4920
sync at 19949
sync at 24300
sync at 31782
sync at 44390
sync at 50260
sync at 68705
sync at 80677
sync at 85097
$ du -bk /etc/info-dir
84      /etc/info-dir
$ 

Из этого видно, что на самом деле размер блока в данном случае
получается примерно 8K (9 синков = 10 блоков на 84Кб), а не 4,
как я ожидал.  В чём тут дело?

[-- Attachment #1.2: rsyncable.c --]
[-- Type: text/plain, Size: 909 bytes --]

#include <stdint.h>
#include <stdbool.h>

#define RSYNC_WIN 4096

struct rsync_state {
	uint64_t n;			/* number of elements in the window */
	uint64_t sum;			/* current sum */
	unsigned char win[RSYNC_WIN];	/* window elements */
};

static inline
bool rsync_next(struct rsync_state *s, unsigned char c)
{
	if (s->n < RSYNC_WIN) {		/* not enough elements */
		s->sum += c;		/* update the sum */
		s->win[s->n++] = c;	/* remember the element */
		return false;		/* no match */
	}
	int i = s->n++ % RSYNC_WIN;	/* wrap up */
	s->sum -= s->win[i];		/* move the window on */
	s->sum += c;
	s->win[i] = c;
	if (s->sum % RSYNC_WIN == 0) {	/* match */
		s->n = 0;		/* reset */
		s->sum = 0;
		return true;
	}
	return false;
}

#include <stdio.h>

int main()
{
	struct rsync_state rs = { 0, 0 };
	int c;
	while ((c = getc(stdin)) != EOF)
		if (rsync_next(&rs, c))
			printf("sync at %ld\n", ftell(stdin));
	return 0;
}

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

  parent reply	other threads:[~2008-05-25 18:30 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-24 14:21 [devel] rpm: LZMA payload compression Alexey Tourbin
2008-05-24 14:20 ` Andrey Rahmatullin
2008-05-24 14:32   ` Alexey Tourbin
2008-05-25  0:01     ` Dmitry V. Levin
2008-05-24 14:51 ` Alexander Bokovoy
2008-05-24 15:35   ` Alexey Tourbin
2008-05-24 15:45     ` Alexey Tourbin
2008-05-24 15:53     ` Alexander Bokovoy
2008-05-24 15:58       ` Andrey Rahmatullin
2008-05-24 16:09         ` Alexander Bokovoy
2008-05-24 16:02       ` Alexander Bokovoy
2008-05-24 16:37       ` Alexey Tourbin
2008-05-24 17:55         ` Alexander Bokovoy
2008-05-24 19:16           ` Alexey Tourbin
2008-05-25  6:55           ` [devel] [JT] " Alexey Tourbin
2008-05-25  7:10             ` Alexander Bokovoy
2008-05-25  7:24               ` Alexey Tourbin
2008-05-25  7:27                 ` Alexander Bokovoy
2008-05-25  0:11         ` [devel] rsync mirrors Dmitry V. Levin
2008-05-25  6:03           ` Alexey Tourbin
2008-05-25  7:54       ` [devel] gzip --rsyncable Alexey Tourbin
2008-05-25  8:08         ` Alexander Bokovoy
2008-05-25  8:18           ` Alexey Tourbin
2008-05-25  8:31             ` Alexander Bokovoy
2008-05-25  8:48               ` Alexander Bokovoy
2008-05-25 11:35               ` Alexey Tourbin
2008-05-25 18:30               ` Alexey Tourbin [this message]
2008-05-25 18:38                 ` [devel] rsync_roll Alexander Bokovoy
2008-05-25 20:11                 ` Alexander Myltsev
2008-05-26  7:15                   ` Alexey Tourbin
2008-05-26  8:38                     ` Alexey Tourbin
2008-05-25  8:09         ` [devel] gzip --rsyncable Led
2008-05-25  8:27         ` Alexey Tourbin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080525183039.GH7996@solemn.turbinal \
    --to=at@altlinux.ru \
    --cc=devel@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git