标签: unmanaged-memory

为什么(以及如何)ASP.NET Cache存储在非托管内存中?

好的,你所有的ASP.NET专家:我用反射器来研究ASP.NET Cache实现(它位​​于HttpRuntime.CacheHttpContext.Current.Cache)使用Hashtable内部来保持缓存.

但是,数据存储在非托管内存中.这很奇怪,因为我无法看到任何数据存储在非托管内存中.但是,编写一个非常简单的Web应用程序,将一大块字节数组插入缓存中,我们可以看到:

在此输入图像描述

  • 私人字节:460MB
  • 所有堆中的字节数:150MB

=>

托管内存:150 MB

非托管内存:310 MB

所以基本上我多次调用应用程序(每次增加1000x请求,每个将64KB空缓冲区byte []放入缓存).因此,增长最多的是私有字节(总内存)而不是所有堆中字节(托管内存).但是我期望托管内存与总内存一致增长,因为我使用Hashtable将对象添加到托管堆.

你能解释一下这种行为吗?


UPDATE

正如Simon所说,所有堆中的字节值仅在垃圾收集后更改 - 我更改了代码以引发垃圾收集并更新计数器.Gen 2堆内存的增加与添加的内存量完全相同.但是,非托管内存仍然高得多.在此示例中,堆2仅为96MB,而总内存为231 MB.

在此输入图像描述

memory asp.net heap caching unmanaged-memory

20
推荐指数
1
解决办法
996
查看次数

如何清除Marshal.AllocHGlobal分配的内存?

我通过我的应用程序分配一些非托管内存Marshal.AllocHGlobal.然后,我将一组字节复制到此位置,并将生成的内存段转换为a,struct然后再通过释放内存Marshal.FreeHGlobal.

这是方法:

public static T Deserialize<T>(byte[] messageBytes, int start, int length)
    where T : struct
{
    if (start + length > messageBytes.Length)
        throw new ArgumentOutOfRangeException();

    int typeSize = Marshal.SizeOf(typeof(T));
    int bytesToCopy = Math.Min(typeSize, length);

    IntPtr targetBytes = Marshal.AllocHGlobal(typeSize);
    Marshal.Copy(messageBytes, start, targetBytes, bytesToCopy);

    if (length < typeSize)
    {
        // Zero out additional bytes at the end of the struct
    }

    T item = (T)Marshal.PtrToStructure(targetBytes, typeof(T));
    Marshal.FreeHGlobal(targetBytes);
    return item;
}
Run Code Online (Sandbox Code Playgroud)

这在大多数情况下都有效,但是如果我的字节数少于需求的大小struct,那么"随机"值将分配给最后的字段(我LayoutKind.Sequential在目标结构上使用).我想尽可能有效地将这些悬挂的区域归零.

对于上下文,此代码对从Linux上的C++发送的高频多播消息进行反序列化. …

.net memory unmanaged-memory

14
推荐指数
4
解决办法
1万
查看次数

如何在非托管内存中实例化C#类?(可能?)

更新:现在有一个被接受的答案"有效".你应该永远,永远,永远,永远使用它.曾经.


首先让我先说明我是一名游戏开发者.想要这样做有一个合法的 - 如果非常不寻常 - 与性能相关的原因.


假设我有一个像这样的C#类:

class Foo
{
    public int a, b, c;
    public void MyMethod(int d) { a = d; b = d; c = a + b; }
}
Run Code Online (Sandbox Code Playgroud)

没有什么花哨.请注意,它是仅包含值类型的引用类型.

在托管代码中,我希望有这样的东西:

Foo foo;
foo = Voodoo.NewInUnmanagedMemory<Foo>(); // <- ???
foo.MyMethod(1);
Run Code Online (Sandbox Code Playgroud)

这个功能NewInUnmanagedMemory会是什么样的?如果无法在C#中完成,可以在IL中完成吗?(或者可能是C++/CLI?)

