gpt4 book ai didi

c# - 内存缓存 .Net 4.0 性能测试 : astonishing result

转载 作者:太空狗 更新时间:2023-10-29 22:11:00 26 4
gpt4 key购买 nike

这个性能测试是错误的还是系统缓存正在以异常性能工作?

这是我的结果:
[13] 交互次数 100000 : 63 毫秒
[14] 交互次数 100000 : 139 毫秒
[12] 交互次数 100000 : 47 毫秒
[15] 交互次数 100000 : 44 毫秒
测试结束。

硬件:x86 系列 6 型号 23 步进 GenuineIntel ~2992 Mhz 3.327 MB,5.1.2600 Service Pack 3

using System;
using System.Collections.Generic;
using System.Runtime.Caching;
using System.Diagnostics;
using System.Threading;

namespace CacheNet40
{
public class CacheTest
{
private ObjectCache cache;

public CacheTest()
{
cache = MemoryCache.Default;
}

public void AddItem(CacheItem item, double span)
{
CacheItemPolicy cp = new CacheItemPolicy();
cp.SlidingExpiration.Add(TimeSpan.FromMinutes(span));

cache.Add(item, cp);
}
public Object GetItem(string key)
{
return cache.Get(key);
}
}

class Program
{
private static CacheTest Cache = new CacheTest();
private static string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!@$?_-";
private static int counter = 0;
private static readonly object locker = new object();

static string CreateRandomString(int passwordLength, int idx)
{
char[] chars = new char[passwordLength];
Random rd = new Random((int)DateTime.Now.Ticks + idx);

for (int i = 0; i < passwordLength; i++)
{
chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
}
return new string(chars);
}

private static void CacheAccessTes()
{
int span = 5;
string key;
string data;
int itens = 1000;
int interactions = 100000;
int cont = 0;
int index = 0;
List<string> keys = new List<string>();

lock (locker)
{
counter++;
}

cont = itens;

//populates it with data in the cache
do
{
key = CreateRandomString(127, Thread.CurrentThread.ManagedThreadId + cont);
keys.Add(key);

data = CreateRandomString(156000, Thread.CurrentThread.ManagedThreadId + cont + 1);

CacheItem ci = new CacheItem(key, data);
Cache.AddItem(ci, span);

cont--;
}
while (cont > 0);

cont = interactions;
index = 0;

//test readings
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
do
{
Object ci = Cache.GetItem(keys[index]);

ci = null;
index++;
if (index == itens)
{
index = 0;
}

cont--;
}
while (cont > 0);
stopWatch.Stop();

lock (locker)
{
counter--;
}

string outstring = String.Format("[{0}] number of interactions {1} : {2} milliseconds", Thread.CurrentThread.ManagedThreadId, interactions, stopWatch.ElapsedMilliseconds );
Console.WriteLine(outstring);
}

static void Main(string[] args)
{
for (int threads = 0; threads < 4; threads++)
{
Thread thread = new Thread(new ThreadStart(CacheAccessTes));
thread.Start();
}

Thread.Sleep(1000);

while (true)
{
lock (locker)
{
if (counter == 0) break;
}
Thread.Sleep(100);
}

Console.WriteLine("End of test.");
Console.ReadLine();
}
}
}

最佳答案

我刚刚在网上搜索有关 MemoryCache 性能的信息,并偶然发现了这个 SO 问题。我问自己为什么没有使用合适的基准库,所以我最终非常懒惰地编写了自己的基准(所有优秀的程序员都应该 :-) 并使用了令人难以置信的 BenchmarkDotNet库来检查这个类的行为有多好(或不好)。

