2009-09-22

Hex to string - speed test

I recently wrote a function to parse JSON strings and part of that had to deal with converting a hex string to its string value. I decided to Google to see what other people had done. I found several posts but they used XML or a LIKE statements, which would seem to be a slow. Since binary is the fastest database collation, would binary logic be faster?

Test 1, Using LIKE
DECLARE @InputString nvarchar(max)='0x0061'
,
@hex varchar(255), @value nvarchar(max)
,
@w int, @max int= 10000
, @StartTime datetime2, @EndTime datetime2
SELECT
@hex = SUBSTRING(@InputString, 3, 4)
SELECT @w = 1, @StartTime =GETDATE()

WHILE @w < @max
BEGIN

SELECT @value =
CAST(CASE WHEN SUBSTRING(@hex, 1, 1) LIKE'[0-9]'
THEN CAST(SUBSTRING(@hex, 1, 1) AS INT)
ELSE
CAST(ASCII(UPPER(SUBSTRING(@hex, 1, 1)))-55 AS int)
END * 4096
+ CASE WHEN
SUBSTRING(@hex, 2, 1) LIKE'[0-9]'
THEN CAST(SUBSTRING(@hex, 2, 1) AS INT)
ELSE
CAST(ASCII(UPPER(SUBSTRING(@hex, 2, 1)))-55 AS INT)
END * 256
+ CASE WHEN SUBSTRING(@hex, 3, 1)LIKE'[0-9]'
THEN CAST(SUBSTRING(@hex, 3, 1) AS INT)
ELSE
CAST(ASCII(UPPER(SUBSTRING(@hex, 3, 1)))-55 AS INT)END * 16
+ CASE WHEN SUBSTRING(@hex, 4, 1) LIKE'[0-9]'
THEN
CAST(SUBSTRING(@hex, 4, 1) AS INT)
ELSE
CAST(ASCII(UPPER(SUBSTRING(@hex, 4, 1)))- 55 AS int)
END AS binary(1))

SELECT @w += 1
END

SELECT @EndTime =GETDATE()

SELECT @value AS 'Value', @w AS 'Iterations', DATEDIFF(millisecond, @StartTime, @EndTime)AS 'Diff'

Result 1
Time = 90 milliseconds for 10000 iterations

Test 2, Using Binary
DECLARE @InputString nvarchar(max) = '0x0061'
, @btmp varbinary(255), @value nvarchar(max)
, @w int, @max int = 10000
, @StartTime datetime2, @EndTime datetime2

SELECT @btmp = CONVERT(varbinary(8),
SUBSTRING(@InputString, 3, 4), 0) -- get hex value

SELECT @w = 1, @StartTime = GETDATE()

WHILE @w < @max
BEGIN

SELECT @value = NCHAR(
(CAST(SUBSTRING(@btmp, 1, 1) AS int)
- CASE WHEN (SUBSTRING(@btmp, 1,1))<= 0x39 THEN 48
WHEN (SUBSTRING(@btmp, 1, 1))<= 0x5A THEN 55
ELSE 87 END) * 4096
+ (CAST(SUBSTRING(@btmp, 3, 1) AS int)
- CASE WHEN (SUBSTRING(@btmp, 3, 1))<= 0x39 THEN 48
WHEN (SUBSTRING(@btmp, 3, 1))<= 0x5A THEN 55
ELSE 87 END) * 256

+ (CAST(SUBSTRING(@btmp, 5,1) AS int)
- CASE WHEN (SUBSTRING(@btmp, 5,1))<= 0x39 THEN 48
WHEN (SUBSTRING(@btmp, 5,1))<= 0x5A THEN 55
ELSE 87 END) * 16

+ (CAST(SUBSTRING(@btmp, 7,1)AS int)
- CASE WHEN (SUBSTRING(@btmp, 7,1))<= 0x39 THEN 48
WHEN (SUBSTRING(@btmp, 7,1))<= 0x5A THEN 55
ELSE 87 END)
)

SELECT @w += 1
END

SELECT @EndTime =GETDATE()

SELECT @value AS 'Value', @w AS 'Iterations'
, DATEDIFF(millisecond, @StartTime, @EndTime)AS 'Diff'

Result 2
Time = 63 milliseconds for 10000 iterations

The tests show that the binary logic method is much faster than other methods. Check out using binary or bit logic in your code for speed improvement.

No comments:

Post a Comment