Description
Summary of the issue
The method EFCoreSecondLevelCacheInterceptor.EFSqlCommandsProcessor.IsCrudCommand(String) is relatively slow in high performance scenarios with big commands that have several line breaks.
Probably because it first splits the entire string (var lines = text.Split('\n')) and then loop through them, even knowing that usually the CrudMarker will be present in the first couple of lines. The Split is probably the performance offender.
Also, my command is supposed to be ignored by using both SkipCachingCommands and SkipCacheInvalidationCommands, so I suspect the IsCrudCommand call could be bypassed. However I didn't investigate the order of events.
I'm attaching two alternative code suggestions, one for .NET 8 with the use of Span<> and another for .NET 4.6.2. Both code files were generated by ChatGPT o1-mini.
Thanks and regards.
Environment
.NET (Core) SDK version: .NET 8
Microsoft.EntityFrameworkCore version: 8.0.10
EFCoreSecondLevelCacheInterceptor version: 4.8.3
Database: PostgreSQL 16 (irrelevant)
Cache provider: in-memory
Example code/Steps to reproduce:
(run in a loop to measure performance)
const string sql =
"""
UPDATE table
SET
column0 = 'value0',
column1 = 'value1',
column2 = 'value2',
column3 = 'value3',
column4 = 'value4',
column5 = 'value5',
column6 = 'value6',
column7 = 'value7',
column8 = 'value8',
column9 = 'value9'
WHERE id = 1
AND condition0 = 'value0'
AND condition1 = 'value1'
AND condition2 = 'value2'
AND condition3 = 'value3'
AND condition4 = 'value4'
AND condition5 = 'value5'
AND condition6 = 'value6'
AND condition7 = 'value7'
AND condition8 = 'value8'
AND condition9 = 'value9'
""";
var efSqlCommandsProcessor = new EFSqlCommandsProcessor(new XxHash64Unsafe());
var isCrudCommand = efSqlCommandsProcessor.IsCrudCommand(sql);
Output:
Exception message:
Full Stack trace: