64bit method call slow C# - c#

HI i have a 32bit application being ported to 64bit
somehow method calls of 64bit is a lot slower than 32bit.
code example
class huge_class
{
class subclass0{}
class subclass1{}
class subclass2{}
class subclass3{}
class subclass4{}
class subclass5{}
class subclass6{}
class subclass7{}
//so on... say 300
private object[] GetClassObj(Stopwatch x)
{
Console.WriteLine(x.ElapsedMilliseconds.ToString()); //<- the latency can be observed here, the time it takes to execute this line takes a big amount of time
object[] retObj = new object[300];
retObj[0] = new subclass0();
retObj[1] = new subclass1();
retObj[2] = new subclass2();
retObj[3] = new subclass3();
retObj[4] = new subclass4();
retObj[5] = new subclass5();
retObj[6] = new subclass6();
//so on... to 299
}
}
Class CallingClass{
static void Main(string[] args)
{
Console.WriteLine("Ready");
Console.ReadKey();
huge_class bigClass = new huge_class();
Console.WriteLine("Init Done");
Console.ReadKey();
Stopwatch tmr = Stopwatch.StartNew();
object[] WholeLottaObj = bigClass.GetClassObj(tmr);
Console.WriteLine(tmr.ElapsedMilliseconds.ToString());
Console.WriteLine("Done");
Console.ReadKey();
}
for some odd reason on 32bit the GetClassObj is entered faster than on its 64bit version
what am i doing wrong

This may be due to cache coherency. Don't forget that each reference will be twice as large on a 64-bit machine as it is on a 32-bit machine. That means:
Each of your instance objects is going to be bigger, so they'll be spread out further in memory (there's more per-object overhead in x64 anyway, and any reference fields will be twice the size)
The array itself will be about twice as big
Now it could easily be that in the 32-bit CLR you were just within one of the fastest caches on your CPU - whereas on the 64-bit CLR you've gone outside it so it's having to swap memory in and out of that cache, either to another cache or to main memory.
That's why x86 is the default for executable projects in VS2010 (and possibly 2008; not sure). This blog post goes into a lot more detail.

Why it should be faster in the first place? 64-bit pointer operations are twice as heavy (in memory terms), so it's natural for 64-bit app to be slower.

Related

How do I properly dispose and free the memory used for V8.Net.V8Engine instances?