首先是结果

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17134.706 (1803/April2018Update/Redstone4)
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
Frequency=1757813 Hz, Resolution=568.8887 ns, Timer=TSC
[Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3394.0
DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3394.0



| Method | N | Mean | Error | StdDev |
|------------------------------- |------ |----------:|----------:|----------:|
| FindDadosEmpInCache | 30000 | 231.40 ns | 0.4435 ns | 0.3703 ns |
| FindDataAtTheEnd | 30000 | 429.90 ns | 1.1490 ns | 1.0186 ns |
| FindDataInDictionary | 30000 | 24.09 ns | 0.2244 ns | 0.2099 ns |
| FindDataInConcurrentDictionary | 30000 | 29.66 ns | 0.0990 ns | 0.0926 ns |
| FindDataInHashset | 30000 | 16.25 ns | 0.0077 ns | 0.0065 ns |

现在一些解释......

我最感兴趣的是看看 MemoryCache 与具有数千个条目的哈希列表(DictionaryHashset...)相比有多快以及对这种“长”列表的最坏情况线性搜索。因此,我添加了一些额外的测试,并意识到虽然 MemoryCache 不如简单列表或并发列表快,但速度仍处于纳秒级。检索 30,000 长缓存项目列表中的项目甚至不需要一毫秒。

公平地说,MemoryCache 比那些简单的列表做得更多,因为它必须控制并发、项目过期/逐出等。我相信它对于所有类型的工作负载都足够快,但是如果你不需要它的附加功能,例如逐出策略,您最好坚持使用更简单的哈希列表实现。

另一方面,由于它比散列查找“慢”一个数量级,因此可能还有改进的余地。我想设计师们认为它已经足够好了,我有什么资格不同意 DOTNET 工程师的意见呢? :-)

这是基准程序的源代码:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;

namespace TestListPerformance
{
class Program
{
static void Main(string[] args) {
var summary = BenchmarkRunner.Run<BenchmarkMemoryCache>();
}
}

public class BenchmarkMemoryCache
{
[Params(30000)]
public int N { get; set; }
public string FindStr;
private IList<DadosEmp> data;
private Dictionary<string, DadosEmp> dict;
private ConcurrentDictionary<string, DadosEmp> concurrentDict;
private HashSet<DadosEmp> hashset;
private DadosEmp last;

[GlobalSetup]
public void BuildData() {
FindStr = N.ToString();
data = new List<DadosEmp>(N);
dict = new Dictionary<string, DadosEmp>(N);
concurrentDict = new ConcurrentDictionary<string, DadosEmp>();
hashset = new HashSet<DadosEmp>();
for (int i = 0; i <= N; i++) {
DadosEmp d;
data.Add(d = new DadosEmp {
Identificacao = i,
Pis = i * 100,
NumCartao = i * 1000,
Nome = "Nome " + i.ToString(),
});
MemoryCache.Default.Add(i.ToString(), d,
new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(30) });
dict.Add(i.ToString(), d);
concurrentDict.TryAdd(i.ToString(), d);
hashset.Add(d);
last = d;
}
}
[Benchmark]
public DadosEmp FindDadosEmpInCache() {
var f = (DadosEmp)MemoryCache.Default.Get(FindStr);
return f;
}
[Benchmark]
public DadosEmp FindDataAtTheEnd() {
var f = data.FirstOrDefault(e => e.NumCartao == N || e.Pis == N || e.Identificacao == N);
return f;
}
[Benchmark]
public DadosEmp FindDataInDictionary() {
var f = dict[FindStr];
return f;
}
[Benchmark]
public DadosEmp FindDataInConcurrentDictionary() {
var f = concurrentDict[FindStr];
return f;
}
[Benchmark]
public bool FindDataInHashset() {
return hashset.Contains(last);
}

}

public class DadosEmp : IEquatable<DadosEmp>
{
public const string BIO_EXCLUSAO = "xbio";

public DadosEmp() {
Biometrias = new List<string>();
}
public long Identificacao { get; set; }
public long Pis { get; set; }
public long NumCartao { get; set; }
public string Nome { get; set; }
public int VersaoBio { get; set; }
public string Unidade { get; set; }
public IList<string> Biometrias { get; set; }
public string Biometria { get; set; }
public bool ExcluirBiometria { get { return Biometria == BIO_EXCLUSAO; } }
public DateTime DataEnvioRep { get; set; }
public string SenhaTeclado { get; set; }
public bool ExigeAutorizacaoSaida { get; set; }
public bool BioRepPendente { get; set; }
public override bool Equals(object obj) {
DadosEmp e = obj as DadosEmp;
if (ReferenceEquals(e, null))
return false;
return Equals(e);
}
public bool Equals(DadosEmp e) {
if (ReferenceEquals(e, null))
return false;
return e.Pis == this.Pis;
}
public override int GetHashCode() {
return Pis.GetHashCode();
}
public override string ToString() {
return string.Format("{0} ({1} - {2})", Nome, Pis, Identificacao);
}
}
}

关于c# - 内存缓存 .Net 4.0 性能测试 : astonishing result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11729023/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com