为什么我应该在C#中使用int而不是字节或short


73

我发现了一些有关此问题的话题。即使字节或smallint可以处理数据,除非它是移动应用程序,否则大多数人似乎更喜欢在整个C#代码中使用int。我不明白为什么。将C#数据类型定义为与数据存储解决方案中相同的数据类型是否更有意义?

我的前提:如果我使用类型化的数据集,Linq2SQL类,POCO(一种或另一种),如果我不使我的数据类型在各层之间保持同步,则会遇到编译器数据类型转换问题。我真的不喜欢做System.Convert,只是因为在c#代码中使用int更加容易。我一直使用所需的最小数据类型来处理数据库以及代码中的数据,以保持与数据库的接口整洁。因此,我敢打赌我的C#代码中有75%是使用字节或短整数而不是整数,因为这就是数据库中的内容。

可能性:这是否意味着大多数只将int用于代码中所有内容的人也将int数据类型用于其sql存储数据类型,并且可能不太在乎数据库的整体大小,还是在适用的情况下对代码进行system.convert?

我为什么在乎:我永远都在工作,我只想熟悉最佳实践和标准编码约定。


最初的问题给人的印象是,我在问是否有任何理由应该避免使用byte或smallint来支持int。我真的想知道为什么在那些数据类型足够时在所有地方都使用int而不是byte或smallint更好。
面包车

因此,如果您同意在所有地方都使用int,我想知道有什么好处,更好的性能,没有转换,为什么我应该在所有地方都使用int
Breadtruck

Answers:


96

从性能角度来看,int在几乎所有情况下都更快。CPU被设计为以32位值有效工作。

较短的值很难处理。例如,要读取单个字节,CPU必须读取包含该字节的32位块,然后屏蔽掉高24位。

要写入一个字节,它必须读取目标32位块,用所需的字节值覆盖低8位,然后再次写回整个32位块。

当然,从空间角度来看,您可以使用较小的数据类型节省一些字节。因此,如果您要构建一个包含几百万行的表,那么较短的数据类型可能值得考虑。(这也许是为什么应该在数据库中使用较小的数据类型的一个很好的理由)

而且从正确的角度来看,int不会轻易溢出。如果您认为您的值将适合一个字节,然后在将来的某个时候对代码进行一些无害的更改,意味着将更大的值存储在其中,该怎么办?

这些就是为什么int应该是所有整数数据的默认数据类型的一些原因。仅当您实际要存储机器字节时才使用字节。仅在处理实际指定16位整数值的文件格式或协议或类似格式时,才使用短裤。如果您通常只处理整数,则将它们设置为整数。


3
我应该long默认在64位计算机上使用吗?(如果您有兴趣,请看一下这个问题
Alexander Malakhov

2
@亚历山大:可能不是。至少在x86上,至少不是32位仍然是最佳的“默认”选择(64位指令更长,并且使用更大的值可获得更多的内存流量)。如果您将.NET移植到没有专用32位指令或它们的速度明显慢的体系结构,那么..谁知道。进行基准测试,看看最有效的方法。;)
jalf

2
@亚历山大:是和不是。这不仅取决于可用的寄存器大小,还取决于它们的实现效率,以及它们如何与内存总线宽度和其他因素一起发挥作用。现代CPU的设计假设是大多数整数均为32位宽,并尝试针对这种情况进行优化。如果您绝对需要压缩每个性能的最后一个时钟周期,请对其进行基准测试。在特定情况下,较小的变量大小可能是值得的。
jalf

4
好吧,随时使用long。没有任何伤害。但是您不能始终如一地这样做,因为大多数.NET(或Java)APIint几乎在所有地方都使用。因此,您可能需要使用比其他方式更多的强制转换来填充代码。
jalf

2
我想补充一点,“ CPU设计为以32位值有效工作”是比int32短的整数类型甚至没有中间语言的算术支持的原因(例如b ++,其中b是字节实际上是int tmp = b; tmp ++; b =(byte)tmp;)
Aloraman

26

我只迟了6年,但也许我可以帮助别人。

这是我会使用的一些准则:

  • 如果有可能将来无法容纳该数据,请使用较大的int类型。
  • 如果将该变量用作struct / class字段,则默认情况下将对其进行填充以占用整个32位,因此使用byte / int16将不会节省内存。
  • 如果变量寿命很短,那么(就像在函数内部一样),较小的数据类型将无济于事。
  • 有时,“字节”或“字符”可以更好地描述数据,并且可以进行编译时间检查以确保在意外情况下不会为其分配较大的值。例如,如果使用字节存储月份中的一天(1-31)并尝试为其分配1000,则将导致错误。
  • 如果在大约100或更多的数组中使用变量,则我会使用较小的数据类型,只要它有意义。
  • byte和int16数组不像int(基元)那样具有线程安全性。

没有人提出的一个话题是有限的CPU缓存。较小的程序比较大的程序执行得更快,因为CPU可以将更多的程序容纳在更快的L1 / L2 / L3高速缓存中。

使用int类型可以导致更少的CPU指令,但是这也将迫使更高百分比的数据内存不适合CPU缓存。指令执行起来很便宜。现代的CPU内核每个时钟周期可以执行3-7条指令,但是另一方面,单个高速缓存未命中可能要花费1000-2000个时钟周期,因为它必须一直到RAM。

