SQL & CLR Base64 Conversion Performance
As a follow-up to my previous post I thought I would have a look at the performance of this type of conversion using the XML query and T-SQL type conversions versus the equivalent code written in C# and executed by the SQL CLR engine.
The first thing was to convert the code to the equivalent T-SQL functions:
CREATE FUNCTION ConvertToBase64SQL(@toEncode varchar(max)) RETURNS varchar(max)
AS
BEGIN
DECLARE @xml xml
DECLARE @bin varbinary(max)
SELECT @bin = CAST(@toEncode as varbinary(max))
SET @xml = (SELECT * FROM (SELECT @bin as data) as row FOR XML AUTO, BINARY BASE64)
RETURN @xml.value('(/row/@data)[1]', 'varchar(max)')
END
CREATE FUNCTION ConvertFromBase64SQL(@toDecode varchar(max)) RETURNS varchar(max)
AS
BEGIN
DECLARE @xml xml
DECLARE @bin varbinary(max)
SELECT @xml = CAST( '<row data="' + @toDecode + '" />' as xml )
SELECT @bin = @xml.value('(/row/@data)[1]', 'varbinary(max)')
RETURN CAST(@bin as varchar(max))
END
Secondly to create the equivalent code in C# and deploy this to the SQL instance:
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString ConvertToBase64CLR(SqlString toEncode)
{
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode.ToString());
SqlString returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString ConvertFromBase64CLR(SqlString toDecode)
{
byte[] DecodedBytes = System.Convert.FromBase64String(toDecode.ToString());
SqlString returnValue = System.Text.ASCIIEncoding.ASCII.GetString(DecodedBytes);
return returnValue;
}
Finally compare the performance:
DECLARE @Counter INT = 100000
DECLARE @Output varchar(max)
DECLARE @StartTime DateTime = GetDate()
WHILE @Counter > 0
BEGIN
SET @Output = dbo.ConvertFromBase64SQL(dbo.ConvertToBase64SQL('This is a small test message'));
SET @Counter = @Counter - 1
END
PRINT @Output
PRINT 1.0*DATEDIFF(MS,@StartTime,GetDate())/1000
-- 25.440000 seconds
DECLARE @Counter INT = 100000
DECLARE @Output varchar(max)
DECLARE @StartTime DateTime = GetDate()
WHILE @Counter > 0
BEGIN
SET @Output = dbo.ConvertFromBase64CLR(dbo.ConvertToBase64CLR('This is a small test message'));
SET @Counter = @Counter - 1
END
PRINT @Output
PRINT 1.0*DATEDIFF(MS,@StartTime,GetDate())/1000
-- 2.663000 seconds
The results indicate that whilst the C# CLR implementation is significantly faster, the benefit of this performance difference (almost 10 times faster) it would likely only have a real impact if there where a large number of documents being converted.
I have not run this test on any larger documents which may result in a different performance results.
I think the real point here is that today there are a number of ways of doing these types of operations and you need to keep your mind open and evaluate the performance of your chosen implementation.
<Gary>