digitalmars.D.learn - Event struct via registers
- Vitaliy Fadeev (60/60) Aug 10 ## Trouble 1
- Vitaliy Fadeev (80/85) Aug 10 I try:
- Vitaliy Fadeev (3/19) Aug 10 D online editor:
- Vitaliy Fadeev (2/23) Aug 10 May be `union` ?
- Vitaliy Fadeev (21/46) Aug 10 Thanks, all, for energy!
- IchorDev (9/69) Aug 10 This depends on the calling convention used by your compiler and
- Vitaliy Fadeev (6/17) Aug 10 Many input event + many internal ui events -> many calls * many
- claptrap (9/15) Aug 10 Lets say you get mouse events 100 times a second and and you have
- Basile B. (18/22) Aug 10 You dont need to pass whole event. The obvious design for this
Pass the structure through registers ? Wrap the registries in a structure ? I need to pass different events: `Draw_Event`, `Mouse_Move_Event`, `...` I need to pass an event to many objects: `foreach (o; world) o.event (e);` I need speed. I want to pass the structure in registers: (like __fastcall callin convention): `void _event (REG r1, REG r2, REG r3, REG r4);`. But it's hard to read. I want comfortable use: (like a wrap registers in struct): ``` void event (Event e) { writeln (e.type); writeln (e.code); writeln (e.value); switch (e.type) { case Type.REL: _rel_event (e); break; case Type.GUI: _gui_event (e); break; case Type.APP: _app_event (e); break; default: } } ``` The problem is that the size of the structure is larger than the size of the register. ``` struct Event { // 64 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit } ``` But the event size can be > 64 bit. More than register size. ``` struct Mouse_Event { // 128 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit float x; // 32 bit float y; // 32 bit } struct Draw_Event { // 192 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit float x; // 32 bit float y; // 32 bit float w; // 32 bit float h; // 32 bit } ``` How to implement on D?
Aug 10
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:Pass the structure through registers ? Wrap the registries in a structure ? How to implement on D?I try: ``` import std.stdio; void main() { Event_1 event_1; event (event_1); Event_2 event_2; event (event_2); } struct Event_1 { ushort type = 1; ushort code = 2; uint value = 3; } struct Event_2 { ushort type = 1; ushort code = 2; uint value = 3; float x = 4.0; float y = 5.0; } void event (EVENT) (/* R this, */ EVENT e) { enum REG_SIZE = (void*).sizeof; // Bytes pragma (msg, EVENT, " : ", EVENT.sizeof); pragma (msg, "REG_SIZE: ", REG_SIZE); static if (EVENT.sizeof == 0) { // } else static if (EVENT.sizeof <= REG_SIZE) { // 64 bit _event (/* this, */ * cast (REG*) &e, //* cast (REG*) cast (ubyte*) &e, //cast (REG) *( // (cast (ubyte*) &e)[0..EVENT.sizeof].ptr //), 0, 0); } else static if (EVENT.sizeof <= 2*REG_SIZE) { // 128 bit _event (/* this, */ cast (REG) *( (cast (ubyte*) &e)[0..REG_SIZE].ptr ), cast (REG) *( (cast (ubyte*) &e)[REG_SIZE..EVENT.sizeof].ptr ), 0); } else static assert (0, "Event sizeof too much"); } alias REG = ulong; void _event (/* REG this, */ REG type_code_value, REG r3, REG r4) { //switch (type_code_value.type) { // case Event.Type.GUI: gui.event (type_code_value, r3, r4); break; // default: //} writeln ("type_code_value: ", type_code_value); writeln ("r3: ", r3); writeln ("r4: ", r4); Event_1 event_1; event_1 = * cast (Event_1*) &type_code_value; writeln (" event_1 :", event_1); if (r3 != 0) { writeln (" event_2 :", r3); } } ``` But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
Aug 10
On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev wrote:On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmdPass the structure through registers ? Wrap the registries in a structure ? How to implement on D?I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
Aug 10
On Saturday, 10 August 2024 at 08:10:10 UTC, Vitaliy Fadeev wrote:On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev wrote:May be `union` ?On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmdPass the structure through registers ? Wrap the registries in a structure ? How to implement on D?I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
Aug 10
On Saturday, 10 August 2024 at 08:29:20 UTC, Vitaliy Fadeev wrote:On Saturday, 10 August 2024 at 08:10:10 UTC, Vitaliy Fadeev wrote:Thanks, all, for energy! I do it with `union`: ``` struct Convertor (T) { union { T from; struct { REG r1; REG r2; REG r3; REG r4; } } } ``` ``` auto convertor = Convertor!(EVENT) (e); _event (/* this, */ convertor.r1, convertor.r2, convertor.r3); ```On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev wrote:May be `union` ?On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmdPass the structure through registers ? Wrap the registries in a structure ? How to implement on D?I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
Aug 10
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:Pass the structure through registers ? Wrap the registries in a structure ? I need to pass different events: `Draw_Event`, `Mouse_Move_Event`, `...` I need to pass an event to many objects: `foreach (o; world) o.event (e);` I need speed. I want to pass the structure in registers: (like __fastcall callin convention): `void _event (REG r1, REG r2, REG r3, REG r4);`. But it's hard to read. I want comfortable use: (like a wrap registers in struct): ``` void event (Event e) { writeln (e.type); writeln (e.code); writeln (e.value); switch (e.type) { case Type.REL: _rel_event (e); break; case Type.GUI: _gui_event (e); break; case Type.APP: _app_event (e); break; default: } } ``` The problem is that the size of the structure is larger than the size of the register. ``` struct Event { // 64 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit } ``` But the event size can be > 64 bit. More than register size. ``` struct Mouse_Event { // 128 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit float x; // 32 bit float y; // 32 bit } struct Draw_Event { // 192 bit ushort type; // 16 bit ushort code; // 16 bit uint value; // 32 bit float x; // 32 bit float y; // 32 bit float w; // 32 bit float h; // 32 bit } ``` How to implement on D?This depends on the calling convention used by your compiler and on your CPU architecture. 64 bits is already 2 data registers on a 32-bit CPU. There are also many calling conventions that allow multiple data registers to be used when passing structs around. Do you really need to avoid them being passed on the stack though? Is your application highly performance critical? (i.e. kernel code) You could also use `ref const` to avoid the copying, but your data will probably always be on the stack that way.
Aug 10
On Saturday, 10 August 2024 at 08:06:42 UTC, IchorDev wrote:On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:Yes.[...]This depends on the calling convention used by your compiler and on your CPU architecture. 64 bits is already 2 data registers on a 32-bit CPU. There are also many calling conventions that allow multiple data registers to be used when passing structs around. Do you really need to avoid them being passed on the stack though?Is your application highly performance critical?Many input event + many internal ui events -> many calls * many objects. Yes, I like the fast, responsive interface on old hardware (as B970 CPU).
Aug 10
On Saturday, 10 August 2024 at 08:18:54 UTC, Vitaliy Fadeev wrote:On Saturday, 10 August 2024 at 08:06:42 UTC, IchorDev wrote:Lets say you get mouse events 100 times a second and and you have 10 function calls to filter through the gui tree, and your overhead for passing on the stack is 20 cycles. (100*10*20) = 20,000 And your CPU is 2Ghz, so... 2,000,000,000 / 20,000 = 100,000 So what you're optimizing for is like 0.001% of your cpu time. It's utterly irrelevant.Is your application highly performance critical?Many input event + many internal ui events -> many calls * many objects. Yes, I like the fast, responsive interface on old hardware (as B970 CPU).
Aug 10
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:Pass the structure through registers ? [...] How to implement on D?You dont need to pass whole event. The obvious design for this kind of things is that you declare a local event that's an union of all possible things then in the low level event loop you dispatch the members of interest to the high level consumer. This is for example how this worked in kheops: 1. low level event loop with the big local union (an XEvent): https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L2770 2. example of dispatching where only the usefull things are passed: https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L2863 3. then the high level consumers just receive the useful parameters: https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L752 That's always 3 or 4 parameters, always passed in general purpose registers. I've never seen these kind of things done differently because it would indeed be slow to pass the whole event.
Aug 10