Delphi memory manager is very fast and for small block allocation it has some parallelism built in. I measured IntToStr(-1583749570) at 17ns, CopyIntegerToWideBuffer(-1583749570, Buffer) at 13ns and the version in System.SysUtils without string allocation 7ns. All numbers in nano seconds. Example code below:
const
CTwoDigitLookup : packed array[0..99] of array[0..1] of Char =
('00','01','02','03','04','05','06','07','08','09',
'10','11','12','13','14','15','16','17','18','19',
'20','21','22','23','24','25','26','27','28','29',
'30','31','32','33','34','35','36','37','38','39',
'40','41','42','43','44','45','46','47','48','49',
'50','51','52','53','54','55','56','57','58','59',
'60','61','62','63','64','65','66','67','68','69',
'70','71','72','73','74','75','76','77','78','79',
'80','81','82','83','84','85','86','87','88','89',
'90','91','92','93','94','95','96','97','98','99');
function DivBy100(i: Cardinal): Cardinal;
{$IF Defined(WIN32)}
asm
MOV ECX, 1374389535 // 1/100 * 2^(32+5)
MUL ECX
MOV EAX, EDX
SHR EAX, 5
end;
{$ELSEIF Defined(WIN64))}
asm
MOV EAX, ECX
IMUL RAX, RAX, 1374389535
SHR RAX, 37
end;
{$ELSE}
inline;
begin
Result := i div 100;
end;
{$ENDIF}
{$R-}
{$Q-}
{$POINTERMATH ON}
function Int32ToWideBuffer(const AValue: Int32; ABuffer: PChar): Integer;
var
LVal, LRemainder: UInt32;
LDigits: Integer;
LNegative: Boolean;
begin
LVal := Abs(AValue);
if LVal >= 10000 then
if LVal >= 1000000 then
if LVal >= 100000000 then
LDigits := 9 + Byte(Ord(LVal >= 1000000000))
else
LDigits := 7 + Byte(Ord(LVal >= 10000000))
else
LDigits := 5 + Byte(Ord(LVal >= 100000))
else
if LVal >= 100 then
LDigits := 3 + Byte(Ord(LVal >= 1000))
else
LDigits := 1 + Byte(Ord(LVal >= 10));
LNegative := AValue < 0;
ABuffer^ := '-';
Inc(ABuffer, Ord(LNegative));
Result := LDigits;
Inc(Result, Ord(LNegative));
while LDigits > 1 do
begin
LRemainder := LVal;
LVal := DivBy100(LVal);
Dec(LRemainder, LVal * 100);
Dec(LDigits, 2);
PCardinal(@ABuffer[LDigits])^ := Cardinal(CTwoDigitLookup[LRemainder]);
end;
if LDigits <> 0 then
ABuffer^ := Char(LVal or Ord('0'));
end;