How can I have a fast and high resolution timer on Windows? - windows

I'm writing a profiler that queries a timer whenever a function enters or exits. So it's possible that it's queried thousands of times a second.
Initially I used QueryPerformanceCounter, despite the fact it's high resolution, it turned out to be quite slow. According to What happens when QueryPerformanceCounter is called? question I also got a noticeable slowdown when I use QPC in the profiler, but probably not that bad 1-2ms figure. If I replace it with GetTickCount I don't notice any slowdown, but that function is inaccurate for the profiling.
The mentioned question mention affinity masks. I tried to use SetProcessAffinityMask(GetCurrentProcess(), 1) to bind it but it doesn't improve the performance at all.
I don't know whether it matters or not, but so far I tested it on Windows that runs in VirtualBox on a Linux host. Could it be the problem?

The highest resolution timers I'm aware of on Windows are the multimedia timers available via winmm.dll
Here's a class I've had lying around for my own perf testing needs - give 'er a whirl:
public class HighResTimer
{
private delegate void TimerEventHandler(int id, int msg, IntPtr user, int dw1, int dw2);
private const int TIME_PERIODIC = 1;
private const int EVENT_TYPE = TIME_PERIODIC;
[System.Runtime.InteropServices.DllImport("winmm.dll")]
private static extern int timeSetEvent( int delay, int resolution, TimerEventHandler handler, IntPtr user, int eventType);
[System.Runtime.InteropServices.DllImport("winmm.dll")]
private static extern int timeKillEvent(int id);
[System.Runtime.InteropServices.DllImport("winmm.dll")]
private static extern int timeBeginPeriod(int msec);
[System.Runtime.InteropServices.DllImport("winmm.dll")]
private static extern int timeEndPeriod(int msec);
private int _timerId;
private TimerEventHandler _handler = delegate {};
public event EventHandler OnTick;
public HighResTimer(int delayInMs)
{
timeBeginPeriod(1);
_handler = new TimerEventHandler(timerElapsed);
_timerId = timeSetEvent(delayInMs, 0, _handler, IntPtr.Zero, EVENT_TYPE);
}
public void Stop()
{
int res = timeKillEvent(_timerId);
timeEndPeriod(1);
_timerId = 0;
}
private void timerElapsed(int id, int msg, IntPtr user, int dw1, int dw2)
{
OnTick(this, new EventArgs());
}
}

