ALT Linux Team development discussions
 help / color / mirror / Atom feed
From: Alexey Tourbin <at@altlinux.ru>
To: devel@lists.altlinux.org
Subject: [devel] вопрос по языку Си - realloc & bit hacks
Date: Thu, 1 Oct 2009 08:03:51 +0400
Message-ID: <20091001040351.GM10769@altlinux.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 3014 bytes --]

lib/depends.c:
   213  static /*@exposed@*/ struct availablePackage *
   214  alAddPackage(availableList al,
   215                  Header h, /*@null@*/ /*@dependent@*/ const void * key,
   216                  /*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
   217          /*@modifies al, h @*/
   218  {
   219      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
   220      HFD_t hfd = headerFreeData;
   221      rpmTagType dnt, bnt;
   222      struct availablePackage * p;
   223      rpmRelocation * r;
   224      int i;
   225      int_32 * dirIndexes;
   226      const char ** dirNames;
   227      int numDirs, dirNum;
   228      int * dirMapping;
   229      struct dirInfo_s dirNeedle;
   230      dirInfo dirMatch;
   231      int first, last, fileNum;
   232      int origNumDirs;
   233      int pkgNum;
   234  
   235      if (al->size == al->alloced) {
   236          al->alloced += al->delta;
   237          al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
   238      }

Здесь в последних строках проверяется, достаточно ли места в массиве
al->list (перед вставкой нового элемента).  Если место кончилось, то
делается realloc "с запасом" al->delta.

Первый вопрос -- есть ли смысл таким образом избегать вызовов realloc.
А именно, резервирует ли realloc дополнительное место на случай
последующих вызовов.  Если это так, то здесь просто дублируется логика
realloc.

Второй вопрос -- как избавиться от дополнительных полей al->alloced
и al->delta.  Ясно, что наличие места в массиве можно проверять по
одному только полю al->size.  Например, если поле size кратно какому-то
числу, то при достижении кратности можно всякий раз увеличивать размер
на это число.  Это лучше всего делать со степенями двойки, потому что
в этом случае modulo заменятся на более дешёвый bitwise and.

	const int step = 8;
	if ((al->size & (step - 1) == 0)
		al->list = xrealloc(al->list,
			sizeof(*al->list) * (al->size + step));

Это получается арифметическая прогрессия -- размер массива всё время
увеличивается на step.  Можно сделать геометрическую прогрессию --
чтобы размер массива удваивался.

	static inline
	bool power_of_2(int x)
	{
		return (x & (x - 1)) == 0;
	}
	if (power_of_2(al->size))
		al->list = xrealloc(al->list,
			sizeof(*al->list) * (al->size << 1));

Существуют ли более оптимальный план для выделения памяти "с запасом"?
Ясно, что на больших размерах массива арифметическая прогрессия будет
расти слишком медленно.  С другой стороны, "удвоение" растёт слишком
быстро.  Хотелось бы размер массива не удваивать, а "уполторять" --
чтобы было 8, 12, 16, 24, 32, 64 и т.д,
т.е. 2^n, 2^n + 2^{n-1}, 2^{n+1}, ...

То есть алгоритм будет примерно такой

	if (полуторный_размер)
		realloc(двойной размер);
	else if (двойной размер)
		realloc(полуторный размер);

Может кто-нибудь знает как это можно попроще изобразить.  Или может
быть кто-нибудь видел как в других местах с realloc'ом поступают.

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

             reply	other threads:[~2009-10-01  4:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-01  4:03 Alexey Tourbin [this message]
2009-10-01  4:30 ` Александр Мыльцев

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=20091001040351.GM10769@altlinux.org \
    --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