字符串比较的并行优化

本文关键字:优化 并行 比较 字符串 | 更新日期: 2023-09-27 18:21:17

我正试图优化用作数据库查询缓存的字典的每个字符串键的字符串比较操作的性能。当前代码看起来像:

public void Clear(string tableName)
{
    foreach (string key in cache.Keys.Where(key => key.IndexOf(tableName, StringComparison.Ordinal) >= 0).ToList())
    {
        cache.Remove(key);
    }
}

我是使用C#并行功能的新手,我想知道将其转换为并行操作的最佳方法是什么,这样可以"同时"进行多个字符串比较。缓存通常会变得相当大,因此使用Clear()对其进行维护可能会非常昂贵。

字符串比较的并行优化

cache对象设为ConcurrentDictionary,并使用TryRemove而不是Remove

这将使您的缓存线程安全;然后,可以调用当前的foreach循环,如下所示:

Parallel.ForEach(cache.Keys, key =>
{
    if(key.IndexOf(tableName, StringComparison.Ordinal) >= 0)
    {
        dynamic value; // just because I don't know your dictionary.
        cache.TryRemove(key, out value);
    }
});

希望这能给你一个起点。

您的方法在Dictionary<string, Whatever>上不能很好地工作,因为该类对多个编写器来说不是线程安全的,因此同时删除可能会导致各种问题。

因此,您必须使用锁来同步删除,这将使对字典的访问基本上是单线程的。唯一可以安全地同时跨线程执行的操作是Where中的比较。

您可以使用ConcurrentDictionary,因为它使用条带锁可以减少这种影响。不过,这似乎仍然不是最好的方法。

如果您从字符串构建密钥,以便测试密钥是否以子密钥开始,并且如果经常需要删除整个子密钥,那么您可以尝试使用Dictionary<string, Dictionary<string, Whatever>>。添加或更新变得有点昂贵,但清除变成了从更高级别的字典中只删除一个值的O(1)。

我以前使用过Dictionaries作为缓存,我过去所做的是"动态"清理缓存,也就是说,每个条目都包含其包含时间,然后每当请求条目时,我都会删除旧条目。对我来说,性能打击很小,但如果需要,您可以实现一个Queue(属于Tuple<DateTime, TKey>,其中TKey是字典上键的类型)作为索引来保存这些时间戳,这样您就不需要每次迭代整个字典。无论如何,如果您必须考虑这些问题,那么是时候考虑使用专用缓存服务器了。对我来说,共享缓存(http://sharedcache.codeplex.com)已经足够好了。