Ended up using the RDTSC instruction directly. So I wrote a wrapper for it in GCC:
static inline unsigned long long rdtsc(void)
{
unsigned hi, lo;
asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
No slowdowns and apparently have quite higher resolution than QueryPerformanceCounter.
The code based on this answer.

Related

.Net Core fast alloc and zero initialise memory (cross-platform solution)

Is there a fast way to allocate and zero initialise a large block of memory using .Net Core?
Looking for a solution that works on both Windows and Linux platforms.
It seems the fastest method on Windows is to call kernel32 HeapAlloc function via PInvoke, this allocates and zeros a 1GB block of memory in less than 2 milliseconds.
However, I haven't found a way to achieve similar results on Linux whilst only using .Net Core.
I've tried the Marshal.AllocHGlobal method which does not zero the memory, and then zeroing the memory using Marshal.Copy to copy an array of zero bytes into the memory, but this gives poor performance i.e. 800 milliseconds compared to the 2 milliseconds above.
For my application the allocation and zeroing needs to be done in less than 10 milliseconds.
Does .Net Core provide a cross platform API that would give similar performance as Windows HeapAlloc or something like the C function calloc?
Test code below:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MemoryApp
{
class Program
{
static void Main(string[] args)
{
const int sizeBytes = 1_000_000_000;
Console.WriteLine($"Allocating memory of size: {sizeBytes} bytes.");
const int totalAttempts = 20;
for (int i = 0; i < totalAttempts; i++)
{
var stopwatch = Stopwatch.StartNew();
var allocatedMemory = new AllocatedMemory(sizeBytes);
stopwatch.Stop();
Console.WriteLine($"Allocated memory in {stopwatch.ElapsedTicks} ticks ({stopwatch.ElapsedMilliseconds} milliseconds).");
allocatedMemory.Dispose();
}
Console.ReadLine();
}
}
public unsafe class AllocatedMemory : IDisposable
{
public byte* MemoryAddress { get; }
#if USE_WINDOWS_HEAP
private IntPtr _heapPtr;
#else
private IntPtr _memoryPtr;
#endif
public AllocatedMemory(int sizeInBytes)
{
#if USE_WINDOWS_HEAP
var heapFlags = HeapFlags.HEAP_GENERATE_EXCEPTIONS | HeapFlags.HEAP_ZERO_MEMORY;
_heapPtr = Heap.HeapCreate(heapFlags, 0, 0);
MemoryAddress = (byte*)Heap.HeapAlloc(_heapPtr, heapFlags, (uint)sizeInBytes);
#else
// Memory allocated but not zeroed
_memoryPtr = Marshal.AllocHGlobal((IntPtr)sizeInBytes);
// Zero the memory
Marshal.Copy(new byte[sizeInBytes], 0, _memoryPtr, sizeInBytes);
MemoryAddress = (byte*)_memoryPtr;
#endif
}
~AllocatedMemory()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (MemoryAddress != null)
{
#if USE_WINDOWS_HEAP
Heap.HeapDestroy(_heapPtr);
#else
Marshal.FreeHGlobal(_memoryPtr);
#endif
}
}
}
}
#if USE_WINDOWS_HEAP
public class Heap
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr HeapCreate(HeapFlags flOptions, uint dwInitialsize, uint dwMaximumSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr HeapAlloc(IntPtr hHeap, HeapFlags dwFlags, uint dwSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool HeapDestroy(IntPtr hHeap);
}
[Flags]
public enum HeapFlags
{
HEAP_NO_SERIALIZE = 0x1,
HEAP_GENERATE_EXCEPTIONS = 0x4,
HEAP_ZERO_MEMORY = 0x8
}
#endif
}
In C# 7, .Net has introduced new constructs to work with memory which include Span and Memory
Span is defined as a ref struct, limited to allocation only on the Stack, i.e. reduces some potential use cases such as storing it as a field in a class. But you can work around these by using another type Memory

GetFinalPathNameByHandle fails for device handles

If I create a File handle using CreateFile for a path like "\\?\NUL" or "\\?\pipe\", the handle is mapped to a File object that's opened for the "\Device\Null" or "\Device\NamedPipe" kernel Device object. Since the GetFinalPathNameByHandle function supports the VOLUME_NAME_NT property, which already returns strings like "\Device\HarddiskVolume1\", I thought I would be able to obtain a similar path for a device handle. However, the call always fails, either with ERROR_INVALID_FUNCTION, or ERROR_INVALID_PARAMETER, depending on the access flags the file was opened with.
In fact, almost any call to similar functions fails -- like GetFileInformationByHandle, GetFileInformationByHandleEx, and even calls to NT functions like NtQueryInformationFile -- returning STATUS_INVALID_PARAMETER. The only functions that don't fail are GetFileType (able to identify a pipe), GetVolumeInformationByHandle (able to identify the driver), and NtQueryInformationFile with FileModeInformation.
All these functions work when used on any standard file, but they are not supported for device file handles. How can I obtain path information from a device handle? Are there some Nt or Io functions that would work? Is there some other way to identify a device if the only thing I have is the handle?
As RbMm and eryksun have pointed out, the driver which implements the object must be able to handle IRP_MJ_QUERY_INFORMATION, but if it doesn't, the name of the object can be obtained via NtQueryObject, passing ObjectNameInformation (1) to it, which will obtain the OBJECT_NAME_INFORMATION structure with the object name.
Since I intended to call it with C#, here is the P/Invoke code for it:
static class Ntdll
{
[DllImport("ntdll.dll")]
static extern int NtQueryObject(
IntPtr Handle, int ObjectInformationClass,
IntPtr ObjectInformation, int ObjectInformationLength,
out int ReturnLength
);
public static int NtQueryObject(IntPtr Handle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength)
{
int length;
int status = NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, out length);
if(status != 0) throw new Win32Exception(RtlNtStatusToDosError(status));
return length;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct OBJECT_NAME_INFORMATION
{
public ushort Length;
public ushort MaximumLength;
public string Buffer;
}
[DebuggerStepThrough]
public static void NtQueryObject(IntPtr Handle, out OBJECT_NAME_INFORMATION ObjectNameInformation)
{
IntPtr buffer = Marshal.AllocHGlobal(1024);
try{
Ntdll.NtQueryObject(Handle, 1, buffer, 1024);
ObjectNameInformation = Marshal.PtrToStructure<Ntdll.OBJECT_NAME_INFORMATION>(buffer);
}finally{
Marshal.FreeHGlobal(buffer);
}
}
}
The path can be then constructed by prepending "\\?\GlobalRoot" to the Buffer member.