I'm running into an issue when using my V8Engine instance, it appears to have a small memory leak, and disposing of it, as well as forcing the garbage collection doesn't seem to help much. It will eventually throw an AccessViolationException on V8Enging local_m_negine = new V8Engine() claiming a Fatal error in heap setup, Allocation failed - process out of memory and Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Monitoring the program's memory usage through Task manager whilst running confirms that it is leaking memory, around 1000 KB every couple of seconds I think. I suspect it is the variables being declared within the executed script not being collected, or something to do with the GlobalObject.SetProperty method. Calling V8Engine.ForceV8GarbageCollection(), V8Engine.Dispose() and even GC.WaitForPendingFinalizers() & GC.Collect() doesn't prevent this memory being leaked (Although it is worth noting that it seems to leak it slower with these commands in place, and I know I shouldn't use GC but it was there as a last resort to see if it would fix the issue.)
A tangential issue that could also provide a solution is the inability to clear the execution context for V8Engine. I am required to dispose and re-instantiate the engine for each script, which I believe is where the memory leak is happening, otherwise I run into issues where variables have already been declared, causing V8Engine.Execute() to throw an exception saying such.
I can definitely confirm that the memory leak is something to do with the V8Engine Implementation, as running the older version of this program that uses Microsoft.JScript has no such memory leak, and the memory used remains consistent.
The affected code is as follows;
//Create the V8Engine and dispose when done
using (V8Engine local_m_engine = new V8Engine())
{
//Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
//Execute the script
result = local_m_engine.Execute(script);
//Please just clear everything I can't cope.
local_m_engine.ForceV8GarbageCollection();
local_m_engine.GlobalObject.Dispose();
}
EDIT:
Not sure how useful this will be but I've been running some memory profiling tools on it and have learnt that after running an isolated version of the original code, My software ends up with a large amount of instances of IndexedObjectList's full of null values (see here: http://imgur.com/a/bll5K). It appears to have one instance of each class for each V8Engine instance that is made, but they aren't being disposed or freed. I cant help but feel like I'm missing a command or something here.
The code I'm using to test and recreate the memory leak that the above implementation causes is as follows:
using System;
using V8.Net;
namespace V8DotNetMemoryTest
{
class Program
{
static void Main(string[] args)
{
string script = #" var math1 = 5;
var math2 = 10;
result = 5 + 10;";
Handle result;
int i = 0;
V8Engine local_m_engine;
while (true)
{
//Create the V8Engine and dispose when done
local_m_engine = new V8Engine();
//Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
//local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
//Execute the script
result = local_m_engine.Execute(script);
Console.WriteLine(i++);
result.ReleaseManagedObject();
result.Dispose();
local_m_engine.Dispose();
GC.WaitForPendingFinalizers();
GC.Collect();
local_m_engine = null;
}
}
}
}
Sorry, I had no idea this question existed. Make sure to use the v8.net tag.
Your problem is this line:
result = local_m_engine.Execute(script);
The result returned is never disposed. ;) You are responsible for returned handles. Those handles are struct values, not class objects.
You could also do using (result = local_m_engine.Execute(script)) { ... }
There is a new version released. I am finally resurrecting this project again as I will need it for the FlowScript VPL project - and it now supports .Net Standard as well for cross-platform support!

SharpDX memory fragmentation

I am working on a .NET 3.5 application which uses SharpDX to render tiled 2D images.
Textures (Texture2D) are loaded into a cache on-demand, and are created in the managed pool.
Textures are disposed of when no longer required, and I have verified that Dispose() is called correctly. SharpDX object tracking indicates that there are no textures being finalized.
The issue is that large amounts of unmanaged heap memory used by the textures continues to be reserved after disposal. This memory is reused when loading a new texture, so memory is not being leaked.
However, another part of the application also requires significant chunks of memory to process new images. Because these heaps are still present, even though the textures have been disposed, there is not enough contiguous memory to load another image (can be hundreds of MB).
If I allocate unmanaged meory using AllocHGlobal, the resulting
heap memory completely vanishes again after calling FreeHGlobal.
VMMap shows the unmanaged heap (red) after heavy usage of the application.
We can see here that unmanaged heap accounts for ~380MB, even though only ~20MB is actually committed at this point.
Long term, the application is being ported to 64-bit. However, this is not trivial due to unmanaged dependencies. Also, not all users are on 64-bit machines.
EDIT: I've put together a demonstration of the issue - create a WinForms application and install SharpDX 2.6.3 via Nuget.
Form1.cs:
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using SharpDX.Direct3D9;
namespace SharpDXRepro {
public partial class Form1 : Form {
private readonly SharpDXRenderer renderer;
private readonly List<Texture> textures = new List<Texture>();
public Form1() {
InitializeComponent();
renderer = new SharpDXRenderer(this);
Debugger.Break(); // Check VMMap here
LoadTextures();
Debugger.Break(); // Check VMMap here
DisposeAllTextures();
Debugger.Break(); // Check VMMap here
renderer.Dispose();
Debugger.Break(); // Check VMMap here
}
private void LoadTextures() {
for (int i = 0; i < 1000; i++) {
textures.Add(renderer.LoadTextureFromFile(#"D:\Image256x256.jpg"));
}
}
private void DisposeAllTextures() {
foreach (var texture in textures.ToArray()) {
texture.Dispose();
textures.Remove(texture);
}
}
}
}
SharpDXRenderer.cs:
using System;
using System.Linq;
using System.Windows.Forms;
using SharpDX.Direct3D9;
namespace SharpDXRepro {
public class SharpDXRenderer : IDisposable {
private readonly Control parentControl;
private Direct3D direct3d;
private Device device;
private DeviceType deviceType = DeviceType.Hardware;
private PresentParameters presentParameters;
private CreateFlags createFlags = CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded;
public SharpDXRenderer(Control parentControl) {
this.parentControl = parentControl;
InitialiseDevice();
}
public void InitialiseDevice() {
direct3d = new Direct3D();
AdapterInformation defaultAdapter = direct3d.Adapters.First();
presentParameters = new PresentParameters {
Windowed = true,
EnableAutoDepthStencil = true,
AutoDepthStencilFormat = Format.D16,
SwapEffect = SwapEffect.Discard,
PresentationInterval = PresentInterval.One,
BackBufferWidth = parentControl.ClientSize.Width,
BackBufferHeight = parentControl.ClientSize.Height,
BackBufferCount = 1,
BackBufferFormat = defaultAdapter.CurrentDisplayMode.Format,
};
device = new Device(direct3d, direct3d.Adapters[0].Adapter, deviceType,
parentControl.Handle, createFlags, presentParameters);
}
public Texture LoadTextureFromFile(string filename) {
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) {
return Texture.FromStream(device, stream, 0, 0, 1, Usage.None, Format.Unknown, Pool.Managed, Filter.Point, Filter.None, 0);
}
}
public void Dispose() {
if (device != null) {
device.Dispose();
device = null;
}
if (direct3d != null) {
direct3d.Dispose();
direct3d = null;
}
}
}
}
My question therefore is - (how) can I reclaim the memory consumed by these unmanaged heaps after the textures have been disposed?
It seems the memory that's giving the issues is allocated by the nVidia driver. As far as I can tell, all the deallocation methods are properly called, so this might be a bug in the drivers. Looking around the internet shows some issues that seem related to this, though it's nothing serious enough to be worth referencing. I can't test this on an ATi card (I haven't seen one in like ten years :D).
So it seems like your options are:
Make sure your textures are big enough to never be allocated on the "shared" heaps. This allows the memory leak to proceed much slower - although it's still unreleased memory, it's not going to cause memory fragmentation anywhere near as serious as you're experiencing. You're talking about drawing tiles - this has historically been done with tilesets, which give you a lot better handling (though they also have drawbacks). In my tests, simply avoiding tiny textures all but eliminated the problem - it's hard to tell if it's just hidden or completely gone (both are quite possible).
Handle your processing in a separate process. Your main application would launch the other process whenever needed, and the memory will be properly reclaimed when the helper process exits. Of course, this only makes sense if you're writing some processing application - if you're making something that actually displays the textures, this isn't going to help (or at least it's going to be really tricky to setup).
Do not dispose of the textures. Managed texture pool handles paging the texture to and from the device for you, and it even allows you to use priorities etc., as well as flushing the whole on-device (managed) memory. This means that the textures will remain in your process memory, but it seems that you'll still get better memory usage than with your current approach :)
Possibly, the problems might be related to e.g. DirectX 9 contexts only. You might want to test with one of the newer interfaces, like DX10 or DXGI. This doesn't necessarily limit you to DX10+ GPUs - but you will lose support for Windows XP (which isn't supported anymore anyway).

