C# 铸造成本?
我在C# 铸造成本?,c#,caching,casting,C#,Caching,Casting,我在字典中有一个通过散列(ID)映射的键/值对,称为id2key\u值。您可以将其视为用行表示类似数据库的表的一种方法 我添加了一些助手函数,通过执行强制转换来简化一些基本数据类型的使用,如 public int GetInt(string id, string key) { int value = 0; bool success = int.TryParse(map[id][key], out value); if (success) return v
字典
中有一个通过散列(ID)映射的键/值对,称为id2key\u值。您可以将其视为用行表示类似数据库的表的一种方法
我添加了一些助手函数,通过执行强制转换来简化一些基本数据类型的使用,如
public int GetInt(string id, string key)
{
int value = 0;
bool success = int.TryParse(map[id][key], out value);
if (success)
return value;
else
throw new InvalidOperationException(
"Trying to obtain a non-integer value with GetInt().");
}
嗯,当我想到一个“强制缓存”的想法时,我觉得我很聪明,它基本上保存已经解析过的对象,所以我可以跳过对int、bool、DateTime等字符串的解析,直接从缓存中将它们强制转换成适当的数据类型。像
public int GetInt(string id, string key)
{
if (cast_cache.ContainsKey(id) && cast_cache[id].ContainsKey(key))
return (int) cast_cache[id][key];
int value = 0;
bool success = int.TryParse(map[id][key], out value);
if (success)
{
this.AddToCache(id, key, value);
return value;
}
else
throw new InvalidOperationException(
"Trying to obtain a non-integer value with GetInt().");
}
“强制转换缓存”只是字典
因此,我在地图上添加了10000个整数,进行了一些性能测试。然后我做了一百万次随机检索,有没有“强制缓存”
不使用缓存时需要495(毫秒),使用缓存时需要490(毫秒)。我还使用DateTime进行了一次测试,差异更大,但比我预期的要小(约750(ms)非缓存对约500(ms)缓存)
(显然)不了解强制转换的原理,该操作的成本有多高,以及为什么性能与从字符串“反序列化”的性能如此接近?强制转换的速度比大多数人想象的要快得多,因为您没有触及对象本身(您只是更改指向该对象的引用) 您应该避免强制转换的一个主要原因是,当您强制转换时,您避开了类型安全性,并在应用程序中引入了潜在的执行时间错误。我很少考虑铸件是一个性能问题。 作为补充说明,我将确保在缓存中测试引用类型和值类型,以确保不会因为装箱和取消装箱任何值类型而导致性能损失
装箱的性能损失来自这样一个事实:将值类型强制转换到对象并不涉及更改引用,因为值类型必须复制到堆中。此外,使用装箱值类型将取消装箱引用类型,然后将这些值从堆中再次复制到堆栈中。由于您没有触及对象本身(您只是更改指向该对象的引用),因此强制转换比大多数人想象的快得多 您应该避免强制转换的一个主要原因是,当您强制转换时,您避开了类型安全性,并在应用程序中引入了潜在的执行时间错误。我很少考虑铸件是一个性能问题。 作为补充说明,我将确保在缓存中测试引用类型和值类型,以确保不会因为装箱和取消装箱任何值类型而导致性能损失
装箱的性能损失来自这样一个事实:将值类型强制转换到对象并不涉及更改引用,因为值类型必须复制到堆中。此外,使用装箱值类型将取消装箱引用类型,然后将这些值从堆中再次复制到堆栈中。由于时间和空间之间的关系,您的示例运行得更快。如果继续缓存每个哈希类型,程序需要多少内存?由于时间和空间之间的关系,您的示例运行得更快。如果继续缓存每种哈希类型,程序需要多少内存?等等,您在代码中称为“强制转换”的不是强制转换 如果您正在这样做:
bool success = int.TryParse(map[id][key], out value);
这是一种转换,而不是演员阵容。演员阵容将是:
value = (int) map[id][key];
或
在这种情况下会失败,因为对象实际上是字符串,而不是int
如果你有一个
字典
,但你真的对在其中存储任意对象感兴趣,我会把它做成字典
。因此,您将能够使用强制转换而不是转换,正如Andrew Hare指出的那样,转换将快得多。等等,您在代码中所称的“强制转换”不是强制转换
如果您正在这样做:
bool success = int.TryParse(map[id][key], out value);
这是一种转换,而不是演员阵容。演员阵容将是:
value = (int) map[id][key];
或
在这种情况下会失败,因为对象实际上是字符串,而不是int
如果你有一个
字典
,但你真的对在其中存储任意对象感兴趣,我会把它做成字典
。因此,您将能够使用强制转换而不是转换,正如Andrew Hare指出的那样,转换将要快得多。如果减少字典查找的数量,您的代码在缓存中的执行速度可能会更快。此外,使缓存字典
而不是字典
将避免装箱和拆箱,这也会带来成本
public int GetInt(string id, string key)
{
int value;
Dictionary<string, int> cache;
if (cast_cache.TryGetValue(id, out cache)
&& cache.TryGetValue(key, out value))
{
return value;
}
if (int.TryParse(map[id][key], out value))
{
this.AddToCache(id, key, value);
return value;
}
throw new InvalidOperationException("Trying to obtain a non-integer value with GetInt().");
}
public int GetInt(字符串id,字符串键)
{
int值;
字典缓存;
if(cast_cache.TryGetValue(id,out cache)
&&cache.TryGetValue(键,输出值))
{
返回值;
}
if(int.TryParse(映射[id][key],输出值))
{
this.AddToCache(id、key、value);
返回值;
}
抛出新的InvalidOperationException(“尝试使用GetInt()获取非整数值”);
}
如果减少字典查找的数量,则代码在缓存中的执行速度可能会更快。此外,使缓存字典
而不是字典
将避免装箱和拆箱,这也会带来成本
public int GetInt(string id, string key)
{
int value;
Dictionary<string, int> cache;
if (cast_cache.TryGetValue(id, out cache)
&& cache.TryGetValue(key, out value))
{
return value;
}
if (int.TryParse(map[id][key], out value))
{
this.AddToCache(id, key, value);
return value;
}
throw new InvalidOperationException("Trying to obtain a non-integer value with GetInt().");
}
public int GetInt(字符串id,字符串键)
{
int值;
字典缓存;
if(cast_cache.TryGetValue(id,out cache)
&&cache.TryGetValue(键,输出值))
{
返回值;
}
if(int.TryParse(映射[id][key],输出值))
{
this.AddToCache(id、key、value);
返回值;
}
抛出新的InvalidOperationException(“尝试使用GetInt()获取非整数值”);
}
> > >在这里面有两件事要考虑。首先,我只是想告诉你