我们在仪器上用.Net / C#3.5 Compact Framework编写了一个应用程序。
我们正在使用Windows Compact Embedded 7
操作系统。
此应用程序在很大程度上从设备读取一些数据并将其存储在磁盘或SD卡和显示器上的文件中 图形/数字方式的数据。
通过以下列方式传递字节数组来读取我们调用驱动程序的数据。
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static unsafe extern bool ReadFile(
IntPtr hFile,
byte* lpBuffer,
uint nNumberOfBytesToRead,
uint* lpNumberOfBytesRead,
uint lpOverlapped);
public int Read(byte[] buffer, int index, int count)
{
uint temp;
unsafe
{
fixed (byte* pByte = &(buffer[index]))
{
if (!ReadFile(handle, pByte, (uint)count, &temp, 0))
{
return -1;
}
}
}
return (int)temp;
}
我们在一个单独的线程中运行的read方法看起来像这样。
private void Reader()
{
try
{
while(true)
{
byte[] data = new byte[1024*10];
Read(data,0,data.Length);
// Do something with data
}
}
catch(Exception ex)
{
}
}
我们的要求是应用程序应连续运行数月。
我在instrumnet上启用了性能监视器,当我运行应用程序时,停止它并查看perf监视器生成的统计文件,我看到我们有数百万个固定对象,最终可能会导致内存泄漏。 / p>
这是stat文件。
counter total last datum n mean min max
Total Program Run Time (ms) 60240358 - - - - -
App Domains Created 1 - - - - -
App Domains Unloaded 2 - - - - -
Assemblies Loaded 16 - - - - -
Classes Loaded 2466 - - - - -
Methods Loaded 9685 - - - - -
Closed Types Loaded 598 - - - - -
Closed Types Loaded per Definition 598 1 61 9 1 97
Open Types Loaded 16 - - - - -
Closed Methods Loaded 184 - - - - -
Closed Methods Loaded per Definition 184 3 55 3 1 13
Open Methods Loaded 1 - - - - -
Threads in Thread Pool - 9 19 6 1 9
Pending Timers - 0 1986882 0 0 4
Scheduled Timers 662294 - - - - -
Timers Delayed by Thread Pool Limit 0 - - - - -
Work Items Queued 662294 - - - - -
Uncontested Monitor.Enter Calls 30435505 - - - - -
Contested Monitor.Enter Calls 72 - - - - -
Peak Bytes Allocated (native + managed) 10869964 - - - - -
Managed Objects Allocated 386020616 - - - - -
Managed Bytes Allocated 25202701076 16 386022691 65 8 1048588
Managed String Objects Allocated 39325752 - - - - -
Bytes of String Objects Allocated 3041772660 - - - - -
Garbage Collections (GC) 24644 - - - - -
Bytes Collected By GC 25218571932 936288 24644 1023314 49132 1528716
Managed Bytes In Use After GC - 6162292 24644 5988047 235620 6162292
Total Bytes In Use After GC - 10729796 24644 10045775 2113544 10729796
GC Compactions 24640 - - - - -
Code Pitchings 1 - - - - -
Calls to GC.Collect 0 - - - - -
GC Latency Time (ms) 532689 23 24644 21 4 103
**Pinned Objects 846589** - - - - -
Objects Moved by Compactor 15728750 - - - - -
Objects Not Moved by Compactor 261474730 - - - - -
Objects Finalized 14917931 - - - - -
Objects on Finalizer Queue - 0 14944139 303 0 2546
Boxed Value Types 17838485 - - - - -
Process Heap - 5968 101947181 156314 336 209656
Short Term Heap - 0 4050880 51 0 79952
JIT Heap - 0 27236 895917 0 1861844
App Domain Heap - 1536 29669 960504 1536 1297080
GC Heap - 0 208 4088477 0 7512064
Native Bytes Jitted 3495028 136 8431 414 84 111248
Methods Jitted 8431 - - - - -
Bytes Pitched 1738556 164 4269 407 72 111248
Methods Pitched 4269 - - - - -
Method Pitch Latency Time (ms) 78 78 1 78 78 78
Exceptions Thrown 171 - - - - -
Platform Invoke Calls 9528151 - - - - -
COM Calls Using a vtable 0 - - - - -
COM Calls Using IDispatch 0 - - - - -
Complex Marshaling 1929605 - - - - -
Runtime Callable Wrappers 0 - - - - -
Socket Bytes Sent 784 - - - - -
Socket Bytes Received 1934 - - - - -
Controls Created 255 - - - - -
Brushes Created 3022728 - - - - -
Pens Created 1888616 - - - - -
Bitmaps Created 166286 - - - - -
Regions Created 19 - - - - -
Fonts Created 31 - - - - -
Graphics Created (FromImage) 0 - - - - -
Graphics Created (CreateGraphics) 23 - - - - -
在互联网上阅读后,我发现/了解在Read
方法中我们将有一个固定对象,但是当我们退出Read方法时,它应该再次取消固定。
除了与非托管环境交互的上述代码之外,我们没有任何其他代码。
我正在寻找解决固定对象问题的建议,是否有其他方法/工具可以帮助我们找到那些固定对象的确切内容。
还有其他更好的方法来进行这种托管/非托管通信吗?
答案 0 :(得分:0)
我认为计数器是指在GC期间系统在固定状态下找到的对象数。如果读取呼叫可能需要很长时间,则可能经常发生这种情况。另一方面,我认为只需在while循环外部移动数据缓冲区的分配,就可以轻松减少应用程序执行的内存分配。如果它的大小是固定的(从代码中可以看出),或者至少很容易确定最大大小,那么在每次迭代时重新分配它是没有意义的。你为gc标记旧的并记住新的记忆。你将达到最大内存阈值,gc将启动。我不知道你的应用程序运行了多长时间,但分配3.86亿个对象看起来相当大。避免无用的重新分配(例如您发布的代码中的那个)并使用StringBuffers而不是字符串,例如,可以减少内存分配的数量,防止GC过于频繁地运行,并且通常可以提高代码效率。