Overhead of calling GC.GetTotalMemory(false) - c#

In the company I work at we have a bunch of web applications in which we display in the website's footer some information useful for the developers (such as the assembly version).
Performance wise (I'm not caring for the UX aspect of it), would it be a bad idea to show the memory usage by calling GC.GetTotalMemory(false)? Should I worry having this call performed on every request?

I got curious when I saw your question since it was not the regular stuff, and decided to give it a try.
Created a simple web site and in default.aspx filled almost 1 GB of small objects (10 million byte arrays with 64 bytes each) into the heap, then called GC.GetTotalMemory 100 times and before each time by adding a new object so that if there is any cached value, it would be obsolete.
The average execution time for GC.GetTotalMemory(false) was 0,000687 milliseconds!
I have a Win 7 64 bit 2 cpu (8 core total) HP with 8 GB RAM.
I think, your developers will have a good metric down there :)
Default.aspx.cs:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
private List<object> objects = new List<object>();
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10000000; i++)
{
objects.Add(new byte[64]);
}
double averageDuration = 0;
for (int x = 0; x < 100; x++)
{
objects.Add(new byte[64]);
Stopwatch sw = Stopwatch.StartNew();
Response.Write("Total memory: " + GC.GetTotalMemory(false) + " / ");
sw.Stop();
averageDuration += sw.Elapsed.TotalMilliseconds;
Response.Write("Duration: " + sw.Elapsed.TotalMilliseconds + "<br/>");
}
Response.Write("Average Duration: " + (averageDuration / 100));
}
}

Related

C# simple program slow

I have a simple program written in C# and I ran it in two laptops same specs but one has Windows 8 and the other has Windows 10 and I measure the time in milliseconds and get the difference between the start and the end but in windows 8 it takes approx 1k milliseconds while in windows 10 it takes approx 15k milliseconds. Why this huge difference?
This is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
Console.WriteLine(milliseconds);
for(int i = 0; i < 100000000; i++)
{
if(i%10000==0)
Console.WriteLine(i);
}
long milliseconds2 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
Console.WriteLine(milliseconds2);
Console.WriteLine("Diff " + (milliseconds2-milliseconds));
Console.ReadLine();
}
}
}

Streaming short[] is ~800 times slower than streaming byte[] - How to speed it up?

