我一直在做我们的大型项目中的这一切。大内存用作将大量数据写入磁盘(来自传感器硬件)的应用程序的循环缓冲区。访问缓冲区的代码是用托管C++编写的,因为它更容易访问非托管函数,但我认为一个不安全的C#代码块也可以很好地工作。我不记得有任何问题。
为了与OS接口,手动分配的缓冲区具有不移动和4kb对齐的优点。它可以直接用于调用无缓冲的I/O功能。
这是一段代码。我写这篇文章的时间很长(虽然它仍在使用中),所以不要问我关于细节的问题(比“最初承诺的5%”应该对......有好处)。此代码正在托管的C++中运行。
try
{
LPVOID lpvReserveBase; // base address of the test memory
LPVOID lpvCommitBase; // base address of the test memory
SYSTEM_INFO sSysInfo; // useful information about the system
DWORD dwPageSize; // the page size on this computer
GetSystemInfo(&sSysInfo); // initialize the structure
dwPageSize = sSysInfo.dwPageSize;
ULONG nCommitPages = nTargetUserSizeBytes/dwPageSize;
if (nCommitPages * dwPageSize < (DWORD)nTargetUserSizeBytes)
{
nCommitPages++;
}
nTargetUserSizeBytes = nCommitPages * dwPageSize;
ULONG nReservedPages = (ULONG)(nCommitPages * 1.05); // reserve 5% more than initially committed
// Reserve pages in the process's virtual address space.
lpvReserveBase = VirtualAlloc(
NULL, // system selects address
nReservedPages * dwPageSize, // size of allocation
MEM_RESERVE, // allocate reserved pages
PAGE_NOACCESS); // protection = no access
if (lpvReserveBase == NULL)
{
ErrLog(E_SHIF_ERR_DMAALLOC_FAILED, "Error: VirtualAlloc reserve failed");
return FALSE;
}
// commit another page.
lpvCommitBase = VirtualAlloc(
(LPVOID)lpvReserveBase, // next page to commit
nCommitPages * dwPageSize, // page size, in bytes
MEM_COMMIT, // allocate a committed page
PAGE_READWRITE); // read/write access
if (lpvCommitBase == NULL)
{
ErrLog(E_SHIF_ERR_DMAALLOC_FAILED, "Error: VirtualAlloc failed");
return FALSE;
}
m_pUserAddr = (LPTSTR)lpvCommitBase;
pDMADesc->m_dwReservedUserSize = nReservedPages * dwPageSize;
}
catch (std::bad_alloc* exc)
{
sprintf_s(gsSH_IF_LastErr, 512, "Error: AddDMA: Failed allocate std memory (%d bytes, %s)", nTargetUserSizeBytes, exc->what());
ErrLog(E_SHIF_ERR_DMAALLOC_FAILED, gsSH_IF_LastErr);
return FALSE;
}
来源
2014-04-08 19:09:33
PMF
如果你想做这样的事情,你可能不应该使用C#开始。使用非托管内存将阻止您使用该语言的大部分功能。另外绝大多数情况下绝大多数人都不会从这种细粒度的内存管理中受益,并且最终会导致代码被破坏,对于那些能够正常工作的极少数人来说,大多数*他们*将会看到相当甚至更糟糕的表现。这是一个好主意的可能性是微乎其微的。 – Servy
手动管理内存不是很难,特别是对于您希望在整个流程生命周期中存在的大型缓冲区。将缓冲区包装在不安全的类中可让您将它们暴露给代码库的其余部分,因此它不会“妨碍您使用大部分语言的功能”。而地球上的表现会变得更糟?如果通过分配和释放你的表现是瓶颈的,那么无论如何你都会做错事。 –
:)“如果通过分配和释放你的表现是瓶颈的,那么无论如何你都会做错事。” - 我认为这很好地回答了你自己的问题。 –