简体   繁体   English

是否可以监视.Net的内部池大小?

[英]Is it possible to monitor .Net's intern pool size?

I'm maintaining a legacy application that uses strings to lock values in a cache. 我正在维护一个使用字符串锁定缓存中的值的旧版应用程序。 It does so something like this: 它是这样的:

object Cache(string key, Func<object> createObjToCache)
{
    object result = Get(key);
    if (result == null)
    {
        string internKey = string.Intern(key);
        lock (internKey) {
            result = Get(key);
            if (result == null)
            {
                result = createObjToCache();
                Add(key, result);
            }
        }
    }
    return result;
}

I've two questions about this code. 关于此代码,我有两个问题。 First is string.Intern() thread safe? 首先是string.Intern()线程安全吗? Is it possible that two threads on two separate CPUs with two identical strings would return different references? 两个单独的CPU上具有两个相同字符串的两个线程是否可能返回不同的引用? If not is that a possible bottle neck, does string.Intern block? 如果不是可能的瓶颈,string.Intern是否会阻塞?

Secondly I'm concerned that this application might be using a huge number of strings as keys. 其次,我担心此应用程序可能会使用大量字符串作为键。 I'd like to be able to monitor the amount of memory that the intern pool uses to store all these strings, but I can't find a performance counter for this on .Net Memory. 我希望能够监视内部缓冲池用来存储所有这些字符串的内存量,但是我无法在.Net Memory上找到用于此的性能计数器。 Is there one somewhere else? 还有其他地方吗?

NOTE: 注意:

I'm aware that this implementation sucks. 我知道这种实现很糟糕。 However I need to make the case to management before re-writing what they see as a critical bit of code. 但是,在重新编写他们认为关键的代码之前,我需要先向管理层提出理由。 Hence I could use facts and stats on exactly how bad it sucks rather than alternative solutions. 因此,我可以使用事实和统计数据来确定它到底有多糟,而不是其他解决方案。

Also Get() and Add() are not in the original code. 此外,Get()和Add()不在原始代码中。 I've replaced the original code to keep this question simple. 我已替换原始代码以使此问题保持简单。 We can assume that Add() will not fail if it is called twice with the same or different keys. 我们可以假设,如果使用相同或不同的键两次调用Add(),则不会失败。

MSDN does not make any mention of thread-safety on string.Intern , so you're right in that it is very undefined what would happen if two threads called Intern for a new key at exactly the same time. MSDN没有提到string.Intern上的线程安全,因此您说对了,因为如果两个线程同时调用一个Intern作为一个 key ,这将是非常不确定的。 I want to say "it'll probably work OK", but that isn't a guarantee. 我想说“它可能会正常工作”,但这不是保证。 There is no guarantee AFAIK. 无法保证AFAIK。 The implementation is extern , so peeking at the implementation means looking at the runtime itself. 实现是extern ,因此查看实现意味着查看运行时本身。

Frankly, there are so many reasons not to do this that it is hard to get excited about answering these specific questions. 坦白说,有许多理由不这样做,以至于很难回答这些具体问题。 I'd be tempted to look at some kind of Dictionary<string,object> or ThreadSafeDictionary<string,object> (where the object here is simply a new object() that I can use for the lock) - without all the issues related to string.Intern . 我很想看看某种Dictionary<string,object>ThreadSafeDictionary<string,object> (这里的object只是我可以用于锁定的一个new object() )- 没有所有相关的问题到string.Intern Then I can a: query the size, b: discard it at whim, c: have parallel isolated containers, etc. 然后我可以:a:查询大小,b:随意丢弃,c:具有并行隔离的容器,等等。

First is string.Intern() thread safe? 首先是string.Intern()线程安全吗?

Unless something has changed (my info on this is quite old, and I'm not curious enough to take a look at the current implementation), yes. 除非发生了什么变化(我对此的信息已经很老了,并且我不太好奇以了解当前的实现),否则可以。 This however is about the only good thing with this idea. 然而,这是关于这个想法的唯一好处。

Indeed, it's not fully a good thing. 确实,这并不是一件好事。 string.Intern() locks globally which is one of the things that can make it slow. string.Intern()全局锁定,这可能会使它变慢。

Secondly I'm concerned that this application might be using a huge number of strings as keys. 其次,我担心此应用程序可能会使用大量字符串作为键。

If that cache lives forever then that's an issue (or not if the memory use is sufficiently low) whether you intern or not. 如果该缓存永久存在,那么无论您是否实习,这都是一个问题(如果内存使用率足够低,则不是问题)。 In which case have the wrong approach to the right potential issue to investigate: 在这种情况下,应针对错误的潜在问题采取错误的方法进行调查:

I'd like to be able to monitor the amount of memory that the intern pool uses to store all these strings, 我希望能够监视内部缓冲池用来存储所有这些字符串的内存量,

If they weren't interned but still lived forever in that cache, then if you stopped interning, you'd still be the same that amount of memory for the strings themselves, and the extra memory overhead of the interning wouldn't really be the issue. 如果他们没有被实习,但仍然永久存在于该缓存中,那么如果您停止了实习,则字符串本身的内存量仍然是相同的,实习的额外内存开销实际上不是问题。

There are a few reasons why one might want to intern a key, and not all of them are even bad (if the strings being interned are going to all appear regularly throughout the lifetime of the application then interning could even reduce memory use), but it seems here that the reason is to make sure that the key locked on is the same instance that another attempt to use the same string would use. 人们可能有几个原因想要插入一个键,并且并非所有人都坏(如果要插入的字符串在应用程序的整个生命周期中都定期出现,则插入甚至可以减少内存使用),但是在这里看来,原因是要确保锁定的键与另一个尝试使用相同字符串的实例相同。

This might be thread safety at the wrong place, if Add() isn't thread-safe enough to guarantee that two simultaneous insertions of different keys can't put it into an invalid state (if Add() isn't explicitly thread-safe, then it does not make this guarantee). 如果Add()的线程安全性不足以保证两次同时插入不同的键不能将其置于无效状态(如果Add()不是明确的线程- Add() ,则这可能是错误的线程安全性。安全,则不能保证此权利。

If the cache is threadsafe, then this is likely extra thread safety for no good reason. 如果高速缓存是线程安全的,则没有充分的理由这可能是额外的线程安全。 Since objToCache has already been created and races will result in one being thrown away, it might be fine to let them race and have a brief period of two objToCache existing before one is collected. 由于已经创建了objToCache并且objToCache将导致其中一个被扔掉,因此最好让它们竞争并在收集一个之前短暂存在两个objToCache If not then MemoryCache.AddOrGetExisting or ConcurrentDictionary.GetOrAdd deal with this issue much better than this. 如果不是,那么MemoryCache.AddOrGetExistingConcurrentDictionary.GetOrAdd处理此问题的能力要比这好得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM