Tôi có một ứng dụng sử dụng số lượng lớn các chuỗi. Vì vậy, tôi có một số vấn đề về cách sử dụng bộ nhớ. Tôi biết rằng một trong những giải pháp tốt nhất trong trường hợp này là sử dụng một DB, nhưng tôi không thể sử dụng điều này cho thời điểm này, vì vậy tôi đang tìm kiếm các giải pháp khác.Chuỗi VS Byte [], sử dụng bộ nhớ
Trong chuỗi C# được lưu trữ trong Utf16, điều đó có nghĩa là tôi đã mất một nửa dung lượng bộ nhớ so với Utf8 (đối với phần chính của chuỗi của tôi). Vì vậy, tôi quyết định sử dụng mảng byte của chuỗi utf8. Nhưng với sự ngạc nhiên của tôi, giải pháp này chiếm không gian bộ nhớ gấp đôi so với các chuỗi đơn giản trong ứng dụng của tôi.
Vì vậy, tôi đã thực hiện một số thử nghiệm đơn giản, nhưng tôi muốn biết ý kiến của các chuyên gia để chắc chắn.
Test 1: phân bổ chuỗi dài cố định
var stringArray = new string[10000];
var byteArray = new byte[10000][];
var Sb = new StringBuilder();
var utf8 = Encoding.UTF8;
var stringGen = new Random(561651);
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
Sb.Append((stringGen.Next(90)+32).ToString());
}
stringArray[i] = Sb.ToString();
byteArray[i] = utf8.GetBytes(Sb.ToString());
Sb.Clear();
}
GC.Collect();
GC.WaitForFullGCComplete(5000);
sử dụng bộ nhớ
00007ffac200a510 1 80032 System.Byte[][]
00007ffac1fd02b8 56 152400 System.Object[]
000000bf7655fcf0 303 3933750 Free
00007ffac1fd5738 10004 224695091 System.Byte[]
00007ffac1fcfc40 10476 449178396 System.String
Như chúng ta có thể thấy, byte mảng mất không gian bộ nhớ hai lần ít hơn, không ngạc nhiên thực sự ở đây.
thử nghiệm 2: Random phân bổ kích thước chuỗi (với chiều dài thực tế)
var stringArray = new string[10000];
var byteArray = new byte[10000][];
var Sb = new StringBuilder();
var utf8 = Encoding.UTF8;
var lengthGen = new Random(2138784);
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < lengthGen.Next(100); j++) {
Sb.Append(i.ToString());
stringArray[i] = Sb.ToString();
byteArray[i] = utf8.GetBytes(Sb.ToString());
}
Sb.Clear();
}
GC.Collect();
GC.WaitForFullGCComplete(5000);
sử dụng bộ nhớ
00007ffac200a510 1 80032 System.Byte[][]
000000be2aa8fd40 12 82784 Free
00007ffac1fd02b8 56 152400 System.Object[]
00007ffac1fd5738 9896 682260 System.Byte[]
00007ffac1fcfc40 10368 1155110 System.String
Chuỗi mất một chút ít không gian hơn gấp đôi thời gian không gian bộ nhớ của mảng byte . Với chuỗi ngắn hơn tôi đã mong đợi một chi phí cao hơn cho dây. Nhưng có vẻ như ngược lại, tại sao?
thử nghiệm 3: String mô hình tương ứng với ứng dụng của tôi
var stringArray = new string[10000];
var byteArray = new byte[10000][];
var Sb = new StringBuilder();
var utf8 = Encoding.UTF8;
var lengthGen = new Random();
for (int i=0; i < 10000; i++) {
if (i%2 == 0) {
for (int j = 0; j < lengthGen.Next(100000); j++) {
Sb.Append(i.ToString());
stringArray[i] = Sb.ToString();
byteArray[i] = utf8.GetBytes(Sb.ToString());
Sb.Clear();
}
} else {
stringArray[i] = Sb.ToString();
byteArray[i] = utf8.GetBytes(Sb.ToString());
Sb.Clear();
}
}
GC.Collect();
GC.WaitForFullGCComplete(5000);
sử dụng bộ nhớ
00007ffac200a510 1 80032 System.Byte[][]
00007ffac1fd02b8 56 152400 System.Object[]
00007ffac1fcfc40 5476 198364 System.String
00007ffac1fd5738 10004 270075 System.Byte[]
Đây chuỗi mất không gian bộ nhớ ít hơn nhiều so với byte. Điều này có thể gây ngạc nhiên, nhưng tôi cho rằng chuỗi rỗng chỉ được tham chiếu một lần. Là nó? Nhưng tôi không biết nếu điều này có thể giải thích tất cả những khác biệt lớn. Có lý do nào khác không? giải pháp tốt nhất là gì?
Tại sao không sử dụng 'string.IsNullOrEmpty (stringArray [i])' ? –
@MarkJansen Nó chỉ là một minh họa: Tôi biết chắc chắn rằng 'stringArray [i]' rỗng trong nhánh 'else' của' if (i% 2 == 0) 'có điều kiện, vì vậy tôi có thể bỏ qua sự so sánh với 'string.Empty' hoàn toàn. – dasblinkenlight
Thú vị, thực sự sử dụng một tham chiếu byte trống cải thiện việc sử dụng bộ nhớ rất nhiều. Tôi quên nói trong bài viết của mình, hơn là 64 bit và đơn vị là byte. Dù sao điều này không thay đổi ý tưởng của bạn giải thích, ngay cả khi tôi thấy rằng 34 byte cho một con trỏ nó rất nhiều, (thậm chí nhiều hơn với 26 byte trên mỗi chuỗi). Tôi đã mất kích thước của con trỏ 10K (80032 KB tức là 25% kích thước bộ nhớ hữu ích) với System.Byte [] []. Có cách nào để tránh việc sử dụng quá nhiều không? Có thể không phải với mảng byte. – Edeen