I'm transferring some large short[] arrays between processes using WCF in streaming mode, and I've run into a problem where the transfer is extremely slow.
I've done some tests, and it turns out that transferring a short[] array is around 800 times slower than using a byte[] array that contains the same number of bytes.
I assume that I must be doing something wrong here, since this behaviour cannot be expected.
Given the reproduction below, can anyone suggest how I can speed it up?
Note that I'm using streaming mode because the arrays are VERY large, and using non-streaming mode appears to use a total of three times the size of the array during transfer. (I'm wrapping a third-party 32-bit managed DLL in a separate process so that it can be called from a 64-bit C# program via WCF.)
Here's the server and client code. It seems quite long, but it's the shortest complete repro I can come up with...
The code is very simple: The WCF interface just has two methods, one taking a short[] parameter and another with a byte[] parameter. I test it by passing a short[] and a byte[] each containing the same number of bytes, and use a Stopwatch to time how long it takes.
To simplify things, I've put a copy of the ITest interface into both the client and the server source code to avoid having a third library - the real code does it properly.
These are both just console apps - you just need to compile and run them in any order, and then press ENTER in the client app to run the test.
Also note that I'm using .Net 4.6.2, but I have similar results with other versions.
CLIENT
using System;
using System.Diagnostics;
using System.ServiceModel;
using Shared;
namespace Shared
{
[ServiceContract]
interface ITest
{
[OperationContract]
void ShortTest(short[] array);
[OperationContract]
void ByteTest(byte[] array);
}
}
namespace Client
{
class Client
{
static void Main()
{
int arraySizeInBytes = 10 * 1024 * 1024;
var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxReceivedMessageSize = 4*arraySizeInBytes + 1024,
SendTimeout = TimeSpan.FromHours(1), // To allow debugging without timeouts.
ReceiveTimeout = TimeSpan.FromHours(1),
ReaderQuotas = {MaxArrayLength = 4*arraySizeInBytes + 1024},
TransferMode = TransferMode.Streamed
};
var channelFactory = new ChannelFactory<ITest>(binding, "net.pipe://localhost/wcftest");
var proxy = channelFactory.CreateChannel();
short[] shorts = new short[arraySizeInBytes/sizeof(short)];
for (int i = 0; i < shorts.Length; ++i) // Touch entire array to ensure memory allocated.
shorts[i] = 1;
byte[] bytes = new byte[arraySizeInBytes];
for (int i = 0; i < bytes.Length; ++i) // Touch entire array to ensure memory allocated.
bytes[i] = 1;
Stopwatch sw = new Stopwatch();
while (true)
{
Console.WriteLine("Press <ENTER> to call ByteTest() and ShortTest()");
Console.ReadLine();
Console.WriteLine("Calling ByteTest()");
sw.Restart();
proxy.ByteTest(bytes);
Console.WriteLine("ByteTest() took " + sw.Elapsed);
Console.WriteLine("Calling ShortTest()");
sw.Restart();
proxy.ShortTest(shorts);
Console.WriteLine("ShortTest() took " + sw.Elapsed);
}
}
}
}
SERVER
using System;
using System.ServiceModel;
using System.Threading;
using Shared;
namespace Shared
{
[ServiceContract]
interface ITest
{
[OperationContract]
void ShortTest(short[] array);
[OperationContract]
void ByteTest(byte[] array);
}
}
namespace Server
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class Server : ITest
{
static void Main()
{
int arraySizeInBytes = 10 * 1024 * 1024;
var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxReceivedMessageSize = 4*arraySizeInBytes + 1024,
SendTimeout = TimeSpan.FromHours(1), // To allow debugging without timeouts.
ReceiveTimeout = TimeSpan.FromHours(1),
ReaderQuotas = {MaxArrayLength = 4*arraySizeInBytes + 1024 },
TransferMode = TransferMode.Streamed
};
var serviceHost = new ServiceHost(new Server());
serviceHost.AddServiceEndpoint(typeof(ITest), binding, "net.pipe://localhost/wcftest");
serviceHost.Open();
Console.WriteLine("Server started. Close console to stop.");
Thread.Sleep(TimeSpan.FromHours(10));
}
public void ShortTest(short[] array)
{
Console.WriteLine("ShortTest() received array of size " + array.Length);
}
public void ByteTest(byte[] array)
{
Console.WriteLine("ByteTest() received array of size " + array.Length);
}
}
}
The results I get on my system are as follows:
Press <ENTER> to call ByteTest() and ShortTest()
Calling ByteTest()
ByteTest() took 00:00:00.0519079
Calling ShortTest()
ShortTest() took 00:00:41.9868413
Press <ENTER> to call ByteTest() and ShortTest()
Calling ByteTest()
ByteTest() took 00:00:00.0344547
Calling ShortTest()
ShortTest() took 00:00:41.4307394
Press <ENTER> to call ByteTest() and ShortTest()
Does anyone have any ideas how to speed up the transfer of the short[] data?
At the moment I expect I'll just have to convert it to a byte[] myself, but that is most unsatisfactory.

Why the loop is taking so long and so slow?