保存内存后,由于它不会从缓存中挤出,因此还可以使应用程序的其余部分更好地运行。

我做了一个快速总和测试,使用字节数组和int数组按随机顺序访问随机数据。

const int SIZE = 10000000, LOOPS = 80000;
byte[] array = Enumerable.Repeat(0, SIZE).Select(i => (byte)r.Next(10)).ToArray();
int[] visitOrder = Enumerable.Repeat(0, LOOPS).Select(i => r.Next(SIZE)).ToArray();

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
int sum = 0;
foreach (int v in visitOrder)
    sum += array[v];
sw.Stop();

以下是时间(滴答声)的结果:(x86,发布模式,不带调试器,.NET 4.5,I7-3930k)(越小越好)

________________ Array Size __________________
       10  100   1K   10K  100K    1M   10M 
byte: 549  559  552   552   568   632  3041  
int : 549  566  552   562   590  1803  4206
  • 使用CPU上的字节随机访问1M项,性能提高了285%!
  • 少于10,000的东西几乎不被注意到。
  • 对于这个基本的总和测试,int从未比字节快。
  • 这些值将随具有不同缓存大小的CPU的不同而变化。

最后一点,有时我看一下现在开放源代码的.NET框架,以了解Microsoft的专家所做的事情。.NET框架很少使用byte / int16。我实际上找不到任何东西。


1
您能否在“字节和int16数组不像int(基元)那样具有线程安全性”上做更多解释?
Rahul Rastogi

2
我相信,在x86中的数组中更新8或16位值时,它必须从内存中读取完整的32位字,然后更新其中的一部分(需要更新的字节),然后再将完整的32位值写回。因此,如果某个线程同时在第一个字节上工作,而另一个线程在第二个字节上同时工作,那么其中一个将占用其他线程的更改。这是因为它们同时在同一32位块或内存上工作。紧凑阵列中也可能发生此问题。但是,在数组之外,会将8/16位值填充为32位内存大小,这样就可以了。
Sunsetquest

9

您必须要处理几百亿行,才能使存储容量有任何显着差异。假设您有三列,而不是使用等效于字节的数据库类型,而使用了等效于int的数据库。

这使我们每行3(列)x 3(额外的字节),或每行9字节。

这意味着,对于“几百万行”(比如说三百万行),您将消耗整个额外的27 MB磁盘空间!幸运的是,由于我们不再生活在1970年代,您不必为此担心:)

如上所述,停止微优化-转换到不同整数类型的数字类型或从不同整数类型的数字类型转换为性能带来的损失将比带宽/磁盘空间成本严重得多,除非您要处理的非常非常大数据集。


7

在大多数情况下,“否”。

除非您预先知道要处理100亿行,否则它是微优化。

做最适合领域模型的事情。以后,如果您遇到性能问题,请进行基准测试和配置文件以查明发生问题的位置。


3
我相信您说的是拒绝使用这些类型,尽管在询问是否避免使用它们的问题上有些模棱两可。无论如何,这是关于微优化的好建议。
Noldorin

1
因此,你们两个都建议在整个板上坚持使用int,除非它有数百万行,并且您要进行微优化?
面包车

1
是的,坚持使用int,除非在Domain中使用tinyint(例如)更有意义。当我说微优化时,我的意思是一个坏主意。这不是优化的方法。
米奇·

3
我认为“除非在领域中tinyint更有意义”,否则这是矛盾的。我要问的问题是,即使我可以根据要存储的数字使用字节或smallint,似乎每个人都喜欢或使用int,即使在数据库方面也是如此。对我而言,仅仅因为它可以更好地映射以用于编程目的而在数据库中各处使用ints对我来说似乎很愚蠢,但是从我有限的.Net经验看来,这可能是最简单的方法。Easy并不一定总是翻译“正确的道路”
面包卡车

1
@Breadtruck:好点。我说的是在各处使用int没什么大不了的,除非您要处理大量的行。我还要说的是,如果tinyint在域中更有意义,那么我会倾向于使用它,因为它传达了额外的隐式信息。
米奇·麦特

5

不是说我不相信乔恩·格兰特(Jon Grant)和其他人,而是我不得不亲自看一下我们的“百万行表”。该表有1,018,000。我将11个tinyint列和6个smallint列转换为int,已经有5个int和3个smalldatetimes。4个不同的索引使用了各种数据类型的组合,但是显然新索引现在都使用int列。

进行更改仅需要40 mb(无索引)即可计算基本表磁盘使用量。当我在整个索引中添加索引时,总体变化只有30 mb。所以我很惊讶,因为我认为索引大小会更大。

因此,值得使用30 mb来使用所有不同数据类型的麻烦,没办法!我要去INT领域了,感谢大家让这位具有肛门功能的程序员重新回到了不再进行整数转换的直率和幸福幸福的生活中……yippeee!


3
那数据库现金呢?这是整体数据库性能的主要因素。我的意思是30 MB有多少百分比?在有效减少现金(例如减少30%)之前,我会三思而后行
Alexander Malakhov

4

如果在任何地方都使用int,则不需要强制转换或转换。与使用多个整数大小节省的内存相比,这是一个更大的节省。

它只会使生活更简单。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.