基本上:有没有办法 - 无论多么苛刻 - 将一些完全任意的指针转换为对象引用.并且 - 没有使CLR爆炸 - 该死的后果.

(提出问题的另一种方法是:"我想为C#实现自定义分配器")

这导致了后续问题:当面对指向托管内存之外的引用时,垃圾收集器会做什么(特定于实现,如果需要)?

并且,与此相关,如果Foo将引用作为成员字段会发生什么?如果它指向托管内存怎么办?如果它只指向非托管内存中分配的其他对象怎么办?

最后,如果这是不可能的:为什么?


更新:到目前为止,这是"缺失的部分":

#1:如何将IntPtr对象转换为对象引用?虽然无法验证的IL可能是可能的(见评论).到目前为止,我没有运气.该框架似乎非常小心,以防止这种情况发生.

(能够在运行时获取非blittable托管类型的大小和布局信息也很好.同样,框架试图使这变得不可能.)

#2:假设问题可以解决 - 当GC遇到指向GC堆外部的对象引用时,它会做什么?它崩溃了吗?Anton Tykhyy 在他的回答中猜测它会.考虑到框架对于防止#1的谨慎程度,它似乎很可能.确认这一点的东西会很好. …

.net c# clr garbage-collection unmanaged-memory

12
推荐指数
3
解决办法
4354
查看次数

在WPF中呈现非托管视频帧的最佳性能是什么?

我正在使用FFmpeg库以最小的延迟(MediaElement无法处理的东西)通过UDP接收和解码H.264/MPEG-TS .

在专用的FFmpeg线程上,我正在拉PixelFormats.Bgr32视频帧进行显示.我已经尝试过InteropBitmap:

_section = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, PAGE_READWRITE, 0, size, null);
_buffer = MapViewOfFile(_section, FILE_MAP_ALL_ACCESS, 0, 0, size);
Dispatcher.Invoke((Action)delegate()
{
    _interopBitmap = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(_section, width, height, PixelFormats.Bgr32, (int)size / height, 0);
    this.Source = _interopBitmap;
});
Run Code Online (Sandbox Code Playgroud)

然后每帧更新:

Dispatcher.Invoke((Action)delegate()
{
    _interopBitmap.Invalidate();
});
Run Code Online (Sandbox Code Playgroud)

但性能非常差(跳帧,高CPU使用率等).

我也试过WriteableBitmap:FFmpeg将帧放在_writeableBitmap.BackBuffer和每帧更新:

Dispatcher.Invoke((Action)delegate()
{
    _writeableBitmap.Lock();
});
try
{
    ret = FFmpegInvoke.sws_scale(...);
}
finally
{
    Dispatcher.Invoke((Action)delegate()
    {
        _writeableBitmap.AddDirtyRect(_rect);
        _writeableBitmap.Unlock();
    });
}
Run Code Online (Sandbox Code Playgroud)

遇到几乎相同的性能问题(使用各种DispatcherPriority测试).

任何帮助将不胜感激.

wpf video performance ffmpeg unmanaged-memory

7
推荐指数
1
解决办法
742
查看次数

C#使用Memory <T>或ArraySegment <T>访问非托管数组?

通过引入的Memory,Span并且ArraySegment在C#7.2,我想知道如果我可以代表一个非托管数组作为枚举对象,即生活在堆上.

后一个要求排除了Span,它基本上实现了我想要的东西:例如

