О производительности динамических массивов...

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

zub писал(а):строки какраз SetLength`ом не инятятся, в там только в конце 0 пишется, в середине мусор будет.
Я конечно же имел в виду массив строк(длинных).
Alex2013
долгожитель
Сообщения: 3211
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

zub писал(а):>>Классические массивы могут динамически менять размер?
а че нет? выделяешь память, копируешь старое, и не инитишь новое. какраз ка ты хочешь
Кстати да ! Указанная в начале размерность массива давно уже не мешает выходить за ее рамки.
( Кстати интересно почему? Раньше вроде нужно было специальный ключ ставить ({$R-} кажется ) )
Зы
Начал постепенно править старые скрины в темах . (Косяк не мой, а якобы "крик души хостеров" но мне всеравно стыдно...)
( Такое впечатление что это "заранее спланированная засада" сайт был в зоне .info и какое он отношение к печально известным событиям имеет совершенно непонятно... возможно что это вообще взлом совершенно ЧУЖОГО сервера . ) )
Последний раз редактировалось Alex2013 08.09.2022 09:06:51, всего редактировалось 1 раз.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Кстати да !
нет. так делать не надо. перевыделяешь память под массив
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

Кстати, если какие-то фичи стандартного динамического массива кажутся избыточными, теперь можно же замутить свой собственный вариант.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

Я себе давно сделал велосипед (не через managed record или что iskander подразумевает, а через ручную работу с RTTI и заголовком массива), который как раз в порядке багофичи не зануляет элементы (если они неуправляемые). Но мне это нужно было не потому, что я очень страдал от лишних занулений, а потому, что я очень страдал без универсальной поддержки capacity, и, в меньшей степени, потому, что вместо Push(x) предпочитаю Grow^ := x, особенно если хочется создать объект сразу на месте:

Код: Выделить всё

type
	Ary = type pointer; // Тип, к которому можно кастовать динамические массивы.

	AryHelper = type helper for Ary // Методы для работы с ними.
		...
		function Grow(typeInfo: pointer; var n: SizeUint): pointer;
	end;

	SomeType = record
		...
		procedure Setup(...);
	end;

var
	a: array of SomeType;
	na: SizeUint; // логическое количество элементов 'a'

begin
	na := 0;
	SomeType(Ary(a).Grow(TypeInfo(a), na)^).Setup(...);
	// Теперь na = 1, а length(a) — аналог capacity у TList и может быть больше.
end.
Преимущество этого варианта перед чем-нибудь вроде TFPGList в том, что для 20 массивов разных типов создаются 20 компактных записей RTTI, с которыми работают одни и те же функции (я не только и не столько про свои, сколько про встроенные fpc_dynarray_setlength и т. д.), а дженерик 20 раз продублирует весь свой код.
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

iskander писал(а): попробуйте проверить это предположение для строк, например.
зачем проверять если из определения и для них не надо...
Pchar - нулевой маркер часть самой строки.
Для всех остальных длина строки явно указывается в начале строки и все что лишнее отбрасывается при приведении типа...
Так что вообще нигде не нужно заполнение нулевыми битами...
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

Перешла икота на Федота.
При чем здесь PChar и нулевой маркер, речь же шла про динамические массивы, верно?
Вот вам пример для массива строк:

Код: Выделить всё

program test;

{$mode objfpc}{$h+}

uses
  SysUtils;

procedure StrArrayTest;
var
  StrArray: PString = nil;
  I: Integer;
const
  Len = 100;
begin
  GetMem(StrArray, Len * SizeOf(string));
  try
    FillChar(StrArray^, Len * SizeOf(string), 42); //замусорим выделенную память
    Initialize(StrArray^, Len); //если закомментировать Initialize(), оно брякнется
    for I := 0 to Len - 1 do
      StrArray[I] := I.ToString;
    WriteLn(StrArray[Len - 1]);
    Finalize(StrArray^, Len);   //если закомментировать Finalize(), 100 строк утекут
  finally
    FreeMem(StrArray);
  end;
end;

begin
  StrArrayTest;
  ReadLn;
end.
Аватара пользователя
Alexander
энтузиаст
Сообщения: 865
Зарегистрирован: 18.12.2005 18:10:00
Откуда: оттуда
Контактная информация:

Сообщение Alexander »

Работает. И именно быстрее. Только на что бы заменить PByteArray для снятия ограничение размера в type TByteArray = array [0..32767] of Byte; и warning при компиляции со значением больше 32767 ?

Код: Выделить всё

program project1;

{$mode objfpc}{$H+}

uses
{$IFDEF UNIX}
  cthreads,
     {$ENDIF}
  Classes,
  SysUtils { you can add units after this };

  var
  Ar: array of byte;
  P:  PByteArray;
  i,t : longint;
begin
  t := GetTickCount64;
  for i := 0 to 100000 do
  begin
    SetLength(Ar, 1000000);
    Ar[100] := 100;
    SetLength(Ar, 500);
    if Ar[100] <> 100 then writeln('error:SetLength');
    Ar[9] := 9;
    SetLength(Ar, 0);
  end;
  writeln(GetTickCount64 - t);
  t := GetTickCount64;
  for i := 0 to 100000 do
  begin
    GetMem(P, 1000000);
    (P^)[100000] := 100;
    ReallocMem(P, 500);
   if (P^)[100000] <> 100 then writeln('error:ReallocMem');
    (P^)[9] := 9;
    FreeMem(P);
  end;
  writeln(GetTickCount64 - t);
  readln;
end.

Код: Выделить всё

first@my:~/mysoft/testdynarr$ fpc t2.pas 
Free Pascal Compiler version 3.2.2 [2021/05/16] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling t2.pas
t2.pas(32,10) Warning: range check error while evaluating constants (100000 must be between 0 and 32767)
t2.pas(34,12) Warning: range check error while evaluating constants (100000 must be between 0 and 32767)
Linking t2
39 lines compiled, 0.4 sec
2 warning(s) issued

first@my:~/mysoft/testdynarr$ ./t2 
13923
12
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Только на что бы заменить PByteArray для снятия ограничение размера в type TByteArray = array [0..32767] of Byte; и warning при компиляции со значением больше 32767 ?
На PByte? И ещё P^ заменить на P
Аватара пользователя
Alexander
энтузиаст
Сообщения: 865
Зарегистрирован: 18.12.2005 18:10:00
Откуда: оттуда
Контактная информация:

Сообщение Alexander »

Спасибо !
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

Заменил во втором бенче встроенный динамический массив на вот эту самоделку и получил:

Код: Выделить всё

9079
12742320
19900

9079
12742320
19900
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>на вот эту самоделку и получил
там в основе классический массив
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

zub писал(а):там в основе классический массив
zub, можешь развить мысль?
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Заменил во втором бенче встроенный динамический массив на вот эту самоделку и получил:
а в этой самоделке в основе не динамический массив, а классический. выходит динамический массив вышел из теста
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

Да нет там никакого классического массива, это имитация динамического массива с GetMem/FreeMem под капотом.
Ответить