Loading many large photos into a Panel efficiently

How do I load many large photos from a directory and its sub-directories in such a way as to prevent an OutOfMemoryException?
I have been using:
foreach(string file in files)
{
PictureBox pic = new PictureBox() { Image = Image.FromFile(file) };
this.Controls.Add(pic);
}
which has worked until now. The photos that I need to work with now are anywhere between 15 and 40MB's each, and there could be hundreds of them.
You're attacking the garbage collector with this approach. Loading 15-40mb objects in a loop will always invite an OutOfMemoryException. This is because the objects go straight onto the large object heap, all objects > 85K do. Large objects become Gen 2 objects immediately and the memory is not automatically compacted as of .Net 4.5.1 (you request it) and will not be compacted at all in earlier versions.
Therefore even if you get away with initially loading the objects and the app keeps running, there is every chance that these objects, even when dereferenced completely, will hang around, fragmenting the large object heap. Once fragmentation occurs and for example the user closes the control to do something else for a minute or two and opens the control again, it is much more likely all the new objects will not be able to slot in to the LOH - the memory must be contiguous when allocation occurs. The GC runs collections on Gen 2 and LOH much less often for performance reasons - memcpy is used by the GC in the background and this is expensive on larger blocks of memory.
Also, the memory consumed will not be released if you have all of these images referenced from a control that is in use as well, imagine tabs. The whole idea of doing this is misconceived. Use thumbnails or load full scale images as needed by the user and be careful with the memory consumed.
UPDATE
Rather than telling you what you should and should not do I have decided to try to help you do it :)
I wrote a small program that operates on a directory containing 440 jpeg files with a total size of 335 megabytes. When I first ran your code I got the OutOfMemoryException and the form remained unresponsive.
Step 1
The first thing to note is if you are compiling as x86 or AnyCpu you need to change this to x64. Right click project, go to Build tab and set the target platform to x64.
This is because the amount of memory that can be addressed on a 32 bit x86 platform is limited. All .Net processes run within a virtual address space and the CLR heap size will be whatever the process is allowed by the OS and is not really within the control of the developer. However, it will allocate as much memory as is available - I am running on 64 bit Windows 8.1 so changing the target platform gives me an almost unlimited amount of memory space to use - right up to the limit of physical memory your process will be allowed.
After doing this running your code did not cause an OutOfMemoryException
Step 2
I changed the target framework to 4.5.1 from the default 4.5 in VS 2013. I did this so I could use GCSettings.LargeObjectHeapCompactionMode, as it is only available in 4.5.1 . I noticed that closing the form took an age because the GC was doing a crazy amount of work releasing memory. Basically I would set this at the end of the loadPics code as it will allow the large object heap to not get fragmented on the next blocking garbage collection. This will be essential for your app I believe so if possible try to use this version of the framework. You should test it on earlier versions too to see the difference when interacting with your app.
Step 3
As the app was still unresponsive I made the code run asynchronously
Step 4
As the code now runs on a separate thread to the UI thread it caused a GUI cross thread exception when accessing the form, so I had to use Invoke which posts a message back to the UI thread from the code's thread. This is because UI controls can only be accessed from a UI thread.
Code
private async void button1_Click(object sender, EventArgs e)
{
await LoadAllPics();
}
private async Task LoadAllPics()
{
IEnumerable<string> files = Directory.EnumerateFiles(#"C:\Dropbox\Photos", "*.JPG", SearchOption.AllDirectories);
await Task.Run(() =>
{
foreach(string file in files)
{
Invoke((MethodInvoker)(() =>
{
PictureBox pic = new PictureBox() { Image = Image.FromFile(file) };
this.Controls.Add(pic);
}));
}
}
);
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
}
You can try resizing the image when you are putting on the UI.
foreach(string file in files)
{
PictureBox pic = new PictureBox() { Image = Image.FromFile(file).resizeImage(50,50) };
this.Controls.Add(pic);
}
public static Image resizeImage(this Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}

Extreme Memory Conditions Testing : How to saturate RAM?

I would like to write a small piece of program that launches threads, consumes available RAM memory in a linear fashion, until a certain level, and stops (ideally, pauses until "enough" memory is freed and continues creating threads after that, and so on.)
I tried the following, but the list.Add(new byte[]) requires contiguous RAM space and drops an OutOfMemoryException, which is NOT what I am trying to simulate.
EDIT :
I have a multi-threaded memory-hungry application that eats up a whole bunch of RAM GB's. All I want is to isolate/reproduce that situation in "Lab conditions" to tackle it, i.e write an adaptive mem-monitoring / thread-limiter draft. I am using x64 OS an x64 Platform.
To make it clear : The result I want to see is the Task Manager Memory Monitor going up straight due to the program.
static void Main(string[] args)
{
ComputerInfo ci = new ComputerInfo();
D("TOTAL PHYSICAL MEMORY : " + Math.Round(ci.TotalPhysicalMemory / Math.Pow(10,9),3) +" GB");
//########### Fill Memory ###############
var list = new List<byte[]>();
Thread FillMem= new Thread(delegate()
{
while (Process.GetCurrentProcess().PrivateMemorySize64 < MAX_MEM_LEVEL)
{
list.Add(new byte[1024 * 10000]); //<- I Need to change this
Thread.Sleep(100);
}
});
FillMem.Start();
//########### Show used Memory ###############
Thread MonitorMem = new Thread(delegate()
{
while (true)
{
D("PROCESS MEMORY : " + Math.Round(Process.GetCurrentProcess().PrivateMemorySize64 / Math.Pow(10, 6), 3) + " MB");
Thread.Sleep(1000);
}
});
MonitorMem.Start();
Console.Read();
}
The question is still quite confusing; it is not clear to me what you are trying to do here and why.
If you genuinely want to be consuming physical memory -- that is, telling the operating system no, really do not use this portion of the physical RAM chip that is installed in the machine for anything other than what I say -- then I would probably use the aptly-named AllocateUserPhysicalPages function from unmanaged code.
That will then reduce the amount of physical memory that is available for other uses, forcing more virtual memory pages to go out to the page file.
Other than making all the programs running on your machine a whole lot slower, I'm not sure what you intend to accomplish by this. Can you clarify?
The thing is that with C# you can not grow more then approximately 1.2 GB of RAM on 32 bit .NET framework. You can have even 8GB of RAM on your 64 bit machine, but if the process you run was compiled for 32bit architecture, it will lead to OutOfMemoryException as soon as it reaches approx 1.2GB.
For this kind of testing I would suggest choosing other type of languages/frameworks.
EDIT
A good link on subject:
is-there-a-memory-limit-for-a-single-net-process
If the problem that you're running into is that your process is running out of virtual memory space before the hardware is running out of physical memory space then you could just spin up a number (5 maybe?) processing with your code (and something to stop them at say 1-2 GB so they don't OOM themselves). It's probably not as good of a solution as a unmanaged call to allocate memory, but it would be easy enough to do.

