особенности реализации архитектуры? мне кажется среднее как раз в 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 окажется очень шустрым языком :)