C #에서 바이트 또는 short 대신 int를 사용해야하는 이유
이 문제와 관련하여 몇 가지 스레드를 찾았습니다. 대부분의 사람들은 모바일 앱이 아닌 한 바이트 또는 smallint가 데이터를 처리하더라도 보드 전체의 C # 코드에서 int를 사용하는 것을 선호하는 것으로 보입니다. 이유를 모르겠습니다. C # 데이터 유형을 데이터 스토리지 솔루션에있는 것과 동일한 데이터 유형으로 정의하는 것이 더 합리적이지 않습니까?
내 전제 : 유형이 지정된 데이터 세트, Linq2SQL 클래스, POCO를 사용하는 경우 계층간에 데이터 유형을 동기화하지 않으면 컴파일러 데이터 유형 변환 문제가 발생합니다. 나는 C # 코드에서 보드 전체에서 int를 사용하는 것이 더 쉬웠 기 때문에 System.Convert를 항상 좋아하지 않습니다. 나는 항상 데이터베이스에 대한 인터페이스를 깨끗하게 유지하기 위해 데이터베이스와 코드의 데이터를 처리하는 데 필요한 가장 작은 데이터 유형을 사용했습니다. 그래서 나는 내 C # 코드의 75 %가 int와 달리 바이트 또는 짧은 것을 사용하고 있다고 확신합니다. 왜냐하면 그것이 데이터베이스에 있기 때문입니다.
가능성 : 이것은 코드의 모든 것에 int를 사용하는 대부분의 사람들이 SQL 스토리지 데이터 유형에도 int 데이터 유형을 사용하고 데이터베이스의 전체 크기에 대해 덜 신경을 쓸 수 있음을 의미합니까, 아니면 해당되는 경우 코드에서 system.convert를 수행합니까?
내가 관심을 갖는 이유 : 나는 영원히 혼자 일해 왔으며 모범 사례와 표준 코딩 규칙에 익숙해지고 싶습니다.
성능면에서 int는 거의 모든 경우에 더 빠릅니다. CPU는 32 비트 값으로 효율적으로 작동하도록 설계되었습니다.
더 짧은 값은 다루기가 복잡합니다. 예를 들어, 단일 바이트를 읽으려면 CPU가이를 포함하는 32 비트 블록을 읽은 다음 상위 24 비트를 마스킹해야합니다.
바이트를 쓰려면 대상 32 비트 블록을 읽고 하위 8 비트를 원하는 바이트 값으로 덮어 쓴 다음 전체 32 비트 블록을 다시 써야합니다.
물론 공간적으로는 더 작은 데이터 유형을 사용하여 몇 바이트를 절약 할 수 있습니다. 따라서 수백만 개의 행이있는 테이블을 작성하는 경우 더 짧은 데이터 유형을 고려할 가치가 있습니다. (그리고 데이터베이스에서 더 작은 데이터 유형을 사용해야하는 좋은 이유가 될 수도 있습니다)
그리고 정확성 측면에서 int는 쉽게 오버플로되지 않습니다. 당신이 경우에 생각하는 당신의 값이 바이트에 맞도록 가고, 다음 코드 수단으로 일부 무해한 보이는 변화는 값이 그것으로 저장 얻을 더 큰 미래의 어떤 시점에서인가?
이것이 int가 모든 정수 데이터에 대한 기본 데이터 유형이되어야하는 몇 가지 이유입니다. 실제로 머신 바이트를 저장하려는 경우에만 바이트를 사용하십시오. 실제로 16 비트 정수 값을 지정하는 파일 형식이나 프로토콜 등을 처리하는 경우에만 shorts를 사용하십시오. 일반적으로 정수만 다루고 있다면 정수로 만드십시오.
나는 겨우 6 년 늦었지만 다른 사람을 도울 수 있을지도 모릅니다.
내가 사용할 몇 가지 지침은 다음과 같습니다.
- 데이터가 미래에 맞지 않을 가능성이 있다면 더 큰 int 유형을 사용하십시오.
- 변수가 구조체 / 클래스 필드로 사용되는 경우 기본적으로 전체 32 비트를 차지하도록 패딩되므로 byte / int16을 사용하면 메모리가 절약되지 않습니다.
- 변수가 수명이 짧은 경우 (함수 내부와 같이) 더 작은 데이터 유형은별로 도움이되지 않습니다.
- "byte"또는 "char"는 때때로 데이터를 더 잘 설명 할 수 있으며 실수로 더 큰 값이 할당되지 않도록 컴파일 시간 검사를 수행 할 수 있습니다. 예를 들어 byte를 사용하여 날짜 (1-31)를 저장하고 1000을 할당하려고하면 오류가 발생합니다.
- 변수가 대략 100 개 이상의 배열에서 사용되는 경우 의미가있는 한 더 작은 데이터 유형을 사용합니다.
- byte 및 int16 배열은 int (기본)만큼 스레드로부터 안전하지 않습니다.
아무도 제기하지 않은 한 가지 주제는 제한된 CPU 캐시입니다. CPU가 더 빠른 L1 / L2 / L3 캐시에 더 많은 프로그램을 넣을 수 있기 때문에 작은 프로그램은 큰 프로그램보다 더 빠르게 실행됩니다.
int 유형을 사용하면 CPU 명령이 줄어들 수 있지만 CPU 캐시에 맞지 않는 데이터 메모리 비율이 높아집니다. 명령어는 실행 비용이 저렴합니다. 최신 CPU 코어는 클럭주기 당 3 ~ 7 개의 명령을 실행할 수 있지만, 반면에 단일 캐시 미스는 RAM까지 도달해야하기 때문에 1000-2000 클럭주기가 소요될 수 있습니다.
메모리가 보존되면 캐시에서 압축되지 않기 때문에 나머지 응용 프로그램의 성능도 향상됩니다.
바이트 배열과 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 was never faster then byte for this basic sum test.
- These values will vary with different CPUs with different cache sizes.
One final note, Sometimes I look at the now open-source .NET framework to see what Microsoft's experts do. The .NET framework uses byte/int16 surprisingly little. I could not find any actually.
You would have to be dealing with a few BILLION rows before this makes any significant difference in terms of storage capacity. Lets say you have three columns, and instead of using a byte-equivalent database type, you use an int-equivalent.
That gives us 3 (columns) x 3 (bytes extra) per row, or 9 bytes per row.
This means, for "a few million rows" (lets say three million), you are consuming a whole extra 27 megabytes of disk space! Fortunately as we're no longer living in the 1970s, you shouldn't have to worry about this :)
As said above, stop micro-optimising - the performance hit in converting to/from different integer-like numeric types is going to hit you much, much harder than the bandwidth/diskspace costs, unless you are dealing with very, very, very large datasets.
For the most part, 'No'.
Unless you know upfront that you are going to be dealing with 100's of millions of rows, it's a micro-optimisation.
Do what fits the Domain model best. Later, if you have performance problems, benchmark and profile to pin-point where they are occuring.
Not that I didn't believe Jon Grant and others, but I had to see for myself with our "million row table". The table has 1,018,000. I converted 11 tinyint columns and 6 smallint columns into int, there were already 5 int & 3 smalldatetimes. 4 different indexes used a combo of the various data types, but obviously the new indexes are now all using int columns.
Making the changes only cost me 40 mb calculating base table disk usage with no indexes. When I added the indexes back in the overall change was only 30 mb difference overall. So I was suprised because I thought the index size would be larger.
So is 30 mb worth the hassle of using all the different data types, No Way! I am off to INT land, thanks everyone for setting this anal retentive programmer back on the straight and happy blissful life of no more integer conversions...yippeee!
If int is used everywhere, no casting or conversions are required. That is a bigger bang for the buck than the memory you will save by using multiple integer sizes.
It just makes life simpler.
The .NET runtime is optimised for Int32. See previous discussion at .NET Integer vs Int16?
'Nice programing' 카테고리의 다른 글
HTTPModule 이벤트 실행 순서? (0) | 2020.12.07 |
---|---|
linux / unix에서 WinAPI의 MAX_PATH에 해당하는 것이 있습니까? (0) | 2020.12.07 |
한 사각형의 크기를 다른 사각형 내에서 가능한 최대 크기로 조정하려면 어떻게합니까? (0) | 2020.12.07 |
특수 문자가 포함 된 ANSI 인코딩 파일을 읽는 방법 (0) | 2020.12.07 |
ImageMagick을 사용하여 더 큰 캔버스 안에 이미지 배치 (0) | 2020.12.07 |