особенности реализации архитектуры? мне кажется среднее как раз в 5 раз медленнее.
Это же беда. Замедление в 7 раз на одной из целевых архитектур — веская причина не использовать -Cr
мне кажется, в этом примере не хватает кода с инициализаций и передачей параметра непосредственно в функцию.
Да пожалуйста:
- Код: Выделить всё
{$MODE OBJFPC}
type
generic TOpenArrayOf<T> = object
public type
P = ^T;
public
Elements: P;
Length: LongInt;
function Get(aElements: P; aLength: LongInt): TOpenArrayOf; static; inline;
end;
TOpenArrayOfLongInt = specialize TOpenArrayOf<LongInt>;
var
A: array[0..3] of LongInt;
O: TOpenArrayOfLongInt;
function TOpenArrayOf.Get(aElements: P; aLength: LongInt): TOpenArrayOf;
begin
Result.Elements := aElements;
Result.Length := aLength;
end;
{$I-}
procedure PrintLast(const X: array of LongInt); overload;
begin
Writeln(X[Length(A) - 1]);
end;
procedure PrintLast(X: TOpenArrayOfLongInt); overload;
begin
Writeln(X.Elements[X.Length - 1]);
end;
begin
A[3] := 99;
PrintLast(A);
PrintLast(TOpenArrayOfLongInt.Get(@A[0], 4));
end.
fpc -al -O3
- Код: Выделить всё
# [37] PrintLast(A);
movl $U_$P$PROGRAM_$$_A,%eax
movl $3,%edx
call P$PROGRAM_$$_PRINTLAST$array_of_LONGINT
# [38] PrintLast(TOpenArrayOfLongInt.Get(@A[0], 4));
movl $U_$P$PROGRAM_$$_A,%eax
movl %eax,(%esp)
movl $4,4(%esp)
movl %esp,%eax
call P$PROGRAM_$$_PRINTLAST$TOPENARRAYOF$1$CRC31B95292
Больше на пару инструкций.
ну и непосредственно вызов fpc_write_text_sint, занимает с дженериком чуть больше инструкций
Не понял: и там, и там есть вызов fpc_write_text_sint, но в функции для открытого массива инструкций суммарно больше. Что такое «непосредственный вызов fpc_write_text_sint»?
а строки, это не динамическое в язык, о котором заботиться компилятор? а почему дин-массивы не работают как строки (copy-on-write)?
Так почему динамический массив должен быть обязательно RefCounted? Почему для него особая честь в сравнении с другими коллекциями? Почему TList не RefCounted, например, это недоработка или как? Действительно, почему динамические массивы не работают как строки? Не должен ли TList тоже работать как строки?
Со строками как таковыми всё понятно — копирование строки является частым явлением, которое хочется оптимизировать, подсчёт ссылок — оправданное решение для них. Какое объяснение про концепцию «динамический массив», зачем ей подсчёт ссылок?
а я не согласен, что через жопу. Всего 2 метода добавляется, а QueryInterface можно игнорировать. И вот пожалуйста - полноценная ARC система, можно отрабатывать концепцию сколько влезет.
Эти два метода неявно впендюриваются ВЕЗДЕ, значительно добавляя время работы.
Вот ещё тест:
- Код: Выделить всё
{$MODE OBJFPC}
uses
SysUtils;
type
IObj1 = interface
function X: LongInt;
end;
IObj2 = interface
function I: IObj1;
end;
TObj1 = class{$IFDEF USE_INTERFACE}(TInterfacedObject, IObj1){$ENDIF}
private
I: LongInt;
public
constructor Create;
function X: LongInt;
end;
TObj2 = class{$IFDEF USE_INTERFACE}(TInterfacedObject, IObj2){$ENDIF}
private
FObj1: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
public
constructor Create;
function I: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
end;
constructor TObj1.Create;
begin
I := 0;
end;
function TObj1.X: LongInt;
begin
Result := I;
Inc(I);
end;
constructor TObj2.Create;
begin
FObj1 := TObj1.Create;
end;
function TObj2.I: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
begin
Result := FObj1;
end;
var
Obj2: {$IFDEF USE_INTERFACE}IObj2{$ELSE}TObj2{$ENDIF};
I: LongInt;
t : tdatetime;
k : integer;
n : integer;
begin
t:=now;
Obj2 := TObj2.Create;
for I := 0 to 1024 * 1024 * 1024 do
if I > Obj2.I.X then
Break;
t:=now-t;
Writeln(Obj2.I.X);
writeln('time: ',round( t*MSecsPerDay),'mls');
end.
Запуски:
* Windows 7, i5 2.53Gh 64x,
fpc -O3 3.0.0rc1 —
4340mls (время работы примерно соответствует ожиданиям на 2.5ГГц процессоре)
* Windows 7, i5 2.53Gh 64x,
fpc -O3 -dUSE_INTERFACE 3.0.0rc1 —
36029mls (интерфейсы замедлили прогу в 9 раз)
С такими подходами (в 5 раз «средние по больнице» потери на Range Check, в 9 раз на COM-интерфейсах и т.д.) и Java окажется очень шустрым языком :)