Create account / Log in

CPU profiling

Discussion area for the development team.

Moderators: uckelman, Tim M

Re: CPU profiling

Postby uckelman » July 31st, 2020, 10:16 pm

Thus spake Flint1b:
> I think I understand this, roughly.
>
> Do you want to start a draft PR and implement the main structure and
> I'll help by filling in the implementation in the various trait classes?

I'd like to get thoughts (Brent's especially) on the simplest way we can
handle making the flattened maps available to the outermost GamePiece.
That's the tricky part, and there may be pitfalls or ways of doing it I'm
not considering.

> About the naming, can we use regular Java syntax i.e. camelCase,
> getterMap setterMap localGetterMap localSetterMap instead of gmap smap
> lgmap lsmap and C-style "variable_name"?

Yeah, fine.

All of the local changes---extracting the lambdas for the local maps and
using those in getProperty() and setProperty()---could go ahead now, on
the assumption that we'll find a good place to set the outermost maps.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby Brent Easton » August 1st, 2020, 3:07 am

I am still digesting the design. My concerns relate to how the 'exceptions' to a standard trait property will be handled. e.g. Global/Map/Zone properties, scratch-pad properties in BasicPiece and the 'assembled' properties pieceName and visibleState. Also need to look carefully at Prototype Definitions which are fragments of a unit, and unit definitions with unexpanded prototype definitions. I don't expect problems with these, but need to be checked.

When I was working on the SELECT property, the hardest part was working out how and where to store it, so it ends up stored in every Decorator.

I really like the idea of implementing a top-hat trait that we place on top of each GamePiece when it is created so that every single unit has one. There are very few places where unit GamePieces (as opposed to Stacks or Decks) get created (PieceCloner may be it). I think it would be quite simple to add the top-hat at this point, if the top trait is not already a top-hat. Once created, they will just get saved in the log file like a normal trait. This would make implementation of this scheme, and any further optimisations vastly easier. It think it would be a mistake to try and implement something this complex inside the Decorator class.

We could pre-process the unit at this point and do other optimisations like setting a direct link to the Top-Hat and BasicPiece inside each Decorator, instead of the insane Decorator.getOutermost(this) and Decorator.getInnermost(this) loops.
User avatar
Brent Easton
 
Posts: 3090
Joined: December 21st, 2007, 3:06 am
Location: Berry, NSW, Australia

Re: CPU profiling

Postby Flint1b » August 1st, 2020, 8:56 am

In a module, is it possible to write a custom class for a trait that has all the properties that a gamepiece needs, instead of building a trait stack out of the builtin trait classes?
User avatar
Flint1b
 
Posts: 415
Joined: May 19th, 2020, 12:27 am
Location: Colonia Agrippina

Re: CPU profiling

Postby uckelman » August 1st, 2020, 11:14 am

Thus spake Flint1b:
> In a module, is it possible to write a custom class for a trait that has
> all the properties that a gamepiece needs, instead of building a trait
> stack out of the builtin trait classes?

That depends on what you mean by "all the properties that a gamepiece
needs".

If you mean a custom class for one particular kind of piece in your module,
sure, but it's common to have dozens of different kinds of pieces so you'd
end up with a class for each and it would be a huge effort to start and a
maintenance nightmare thereafter.

If you mean a custsom class that can handle any kind of piece, sure, it's
computable, I don't see why not. It's what I intend to build for V4. The
problems you'd encounter in V3 with doing that are that you'd be
replicating essentially all of the VASSAL.counter package inside that
class if you wanted to maintain current behaivor, and you'd also have to
do something about the module editor to make the custom class usable
there.

In both cases you wouldn't pick up changes we make to VASSAL.counter
upstream. I think it would be a mess, and wouldn't recommend it.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby uckelman » August 1st, 2020, 11:17 am

Thus spake Brent Easton:
>
> I really like the idea of implementing a top-hat trait that we place on
> top of each GamePiece when it is created so that every single unit has
> one. There are very few places where unit GamePieces (as opposed to
> Stacks or Decks) get created (PieceCloner may be it). I think it would
> be quite simple to add the top-hat at this point, if the top trait is
> not already a top-hat. Once created, they will just get saved in the log
> file like a normal trait. This would make implementation of this scheme,
> and any further optimisations vastly easier. It think it would be a
> mistake to try and implement something this complex inside the Decorator
> class.

If a top-hat trait is always present and has no properties of its own,
we could just peel it off when saving and never write it out.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby Flint1b » August 1st, 2020, 11:45 am

What if....

We refactor the guts of each trait class into a kind of abstract trait scheme, and have the current trait classes reference these abstract traits to stay backwards-compatible,

then add a new kind of trait class, a "universal trait", which has a list of these abstract traits, and the module designer can add the traits that he wants to that umbrella trait, just like wrapping traits inside each other but now in an ordered list?
User avatar
Flint1b
 
Posts: 415
Joined: May 19th, 2020, 12:27 am
Location: Colonia Agrippina

Re: CPU profiling

Postby uckelman » August 1st, 2020, 12:09 pm

Thus spake Flint1b:
> [This message has been edited.]
>
> What if....
>
> We refactor the guts of each trait class into a kind of abstract trait
> scheme, and have the current trait classes reference these abstract
> traits to stay backwards-compatible,
>
> then add a new kind of trait class, a "universal trait", which has a
> list of these abstract traits, and the module designer can add the
> traits that he wants to that umbrella trait, just like wrapping traits
> inside each other but now in an ordered list?