I created a new class for the testing:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenHardwareMonitor.Hardware;
using System.Diagnostics;
using DannyGeneral;
using System.Windows.Forms;
using System.Threading;
using System.Management;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
namespace HardwareMonitoring
{
class CpuUsages
{
public static string processes;
public static string cputest()
{
PerformanceCounter cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
var unused = cpuCounter.NextValue(); // first call will always return 0
System.Threading.Thread.Sleep(1000); // wait a second, then try again
//Console.WriteLine("Cpu usage: " + cpuCounter.NextValue() + "%");
processes = "Cpu usage: " + cpuCounter.NextValue() + "%";
return processes;
}
}
}
Then in form1 i added a new timer set it to 1000ms enable it when running the program and inside the timer tick event i did:
private void timer3_Tick(object sender, EventArgs e)
{
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
CpuUsages.cputest();
cpuusage = CpuUsages.processes;
label26.Text = cpuusage;
}
}
This way it's working very slow take a long time to make the loop foreach.
In general i wanted to loop over each running process and get it's cpuusage.
But if i remove the foreach loop like this:
private void timer3_Tick(object sender, EventArgs e)
{
Process[] processes = Process.GetProcesses();
CpuUsages.cputest();
cpuusage = CpuUsages.processes;
label26.Text = cpuusage;
}
Then it will work fast i will see in label26 the cpuusage updating eavery second.
The problem is that it will show the cpuusage for only on process.
What can i do to solve it ?
In general i wanted to create automatic number of labels for each process in the list and display each process cpuusage. But it's so slow and take so long when i use the foreach loop.
Is there any way to solve it ?
This:
foreach (Process process in processes)
{
CpuUsages.cputest();
cpuusage = CpuUsages.processes;
label26.Text = cpuusage;
}
will make your program sleeps for 1 second * (number of processes running on your machine). No wonder the foreach loop is slow.
Remove those Sleep calls, and have your loop running in another Thread, avoiding slowing down the User interface.
Also I don't see why you are iterating over the processes returned by Process.GetProcesses() : you are not using them.

Project Euler #4 in C#

I'm attempting to do Project Euler problem #4 in C#. The problem I'm having is that when the code runs a console window briefly appears and then goes away. I don't know what the problem could be as I'm relatively new to programming.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (int i = 1000; i > 100; i--)
for (int j = 1000; j > 100; j--)
PalCheck(i * j);
}
static void PalCheck(int original)
{
var reversed = new string(Convert.ToString(original).ToCharArray().Reverse().ToArray());
if (Convert.ToString(original) == reversed)
Console.WriteLine(original);
Console.ReadKey();
}
}
}
The code seems to be stuck at the line
Console.ReadKey() as at this line of code, the program is waiting for some input key.
Since you have not used any message before ReadKey(), you don't realize that the program is waiting for some input and not stuck.
Move Console.ReadKey() after PalCheck(i * j) and you should see the output on the console screen.

Find out battery charge capacity in percentage using C# or .NET