Maximum number of threads in a .NET app?

What is the maximum number of threads you can create in a C# application? And what happens when you reach this limit? Is an exception of some kind thrown?
There is no inherent limit. The maximum number of threads is determined by the amount of physical resources available. See this article by Raymond Chen for specifics.
If you need to ask what the maximum number of threads is, you are probably doing something wrong.
[Update: Just out of interest: .NET Thread Pool default numbers of threads:
1023 in Framework 4.0 (32-bit environment)
32767 in Framework 4.0 (64-bit environment)
250 per core in Framework 3.5
25 per core in Framework 2.0
(These numbers may vary depending upon the hardware and OS)]
Mitch is right. It depends on resources (memory).
Although Raymond's article is dedicated to Windows threads, not to C# threads, the logic applies the same (C# threads are mapped to Windows threads).
However, as we are in C#, if we want to be completely precise, we need to distinguish between "started" and "non started" threads. Only started threads actually reserve stack space (as we could expect). Non started threads only allocate the information required by a thread object (you can use reflector if interested in the actual members).
You can actually test it for yourself, compare:
static void DummyCall()
{
Thread.Sleep(1000000000);
}
static void Main(string[] args)
{
int count = 0;
var threadList = new List<Thread>();
try
{
while (true)
{
Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
newThread.Start();
threadList.Add(newThread);
count++;
}
}
catch (Exception ex)
{
}
}
with:
static void DummyCall()
{
Thread.Sleep(1000000000);
}
static void Main(string[] args)
{
int count = 0;
var threadList = new List<Thread>();
try
{
while (true)
{
Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
threadList.Add(newThread);
count++;
}
}
catch (Exception ex)
{
}
}
Put a breakpoint in the exception (out of memory, of course) in VS to see the value of counter. There is a very significant difference, of course.
i did a test on a 64bit system with c# console, the exception is type of out of memory, using 2949 threads.
I realize we should be using threading pool, which I do, but this answer is in response to the main question ;)
I would recommend running ThreadPool.GetMaxThreads method in debug
ThreadPool.GetMaxThreads(out int workerThreadsCount, out int ioThreadsCount);
Docs and examples:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadpool.getmaxthreads?view=netframework-4.8
You should be using the thread pool (or async delgates, which in turn use the thread pool) so that the system can decide how many threads should run.
Jeff Richter in CLR via C#:
"With version 2.0 of the CLR, the maximum number
of worker threads default to 25 per CPU in the machine
and the maximum number of I/O
threads defaults to 1000. A limit of 1000 is effectively no limit at all."
Note this is based on .NET 2.0. This may have changed in .NET 3.5.
[Edit] As #Mitch pointed out, this is specific to the CLR ThreadPool. If you're creating threads directly see the #Mitch and others comments.
You can test it by using this snipped code:
private static void Main(string[] args)
{
int threadCount = 0;
try
{
for (int i = 0; i < int.MaxValue; i ++)
{
new Thread(() => Thread.Sleep(Timeout.Infinite)).Start();
threadCount ++;
}
}
catch
{
Console.WriteLine(threadCount);
Console.ReadKey(true);
}
}
Beware of 32-bit and 64-bit mode of application.

Categories