I suspected this was where you were headed.

It would be far, far more work than adding a top-level wrapper trait
and you'd still have to traverse the traits in the same cases you have
to traverse the traits now.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby Flint1b » August 1st, 2020, 1:39 pm

That's true, just the traversal would be inside a single object, there wouldn't be several trait objects involved. And it would traverse in an iterative manner over a list and not in a kind-of recursive manner, this would save a lot of overhead. You're C++ developer I don't have to tell you how expensive it is to create objects and stackframes for function calls :D

And another question. I understand that currently traits are traversed piece by piece, in a single thread. I think there is a lot of potential for parallel processing here, if it was possible to collect all pieces in a List first, then do a List.parallelstream(). As I already said in another thread, modern Java applications use all CPU cores to get things done, while Vassal only uses 1 core.
User avatar
Flint1b
 
Posts: 415
Joined: May 19th, 2020, 12:27 am
Location: Colonia Agrippina

Re: CPU profiling

Postby uckelman » August 1st, 2020, 2:11 pm

Brent, where are pieces created when a saved game or log is loaded? PieceCloner can't be used for that because there won't be pieces to clone yet, right?
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby uckelman » August 1st, 2020, 2:47 pm

Thus spake Flint1b:
> That's true, just the traversal would be inside a single object, there
> wouldn't be several trait objects involved. And it would traverse in an
> iterative manner over a list and not in a kind-of recursive manner, this
> would save a lot of overhead. You're C++ developer I don't have to tell
> you how expensive it is to create objects and stackframes for function
> calls :D

There's more to it than just property access. Traits delegate inward pretty
much everything they don't handle locally. If you're planning to have all
the traversal happen over the list, then you're looking at rewriting all the
traits.

Based on profiling, property access is by far the most expensive thing
in the trait stacks and flattening it isn't so complicated or risky. It's
low-hanging fruit, and we may find that things are fast enough after
dealing with it.

I want to try this, as it's something I've had on the table for a decade
now and looks like it will be a small effort for potentially a huge gain.
Rewriting all the traits, on the other hand, looks to me like throwing
good time after bad. I'd rather spend the time I could put into rewriting
traits into V4.

> And another question. I understand that currently traits are traversed
> piece by piece, in a single thread. I think there is a lot of potential
> for parallel processing here, if it was possible to collect all pieces
> in a List first, then do a List.parallelstream(). As I already said in
> another thread, modern Java applications use all CPU cores to get things
> done, while Vassal only uses 1 core.

Well, it depends heavily on what it is you're doing. Some operations could
be parallelized, some not. If you have a group of pieces which all need to
be flipped to their next face, you could do that in parallel (though the
operations for that are going to be so short I'd expect the threading
machinery to more than eat up all your gains). If you have a group of pieces
which all need to have some global key command executed on them which then
trigers five other things etc.---good luck figuring out programatically if
that can be parallelized.

Furthermore, modern Java applications also don't have a GUI for the most
part, and virtually every operation you could do on game state will affect
the GUI, so it will be rough going without model-view separation. Again,
I think it's not worth the effort on the current codebase.

After the chatter issue is merged, I'd like to put out a 3.3.3 beta. We
can aim for having flattened property access in 3.3.4 if it works out.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby uckelman » August 1st, 2020, 2:51 pm

Thus spake Flint1b:
> As I already said in another thread, modern Java applications use all
> CPU cores to get things done, while Vassal only uses 1 core.

Also, this isn't true. VASSAL does some very heavyweight things---
nearly all of the image processing---using a thread pool.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby Flint1b » August 1st, 2020, 3:23 pm

uckelman wrote:VASSAL does some very heavyweight things---
nearly all of the image processing---using a thread pool.


I haven't noticed that. When I stopped the time for the "load new scenario" use case, I saw only one core being used in top/ntop. A minute of processing in the background, no GUI changes, only 1 core being used, it must be possible to improve this by using more cores.
User avatar
Flint1b
 
Posts: 415
Joined: May 19th, 2020, 12:27 am
Location: Colonia Agrippina

Re: CPU profiling

Postby uckelman » August 1st, 2020, 3:28 pm

Thus spake Flint1b:
> I haven't noticed that. When I stopped the time for the "load new
> scenario" use case, I saw only one core being used in top/ntop. A minute
> of processing in the background, no GUI changes, only 1 core being used,
> it must be possible to improve this by using more cores.

You wouldn't see any threads loading or manipulating images during that,
as loading a saved game doesn't involve any painting.

--
J.
User avatar
uckelman
Site Admin
 
Posts: 8798
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Re: CPU profiling

Postby Flint1b » August 1st, 2020, 4:56 pm

Yes, that's what I'm saying. Must be possible to cut down 1 minute of initializing internal state on one core to 10-20 seconds on 4+ cores.
User avatar
Flint1b
 
Posts: 415
Joined: May 19th, 2020, 12:27 am
Location: Colonia Agrippina

Re: CPU profiling

Postby Brent Easton » August 1st, 2020, 10:59 pm

For anything where user invoked automation is being executed, there is no way you will ever be able to do any parallel processing. It has to run single threaded in a guaranteed order or you will get different results each time it runs. There is no way to tell which Commands in a command stream are dependent on an earlier Command having already been performed.
User avatar
Brent Easton
 
Posts: 3090
Joined: December 21st, 2007, 3:06 am
Location: Berry, NSW, Australia

PreviousNext

Return to Developers

Who is online

Users browsing this forum: No registered users and 1 guest

cron