Open d3xMachina opened 9 months ago
I'm pretty sure you have to capture all events - I don't think the windows api lets you selectively listen.
Allocations are likely due to the class vs struct nature of things which can't really be changed.
Instead of preventing the capture, what could be done is to just ignore the event and not do any processing if it's a mouse move event.
I have made some tests. The two parts that cause the memory allocations are :
Mostly : In MouseEventSourceState.cs : public EventSourceEventArgs<MouseEvent> GetEventArgs(EventSourceEventArgs<MouseInput> e)
:
var Data = new MouseEvent(Wait, Move, Scroll, Down, Up, Click, ClickHold, DoubleClick, DragStarted, DragFinished);
var ret = new EventSourceEventArgs<MouseEvent>(e.Timestamp, Data, e.RawData);
Then In CallBackData.cs : EventSourceEventArgs<MouseInput> ToMouseEventArgs(GlobalMouseEventSourceCallbackData data)
:
var ret = EventSourceEventArgs.Create(data.Data.Timestamp, new MouseInput(button, data.Data.Point, mouseDelta, Status), data);
So instead of doing : In GlobalMouseEventSource.cs :
protected override bool Callback(CallbackData data) {
var e = data.ToGlobalMouseEventArgs();
var Events = State.GetEventArgs(e);
var ret = InvokeMany(Events.Data, e, Events.Timestamp);
return ret.Next_Hook_Enabled;
}
We could do something like (we check the type of event from the callback data) :
protected override bool Callback(CallbackData data) {
var Data = data.ToGlobalMouseEventSourceCallbackData();
bool ignore = CheckIgnoredEvent(Data);
if (ignore) {
return false; // not 100% sure for the return value
}
var e = ToGlobalMouseEventArgs(Data);
var Events = State.GetEventArgs(e);
var ret = InvokeMany(Events.Data, e, Events.Timestamp);
return ret.Next_Hook_Enabled;
}
The logic to interpret the type of event (for the CheckIgnoredEvent function) is in MouseEventSourceState.cs :public EventSourceEventArgs<MouseEvent> GetEventArgs(EventSourceEventArgs<MouseInput> e)
with var Move = (LastInput?.Data.X != e.Data.X || LastInput?.Data.Y != e.Data.Y)
for the mouse move event for example.
This is a great analysis!
Here my thoughts: I have seldom seen applications, whose performance was majorly impacted by allocations. Yes, removing allocations makes an application faster, however, in my experience, the speed cannot be perceived by a human. (It is much more relevant for benchmarks.)
It has been a long time since I wrote a lot of this code, and I would honestly be concerned about making too many changes to it. As you look at things, you will notice that it has the ability to capture events, and then replay them! That was no easy feat!
Anyways, I noticed that the method that you wanted to optimize was virtual so you could do your own custom filtering directly in it. Does that work? I would be much more open to enabling you to override a method, then implementing an optimization specific to avoid allocations.
Thanks for the fast replies. I appreciate your work!
It would be indeed great to have the ability to override the callback method and possibly being able to call the original callback method from the overriding one.
Hello, I only need to capture mouse button inputs. All events are captured and dispatched when using the following :
WindowsInput.Capture.Global.MouseAsync(true);
The issue I have with mouse move events being captured is that it triggers a ton of events and a lot of memory allocations.
Example after a few seconds of moving the mouse : The 2 spikes are memory allocations due to moving the mouse, after I stop moving the mouse.
Stack trace of relevant memory allocations (over a few seconds) :
I believe it would be nice to have a way to disable the capture of mouse move events as it adds a ton of overhead.