0

Delphi 6 には、可変サイズのデータ​​ ブロック (固定サイズのヘッダーの後にさまざまな量のデータが続く) を受け入れる「送信」ルーチンがあり、ルーチンは最終的に Winsock で sendto() を呼び出します。渡されたブロックが var である場合 (多少誤解を招きますが、機能します) と、ブロックへのポインターが渡される場合の 2 つの方法でコーディングしました。ベンチマークに使用される単純なバージョンは次のようになります。

type 
  header = record destination, serialnumber: integer end;
  pheader = ^header;

var
  smallblock: record h: header; data: array[1..5] of integer end;
  bigblock: record h: header; data: array[1..100] of integer end;

procedure send1(var h: header; size: integer);
begin
h.destination := 1; // typical header adjustments before sendto()
h.serialnumber := 2;
sendto(sock, h, size, 0, client, sizeof(client))
end;

procedure send2(p: pheader; size: cardinal);
begin
p^.destination := 1;
p^.serialnumber := 2;
sendto(sock, p^, size, 0, client, sizeof(client))
end;

procedure doit1;
begin
send1(smallblock.h, sizeof(smallblock));
send1(bigblock.h, sizeof(bigblock));
end;

procedure doit2;
begin
send2(@smallblock, sizeof(smallblock));
send2(@bigblock, sizeof(bigblock));
end;

「送信」ルーチンは、さまざまなブロック サイズで頻繁に呼び出されるため、できるだけ高速にする必要があります。単純なベンチマークを数回実行した後 (gettickcount を使用して呼び出しのタイミングを調整することにより)、私のマシンではポインター手法 (doit2) が var 手法 (doit1) よりも約 3% 高速に動作するように見えますが、実際の違いは見られません。オブジェクト コードの 2 つの手法の間で (私がアセンブラーの第一人者であるというわけではありません)。

3% は私の大まかなベンチマークによる錯覚ですか、それともポインター手法は実際に var 手法を打ち負かしていますか?

4

1 に答える 1

7

varパラメーターを渡す場合とポインター パラメーターを渡す場合のパフォーマンスの違いはありません。これらはまったく同じこと (メモリ アドレスを渡す) を行い、同一ではないにしても同様のアセンブリ コードにコンパイルします。したがって、ベンチマークの違いは、ベンチマーク対象のコードではなく、ベンチマーク自体の問題によって引き起こされる可能性があります。 GetTickCount()たとえば、最適なベンチマーク ツールとは言えません。コードの時間を測定する最善の方法は、AQTime などの外部プロファイラーを使用することです。

ところで、doit2()テストは代わりに次のようにする必要があります。

procedure doit2;
begin
  send2(@(smallblock.h), sizeof(smallblock));
  send2(@(bigblock.h), sizeof(bigblock));
end;
于 2013-04-18T01:16:41.300 に答える