waveOutGetPosition always returns zero

I'm using waveOutWrite to write several small buffers (80ms each). As they are playing, I'm calling this function to get the playback position:
uint GetWaveOutPosInMS()
{
WinMM.MMTIME mmtime = new WinMM.MMTIME();
mmtime.wType = 1;
WinMM.MMRESULT ret = WinMM.waveOutGetPosition(WaveOut, ref mmtime, (uint)Marshal.SizeOf(typeof(WinMM.MMTIME)));
return (mmtime.val);
}
Here are the relative extras as well:
[DllImport("winmm.dll")]
public static extern MMRESULT waveOutGetPosition(IntPtr hwo, ref MMTIME info, uint cbi);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MMTIME
{
public uint wType;
public uint val;
}
The waveOutGetPosition returns 0 (no error), but mmtime.val is always zero. MSDN isn't really clear on what "playback position" is relative to, just that it is reset on waveOutOpen and waveOutReset.. but does it always continue to increase across multiple waveOutWrite() calls? Any ideas as to why it would always be returning zero for me?
I had the MMTIME struct declared incorrectly. Odd that the function didn't report error, but based on other stuff I've read this function is dependant on the OEM so could see various weird results. It also appears asking for MS isn't as well tested as asking for SAMPLES, so I'll just ask for samples instead, and calculate MS myself.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MMTIME
{
public uint wType;
public uint val;
// Padding because val is actually a union
public uint pad;
}

