I thought .NET was supposed to make things easier, if anything, than unmanaged code.
-
If you want to do this in the dotNet framework and have it cross platform you're going to want to use one of the newer frameworks anyway as the older ones are not generally cross platform. I don't see the problem here.
a newer framework doesn't change the landscape though. I'm using the latest stuff anyway.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
C++/CLI
#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
+1 for this suggestion. Performance is much, much better than using the managed classes for memory mapped files. (I remember we clocked this being around 5x faster). We used this approach to store multimedia fingerprint data. Here is a small snippet of code showing how we initialized the memory mapped file using C++/CLI - The data is accessible through the _pData (UInt32*) member.
Int32 StationHashStorage::Open() {
msclr::lock lock(_syncRoot);
if( _isOpen )
return 0;
String^ fileName = GetFullFileName();_szInBytes = ComputeFileSizeInBytes(fileName);
String^ mapExtension = GetFileExtension();
String^ mapName = String::Format("{0}{1}_{2}", _stationId, _date.ToString("yyyyMMdd"), mapExtension);marshal_context context;
LPCTSTR pMapName = context.marshal_as(mapName);{
msclr::lock lock( _openLock );
// Try to see if another storage instance has requested the same memory-mapped file and share it
_hMapping = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, pMapName);
if( !_hMapping ) {
// This is the first instance acquiring the file
LPCTSTR pFileName = context.marshal_as(fileName);
// Try to open the existing file, or create new one if not exists
_hFile = CreateFile(pFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if( !_hFile )
throw gcnew IOException(String::Format(Strings::CreateFileFailed, GetLastError(), _stationId));
_hMapping = CreateFileMapping(_hFile,
NULL,
PAGE_READWRITE | SEC_COMMIT,
0,
_szInBytes,
pMapName);
if( !_hMapping )
throw gcnew IOException(String::Format(Strings::CreateMappingFailed, GetLastError(), _stationId));
_usingSharedFile = false;
} else {
_usingSharedFile = true;
}
}_pData = (UInt32*)::MapViewOfFile(_hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if( !_pData )
throw gcnew IOE -
I know this is a very special case but still i ran headlong into it. The easiest way to implement a B+ tree on disk is using a memory mapped file. I think this is what SQL Server does, but don't quote me. However, the only way you can access memory mapped files in C# is through .NET interop which makes it useless. Because one of the points of a memory mapped file is that you can do memory allocations that are backed by disk. There's no way in hell .NET can give you that in its current incarnation, even if one were to write a custom host, because of the way a GC system works. What I'd like var foo = new int[1000000]; // backed by disk, paged automatically What I'd have to do. somepointer = VirtualAlloc(...) Write(somepointer, data) etc etc basically it works like file i/o which defeats essentially the whole purpose. =(
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
I believe this is the type of library you are looking for... [C# BPlusTree](http://csharptest.net/projects/bplustree/)
Steve Naidamast Sr. Software Engineer Black Falcon Software, Inc. blackfalconsoftware@outlook.com
-
I believe this is the type of library you are looking for... [C# BPlusTree](http://csharptest.net/projects/bplustree/)
Steve Naidamast Sr. Software Engineer Black Falcon Software, Inc. blackfalconsoftware@outlook.com
I've seen that. This is a learning exercise for me, so I'm not looking for one that's already made.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
my posts of this nature were already weighed in on by Chris. they've been ruled okay for the lounge, so if you don't like them skip them or block me.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
honey the codewitch wrote:
my posts of this nature were already weighed in on by Chris
Careful. I said posts that talk about general programming stuff like "here's what I'm doing" are fine. Posts that are of a technical nature that are better suited to one of the dedicated programming forums should be posted in the appropriate forum in order to allow members to discuss programming topics. Yeah it's a grey area, but follow the spirit.
cheers Chris Maunder
-
honey the codewitch wrote:
my posts of this nature were already weighed in on by Chris
Careful. I said posts that talk about general programming stuff like "here's what I'm doing" are fine. Posts that are of a technical nature that are better suited to one of the dedicated programming forums should be posted in the appropriate forum in order to allow members to discuss programming topics. Yeah it's a grey area, but follow the spirit.
cheers Chris Maunder
I hear, you and I'm trying. My brain is all tech whenever i'm on a coding jag, so i eat sleep and breathe it.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
I hear, you and I'm trying. My brain is all tech whenever i'm on a coding jag, so i eat sleep and breathe it.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
You ever get to the point where you try and have conversations with non-coders and you get internal parsing errors? I guess the question could be "do you ever not get to the point..."
cheers Chris Maunder
-
You ever get to the point where you try and have conversations with non-coders and you get internal parsing errors? I guess the question could be "do you ever not get to the point..."
cheers Chris Maunder
yes i do. my solution thus far has been while i'm coding to limit my exposure to non-coders. :laugh: But i wind up here a lot lately while in the middle of it. Mainly because i look here for inspiration and a break from the actual writing of code. sometimes to vent about chicanery in MS products and the like too. Still, I can't turn my mind away from it entirely when i'm in the thick of it. I'm like a dog with a bone.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
I know this is a very special case but still i ran headlong into it. The easiest way to implement a B+ tree on disk is using a memory mapped file. I think this is what SQL Server does, but don't quote me. However, the only way you can access memory mapped files in C# is through .NET interop which makes it useless. Because one of the points of a memory mapped file is that you can do memory allocations that are backed by disk. There's no way in hell .NET can give you that in its current incarnation, even if one were to write a custom host, because of the way a GC system works. What I'd like var foo = new int[1000000]; // backed by disk, paged automatically What I'd have to do. somepointer = VirtualAlloc(...) Write(somepointer, data) etc etc basically it works like file i/o which defeats essentially the whole purpose. =(
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Use unsafe code with pointers just as you would in C and you can do the same thing as you could in C.
Nope, because you can't pin an object to a specific address in memory. Ergo I can't back a .NET instance with a memory mapped file. Memory mapped files work by mapping a portion of the process address space to your application. So you can read and write the file doing pointer ops. However, in .NET you can only get pointers to the GC heap by pinning objects. So I cannot do
var arr = new int[100000000];// backed by memory mapped file
in any variation. Even if I were to pin the array to get the pointer, the pointer wouldn't be part of that mapped address space. At best, I have to *copy* the entire object into that mapped region, which absolutely defeats the whole point of why I'd use mem mapped I/O here in the first place. There's a half measure using Span, but it only works in Standard and Core, not the DNF
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Nope, because you can't pin an object to a specific address in memory. Ergo I can't back a .NET instance with a memory mapped file. Memory mapped files work by mapping a portion of the process address space to your application. So you can read and write the file doing pointer ops. However, in .NET you can only get pointers to the GC heap by pinning objects. So I cannot do
var arr = new int[100000000];// backed by memory mapped file
in any variation. Even if I were to pin the array to get the pointer, the pointer wouldn't be part of that mapped address space. At best, I have to *copy* the entire object into that mapped region, which absolutely defeats the whole point of why I'd use mem mapped I/O here in the first place. There's a half measure using Span, but it only works in Standard and Core, not the DNF
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
This is what "Span" is for. Return that instead of an array and your API will be "managed" in the sense to an external user. Or you can use "GCHandle.Alloc" to pin a managed array in memory. GCHandle.Alloc Method (System.Runtime.InteropServices) | Microsoft Docs[^] Using Span is a better idea though.
-
This is what "Span" is for. Return that instead of an array and your API will be "managed" in the sense to an external user. Or you can use "GCHandle.Alloc" to pin a managed array in memory. GCHandle.Alloc Method (System.Runtime.InteropServices) | Microsoft Docs[^] Using Span is a better idea though.
Another commenter pointed out Span, which I had forgotten about. It's a half measure** but gets me closer, however, it does not work in the DNF, only in Core and Standard i think. GCHandle.Alloc will not let me pin to a specific address. In order for .NET to do anything beyond span it would have to allow you to create unmanaged heaps to allocate objects on which the collector wouldn't collect. It's designed such that it can't work, and I accept that. It would just be nice if it had some kind of feature like the above to enable it. ** I don't actually want to store an array, i was using that as an example. My datastructure is complex and nested, which is precisely why i'd like to use vmem
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Well in that case for .NET Framework unsafe code is the only answer. Or just return a IntPtr and let the user decide if they want to marshal or use unsafe code if this is for an API. Thats how MS does it.
Not applicable for this.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Another commenter pointed out Span, which I had forgotten about. It's a half measure** but gets me closer, however, it does not work in the DNF, only in Core and Standard i think. GCHandle.Alloc will not let me pin to a specific address. In order for .NET to do anything beyond span it would have to allow you to create unmanaged heaps to allocate objects on which the collector wouldn't collect. It's designed such that it can't work, and I accept that. It would just be nice if it had some kind of feature like the above to enable it. ** I don't actually want to store an array, i was using that as an example. My datastructure is complex and nested, which is precisely why i'd like to use vmem
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Not applicable for this.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
MS uses unsafe code all over the place in their own frameworks. Not sure how its an issue but ok. Even if you could address managed array to a native buffer that would make it unsafe usage.
unsafe isn't a problem. This has nothing to do with a desire not to run unsafe code Again, what it has to do with is mapping a complex managed data structure to a file using Vmem. It's not doable. At best, you resolve to something much like standard file i/o which defeats the whole reason i'd use vmem. Adding, span would help here, but it doesn't go near enough to to be a solution since these data structures aren't simple arrays.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
unsafe isn't a problem. This has nothing to do with a desire not to run unsafe code Again, what it has to do with is mapping a complex managed data structure to a file using Vmem. It's not doable. At best, you resolve to something much like standard file i/o which defeats the whole reason i'd use vmem. Adding, span would help here, but it doesn't go near enough to to be a solution since these data structures aren't simple arrays.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
Then just wrap the C API that does what you want. Anything you can do in C you can do in C# by using it like C. So it is doable just maybe not how you like.
can't do that either because it ties it to a platform. the goal is cross platform. At best i'd have to do two binaries per platform. and it would only support a limited number of them. So it doesn't fulfill the requirements. If I didn't care about being cross platform, I'd just use mixed mode C++. It's okay that this isn't doable. I accept it. It would just be nice if it was.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
-
That Ezra Taft Benson, while true, is one of the dumbest remarks I've seen, and is used by some groups to put down government. The point of government is to take your money and do what's best for the people as a whole. You can argue that isn't what happens in some cases, but that misses the point. Government generally is the only entity that takes risks when the reward isn't obvious. That where just about all of our technology comes from because industry won't invest without the promise of fairly quick rewards.
I have seen a similar quote attributed to Thomas Jefferson. I think it is less about government per se, but more about the scale of government.
-
can't do that either because it ties it to a platform. the goal is cross platform. At best i'd have to do two binaries per platform. and it would only support a limited number of them. So it doesn't fulfill the requirements. If I didn't care about being cross platform, I'd just use mixed mode C++. It's okay that this isn't doable. I accept it. It would just be nice if it was.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
You don't need multiple native or managed binaries for this. You can just wrap each platform and detect what platform you're on in the .NET runtime via RuntimeInformation class. So you would probably only need one for Win32 and one for POSIX (aka Linux, BSD and macOS). Because a .NET lib doesn't exist for what you need thats portable, you will have to make one that is.