I have an application that gets detailed system information, and I have been able to get the percent of charge remaining but not the percent of the battery itself.
Explanation: As time goes on, the battery slowly gets worse and worse, and some applications, like Dell Support Center on Laptops, display the status of the battery, not the status of the charge, which used to be 100% but now is 90%.
How can I get this value in C# or .NET?
Don't have a laptop to test with, but I'm guessing you could use the WMI class Win32_Battery.
It has two fields that look interesting - DesignCapacity, which tells you
Design capacity of the battery in milliwatt-hours.
and FullChargeCapacity, which has the fascinating note that
Full charge capacity of the battery in milliwatt-hours. Comparison of the value to the DesignCapacity property determines when the battery requires replacement.
So my guess is that you can use WMI to read these two values, and then calculate FullChargeCapacity/DesignCapacity to find the battery health percentage number.
EDIT
Here's a brief example of accessing WMI information using C#. I first added a reference to the System.Management assembly. Then:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
System.Management.ObjectQuery query = new ObjectQuery("Select * FROM Win32_Battery");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject mo in collection)
{
foreach (PropertyData property in mo.Properties)
{
Console.WriteLine("Property {0}: Value is {1}", property.Name, property.Value);
}
}
}
}
}
Also, note that you are basically running a SQL-like query against WMI, so you can vary that if you want. Windows Management Instrumentation Query Language, or WQL, is what you want to search for to learn more about it.
Also take a look at ahawker's answer, it may end up being more helpful if WMI isn't properly capturing the battery data, as he notes.
It seems that you are looking for the values of FullChargeCapacity, DesignCapacity and CurrentCapacity. As someone who has solved this problem before, let me make a few comments.
The first route normally taken would be through a WMI query (Win32_Battery). However, on the test laptops I ran the WMI query (Win32_Battery) against, which included multiple manufacturers, I consistently ran into the problem of FullChargeCapacity always returning zero. Since that didn't work, I re-wrote my solution using Win32 API and was successfully able to get accurate values that way.
Hopefully, WMI will work for you. However, if you experience the same issues I did, here is a summary of the steps required for Win32API.
Use SetupDiGetClassDevs to get a device handle to the battery (GUID_DEVCLASS_BATTERY).
Use SetupDiEnumDeviceInterfaces to get the device data (SP_DEVICE_INTERFACE_DATA).
Use SetupDiGetDeviceInterfaceDetail to get the device path (SP_DEVICE_INTERFACE_DETAIL_DATA).
Use CreateFile with the device path to get handle to battery.
Use DeviceIoControl with battery handle, IOCTL_BATTERY_QUERY_TAG to retrieve battery query info (BATTERY_QUERY_INFORMATION).
Use DeviceIoControl with battery handle, IOCTL_BATTERY_QUERY_INFORMATION and marshalled structs to to retrieve battery info (BATTERY_INFORMATION).
Also see the Enumerating Battery Devices post on MSDN as I found that quite helpful.
I can post my solution if necessary but with all the native struct definitions, it ends up around 500 lines of code.
Example source code: https://gist.github.com/ahawker/9715872
No need to unnecessary complicate things. Try something like:
using System.Management;
PowerStatus pwr = SystemInformation.PowerStatus;
String strBatteryChargingStatus;
strBatteryChargingStatus = pwr.BatteryChargeStatus.ToString();
MessageBox.Show("battery charge status : " + batterystatus);
String strBatterylife;
strBatterylife = pwr.BatteryLifePercent.ToString();
MessageBox.Show("Battery life: "+batterylife);
In this way you can get all of the battery information.
You can use the System.Windows.Forms.PowerStatus class - http://msdn.microsoft.com/en-us/library/system.windows.forms.powerstatus.aspx
PowerStatus p = SystemInformation.PowerStatus;
int a = (int)(p.BatteryLifePercent * 100);
MessageBox.Show(""+a);
WMI worked for me (tested on 3 notebooks of different brands), but I had to use something like this:
new ManagementObjectSearcher(#"\\localhost\root\wmi",
"Select FullChargedCapacity From BatteryFullChargedCapacity");
// use value of resultingInstance.Properties["FullChargedCapacity"]
new ManagementObjectSearcher(#"\\localhost\root\wmi",
"Select DesignedCapacity From BatteryStaticData");
//use value of resultingInstance2.Properties["DesignedCapacity"]
BatteryChargeStatus.Text = SystemInformation.PowerStatus.BatteryChargeStatus.ToString();
BatteryFullLifetime.Text = SystemInformation.PowerStatus.BatteryFullLifetime.ToString();
BatteryLifePercent.Text = SystemInformation.PowerStatus.BatteryLifePercent.ToString();
BatteryLifeRemaining.Text = SystemInformation.PowerStatus.BatteryLifeRemaining.ToString();
PowerLineStatus.Text = SystemInformation.PowerStatus.PowerLineStatus.ToString();
If you want to perform some operation just convert these string values into the integer.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace batterie
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
showbattrie();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void showbattrie()
{
PowerStatus status = SystemInformation.PowerStatus;
textBox1.Text = status.BatteryLifePercent.ToString("P0");
}
}
}
Simple code to get Battery Level in C#
protected void batteryLevel ()
{
var filter = new IntentFilter(Intent.ActionBatteryChanged);
var battery = RegisterReceiver(null, filter);
int level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
int scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);
double level_0_to_100 = Math.Floor (level * 100D / scale);
}

Categories

Resources