的我遇到這個奇怪的性能問題:C#應用程序CPU性能顯着減慢時,程序會創建大量的對象
我有創造數以百萬計的C#對象的C#應用程序。
在代碼的部分無關,應用程序確實不依賴於在步驟分配的數據1.
的CPU時間似乎被關聯到的對象的數目的特定的工作在步驟1創建。
我寫了一個簡單的C#案例,它再現了我的問題。 slowdown
使用在調用DoMyWork()
方法之前創建的數百萬字符串對象調用該命令。 正如你所看到的,如果200M的字符串被實例化,相同的DoMyWork()
方法最多可能需要3秒。
- 我錯過了語言的東西嗎?
- 假設沒有達到物理內存限制,是否有最大數量的對象不應達到,否則CLR會減慢?
我跑我的測試的Windows 10下的英特爾酷睿i7-6700和我的計劃是建立在32位模式下的控制檯版本(VS 2017年 - FW 4.6.1):
slowdown 0 Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 4 ms Allocating 40000 hashtables: 15 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 5 ms Allocating 40000 hashtables: 5 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 18 ms Allocating 40000 hashtables: 10 ms Allocating 40000 hashtables: 19 ms
放緩0使用〜30M
slowdown 200 Allocating 40000 hashtables: 392 ms Allocating 40000 hashtables: 1120 ms Allocating 40000 hashtables: 3067 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 31 ms Allocating 40000 hashtables: 418 ms Allocating 40000 hashtables: 15 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 18 ms Allocating 40000 hashtables: 416 ms
放緩200個使用800M〜
using System;
using System.Diagnostics;
using System.Collections;
namespace SlowDown
{
class Program
{
static string[] arr;
static void CreateHugeStringArray(long size)
{
arr = new string[size * 1000000];
for (int i = 0; i < arr.Length; i++) arr[i] = "";
}
static void DoMyWork()
{
int n = 40000;
Console.Write("Allocating " + n + " hashtables: ");
Hashtable[] aht = new Hashtable[n];
for (int i = 0; i < n; i++)
{
aht[i] = new Hashtable();
}
}
static void Main(string[] args)
{
if (0 == args.Length) return;
CreateHugeStringArray(Convert.ToInt64(args[0]));
for (int i = 0; i < 10 ; i++)
{
Stopwatch sw = Stopwatch.StartNew();
DoMyWork();
sw.Stop();
Console.Write(sw.ElapsedMilliseconds + " ms\n");
}
}
}
}
在您的示例中,您不會創建「數百萬個C#對象」。您創建了一個巨大的字符串數組,每個數組元素將實際指向相同的字符串對象(請參閱string interning)。 – dymanoid
如果您嘗試在'DoMyWork'內添加一個整數爲整數,它會如何執行,因爲現有邏輯中涉及到一個裝箱操作。你也可以考慮在重複操作相同的字符串時使用'StringBuilder'。 –
在'CreateHugeStringArray'之後加上'GC.Collect()',看看你是否仍然得到相同的時間。 –