How to take the snapshot of a IE webpage through a BHO (C#)

I am trying to build an IE BHO in C# for taking the snapshot of a webpage loaded in the IE browser. Here is what I'm trying to do:
public class ShowToolbarBHO : BandObjectLib.IObjectWithSite
{
IWebBrowser2 webBrowser = null;
public void SetSite (Object site)
{
.......
if (site != null)
{
......
webBrowser = (IWebBrowser2)site;
......
}
}
}
Also, I p/invoke the following COM methods:
[Guid("0000010D-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImportAttribute()]
public interface IViewObject
{
void Draw([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [MarshalAs(UnmanagedType.LPStruct)] ref COMRECT lprcBounds, [In] IntPtr lprcWBounds, IntPtr pfnContinue, int dwContinue);
int GetColorSet([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hicTargetDev, [Out] IntPtr ppColorSet);
int Freeze([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, out IntPtr pdwFreeze);
int Unfreeze([MarshalAs(UnmanagedType.U4)] int dwFreeze);
int SetAdvise([MarshalAs(UnmanagedType.U4)] int aspects, [MarshalAs(UnmanagedType.U4)] int advf, [MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);
void GetAdvise([MarshalAs(UnmanagedType.LPArray)] out int[] paspects, [MarshalAs(UnmanagedType.LPArray)] out int[] advf, [MarshalAs(UnmanagedType.LPArray)] out IAdviseSink[] pAdvSink);
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public class COMRECT
{
public int left;
public int top;
public int right;
public int bottom;
public COMRECT()
{
}
public COMRECT(int left, int top, int right, int bottom)
{
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
}
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisibleAttribute(true)]
[GuidAttribute("0000010F-0000-0000-C000-000000000046")]
[ComImportAttribute()]
public interface IAdviseSink
{
void OnDataChange([In]IntPtr pFormatetc, [In]IntPtr pStgmed);
void OnViewChange([MarshalAs(UnmanagedType.U4)] int dwAspect, [MarshalAs(UnmanagedType.I4)] int lindex);
void OnRename([MarshalAs(UnmanagedType.Interface)] object pmk);
void OnSave();
void OnClose();
}
Now When I take the snapshot:
I make a call CaptureWebScreenImage((IHTMLDocument2) webBrowser.document);
public static Image CaptureWebScreenImage(IHTMLDocument2 myDoc) {
int heightsize = (int)getDocumentAttribute(myDoc, "scrollHeight");
int widthsize = (int)getDocumentAttribute(myDoc, "scrollWidth");
Bitmap finalImage = new Bitmap(widthsize, heightsize);
Graphics gFinal = Graphics.FromImage(finalImage);
COMRECT rect = new COMRECT();
rect.left = 0;
rect.top = 0;
rect.right = widthsize;
rect.bottom = heightsize;
IntPtr hDC = gFinal.GetHdc();
IViewObject vO = myDoc as IViewObject;
vO.Draw(1, -1, (IntPtr)0, (IntPtr)0, (IntPtr)0, (IntPtr)hDC, ref rect, (IntPtr)0, (IntPtr)0, 0);
gFinal.ReleaseHdc();
gFinal.Dispose();
return finalImage;
}
I am not getting the image of the webpage. Rather I am getting an image with black background. I am not sure if this is the right way of doing it, but I found over the web that IViewObject::Draw method is used for taking the image of a webpage in IE.
I was earlier doing the image capture using the Native PrintWindow() method as mentioned in the following codeproject's page - http://www.codeproject.com/KB/graphics/IECapture.aspx
But the image size is humongous! I was trying to see if I can reduce the size by using other techniques. It would be great if someone can point out the mistakes (I am sure there would be many) in my code above.
Thanks,
Kapil
You can try to query IHTMLElementRender interface for the document element (which is available through IHTMLDocument3 interface) and use DrawToDC method to render page to a bitmap.
1 IHTMLElementRender::DrawToDC is deprecated, according to Microsoft's documentation. And it does not draw object and canvas, like flash, as far as I can see.
It's better to cal IViewObject::Draw() or ::OleDraw().
2 I dont know how to do it in C#, but I know how to do it in win32 program. In win32 program, you need to call IOleInplaceObject::SetObjectRect to set IWebBrowser's position and size.
Or SetClientSite(), I am sure one of them does the magic.
CComQIPtr oleObject = browser;
CComQIPtr<IOleInPlaceObject> inPlaceObject(mOleObject);
inPlaceObject->SetObjectRects(&rcClient, &rcClient);
oleObject ->SetClientSite(clientSite);
Hope it helps

Is there an API for vista to detect if the desktop is running full screen?

e.g, Is the user playing a movie full screen, or looking at powerpoint in full screen mode?
I could have sworn I saw a IsFullScreenInteractive API before, but can't find it now
Here's how I've solved this problem:
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(IsForegroundWwindowFullScreen());
}
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetSystemMetrics(int smIndex);
public const int SM_CXSCREEN = 0;
public const int SM_CYSCREEN = 1;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out W32RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct W32RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public static bool IsForegroundWwindowFullScreen()
{
int scrX = GetSystemMetrics(SM_CXSCREEN),
scrY = GetSystemMetrics(SM_CYSCREEN);
IntPtr handle = GetForegroundWindow();
if (handle == IntPtr.Zero) return false;
W32RECT wRect;
if (!GetWindowRect(handle, out wRect)) return false;
return scrX == (wRect.Right - wRect.Left) && scrY == (wRect.Bottom - wRect.Top);
}
}
}
Vista indeed has an API pretty much exactly for this purpose - it's called SHQueryUserNotificationState.
Use GetForegroundWindow to get a handle to the window the user is working with. GetClientRect will give the dimensions of the active part of the window sans borders; use ClientToScreen to convert the rectangle to monitor coordinates.
Call MonitorFromRect or MonitorFromWindow to get the monitor that the window is in. Use GetMonitorInfo to get the coordinates of the monitor.
Compare the two rectangles - if the window rectangle completely covers the monitor rectangle, it's a full screen window.
The preferred way of detecting the state of a window is by calling GetWindowPlacement. If you do that in conjunction with GetForegroundWindow, you can easily check if the user sees a fullscreen window or not.

Resources