All I can say is that in testing I've noticed that Dynamic arrays are much slower then pointer characters.
[pascal]procedure RunArray(A : Array of Byte);
var
I : Integer;
A : Array of byte;
begin
for I := 0 to Length(A) -1 do
DoSomething(A[I]);
end;[/pascal]

Compared to:[pascal]procedure RunPChar(PC : PChar);
begin
while PC^ <> #0 do
begin
DoSomething(PC^);
inc(PC);
end;
end;[/pascal]

I'll grant that the Length calculation takes time, but in the end it doesn't explain the difference. Of course if you really want to get apples to apples then you need something closer to the following (where the array is still slower due to the need to calculate the offset each time):

[pascal]procedure RunArray(A : Array of Byte; l : Integer);
var
I : Integer;
A : Array of byte;
begin
for I := 0 to l-1 do
DoSomething(A[I]);
end;[/pascal]

Compared to:[pascal]procedure RunPChar(PC : PChar; l : Integer);
var
i : Integer;
begin
for I := 0 to l-1 do
begin
DoSomething(PC^);
inc(PC);
end;
end;[/pascal]

The reason for the speed difference (as I sated just before the 2nd code blocks) is that any time you access a dynamic (or static) array the offsets need to be calculated. With a PChar the inc takes care of movement and no calculation is needed to determine offset.

One way around this would be to keep a pointer into the array and increment that pointer. But then, your back to using pointer math and why not just use PChar's to start with.