unsafe { bytes = new Span<byte>((byte*)ptr + (index * Width), Width); 
Run Code Online (Sandbox Code Playgroud)

是否可以用ArraySegment或做同样的事情Memory?他们的构造函数只接受byte[],也许有某种方法可以欺骗C#byte*而不是传递byte[]

c# unmanaged-memory

7
推荐指数
1
解决办法
577
查看次数

直接读取和写入Unlocked Bitmap非托管内存(Scan0)

从解锁的Bitmap非托管内存直接写入和读取是否可以?

在我解锁Bitmap后,我可以继续使用BitmapData吗?我做了一个测试应用程序,我可以在鼠标位置读取PictureBox的Bitmap像素,而另一个线程正在将像素写入同一个Bitmap.

编辑1:正如Boing他在回答中指出的那样:"Scan0没有指向Bitmap对象的实际像素数据;而是指向一个临时缓冲区,它代表Bitmap对象中像素数据的一部分." 来自MSDN.

但是一旦我得到了Scan0,我就可以读取/写入Bitmap而无需Lockbits或UnlockBits!我在一个帖子里做了很多次.相对于MSDN,它不应该发生,因为Scan0指向位图数据的COPY!好吧,在C#中,所有测试表明它不是副本.在C++中,我不知道它是否正常工作.

编辑2:使用旋转方法有时会使操作系统释放位图像素数据副本.结论,it is not safe to read/write an unlocked Bitmap Scan0.谢谢Boing的回答和评论!

下面是我如何获取BitmapData并读取和写入像素值.

    /// <summary>
    /// Locks and unlocks the Bitmap to get the BitmapData.
    /// </summary>
    /// <param name="bmp">Bitmap</param>
    /// <returns>BitmapData</returns>
    public static BitmapData GetBitmapData(Bitmap bmp)
    {
        BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
        bmp.UnlockBits(bmpData);
        return bmpData;
    }

    /// <summary>
    /// Get pixel directly from unamanged pixel data based on the Scan0 pointer.
    /// </summary> …
Run Code Online (Sandbox Code Playgroud)

c# bitmap lockbits unmanaged-memory

6
推荐指数
1
解决办法
5630
查看次数

F# NativePtr.stackalloc 比 C# stackalloc 慢 - 包含反编译代码

继续我的 F# 性能测试。有关更多背景信息,请参见此处:

f# 结构构造函数中的 NativePtr.stackalloc

F#NativePtr.stackalloc 意外堆栈溢出

现在我已经在 F# 中使用了堆栈数组。但是,出于某种原因,等效的 C# 大约快了 50 倍。我在下面包含了 ILSpy 反编译版本,看起来只有 1 行是真正不同的(在 stackAlloc 中)。

这里发生了什么?未经检查的算术真的是造成这种巨大差异的原因吗?不知道我怎么能测试这个??

https://msdn.microsoft.com/en-us/library/a569z7k8.aspx

F# 代码

#nowarn "9"

open Microsoft.FSharp.NativeInterop
open System
open System.Diagnostics    
open System.Runtime.CompilerServices        

[<MethodImpl(MethodImplOptions.NoInlining)>]
let stackAlloc x =
    let mutable ints:nativeptr<byte> = NativePtr.stackalloc x
    ()   

[<EntryPoint>]
let main argv = 
    printfn "%A" argv

    let size = 8192            
    let reps = 10000

    stackAlloc size // JIT
    let clock = Stopwatch()
    clock.Start()
    for i = 1 to reps do            
        stackAlloc …
Run Code Online (Sandbox Code Playgroud)

c# stack f# unmanaged-memory

5
推荐指数
1
解决办法
749
查看次数

将非托管内存复制到托管字节数组

我需要将非托管内存读入托管字节数组.

为此,我有一个对非托管内存的IntPtr引用和一个长度,它表示我感兴趣的非托管内存的大小.

我使用以下代码将其读入托管字节数组.

            byte[] pixelDataArray = new byte[pixelDataLength];
            for (int i = 0; i < pixelDataLength; i++) {
                pixelDataArray[i] = Marshal.ReadByte(pixelData, i);
            }
Run Code Online (Sandbox Code Playgroud)

然而,这导致非常差的性能.使用256KB非托管内存调用此方法1000次,需要7秒以上.我认为必须有一种更有效的方法来做到这一点.

我无法使用Marshal.PtrToStructure,因为我不知道需要预先阅读的内存大小.

关于如何改进这个功能的任何想法?

c# performance marshalling unmanaged-memory

3
推荐指数
1
解决办法
5905
查看次数

结构构造函数中的 f# NativePtr.stackalloc

我正在进行一些 F# 性能测试,并尝试在堆栈上而不是堆上创建一个数组(值与引用类型)。我正在使用 NativePtr.stackalloc 在堆栈上分配内存。在下面的第一个构造函数中出现错误。

type StackArray<'T when 'T : unmanaged> =
    struct
        val pointer: nativeptr<'T>

        new(x) = { pointer = NativePtr.stackalloc x}
        new(pointer) = { pointer = pointer}
    end    

// This give a System.TypeInitializationException with internal System.InvalidProgramException   
let ints2 = new StackArray<int>(10) 

// This works fine
let (pointer:nativeptr<int>) = NativePtr.stackalloc 10
let ints = new StackArray<int>(pointer) 
Run Code Online (Sandbox Code Playgroud)

我可以简单地在函数中使用第二种方法,但是为什么我无法在构造函数内分配内存,这真的很困扰我。

f# struct unmanaged-memory

3
推荐指数
1
解决办法
321
查看次数

C# 调用一个 DLL 函数,该函数返回一个指向结构数组的指针

我尝试了各种方法的许多不同组合来封送此调用。这是一个 DLL,它返回一个指向结构数组的指针。像 debugPort 这样的类型实际上是枚举。

/**
* \struct debugConnectParameters 
* \brief Get device characterization and specify connection parameters through ST-LINK interface. 
*/ 
typedef struct debugConnectParameters { 
    debugPort dbgPort;        /**< Select the type of debug interface #debugPort. */ 
    int index;                /**< Select one of the debug ports connected. */ 
    char serialNumber[33];    /**< ST-LINK serial number. */ 
    char firmwareVersion[20]; /**< Firmware version. */ 
    char targetVoltage[5];    /**< Operate voltage. */ 
    int accessPortNumber;     /**< Number of available access port. */ 
    int accessPort;           /**< Select access …
Run Code Online (Sandbox Code Playgroud)

c# c++ marshalling dllimport unmanaged-memory

3
推荐指数
1
解决办法
1459
查看次数

将UnmanagedMemoryStream转换为Byte-Array

就这么简单,我怎么能在转换VBNET一个UnmanagedMemoryStream字节数组

Dim bytes() As Byte = My.Resources.AudioFile
Run Code Online (Sandbox Code Playgroud)

例外:

Value of type 'System.IO.UnmanagedMemoryStream' cannot be converted to '1-dimensional array of Byte'.
Run Code Online (Sandbox Code Playgroud)

.net vb.net bytebuffer bytearray unmanaged-memory

2
推荐指数
1
解决办法
3467
查看次数

使用UTF8编码将C#字符串写入预分配的非托管缓冲区

我需要将C#字符串写入编码为Utf8的预分配非托管缓冲区.回答之前,请阅读以下要求:

  • 没有新的分配(所以请不要指导我涉及创建字节数组或其他实例化的答案)
  • 没有过渡到非托管代码(没有pinvoke/calli)

目前,我正在使用OpCodes.Cpblk将原始字符串从C#复制到使用16位字符的非托管缓冲区.这给了我与在x64架构上使用非托管memcpy大致相同的性能,我真的需要吞吐量接近它.

我正在考虑字符串固定char*并对其进行迭代,但实现不带跳转表的编码器既麻烦又不太理想.

c# clr unmanaged utf-8 unmanaged-memory

1
推荐指数
1
解决办法
596
查看次数

如何在创建实例时在系统中分配非托管内存?

当从C#创建COM对象或任何其他非托管实例时,如何在系统中分配非托管内存?

.net c# memory-management unmanaged-memory

0
推荐指数
1
解决办法
280
查看次数