Thus spake Flint1b:
Thank you for the detailed answer, I now understand the motives, though
I don’t agree with the implementation.
It is not the job of the user to tell the JVM how much heap it has, but
rather it’s the job of the developer to give the user a start script
that sets a good -Xmx value. It is also the job of the developer to use
the given memory wisely, like you did with the tiling of the images and
only loading the portions into memory that are needed right now.
Splitting the application over several JVMs uses up more memory, not
less, as many if not most classes of the application get loaded several
times into memory, all the static blocks and statically initialized
variables get loaded once per JVM, not to mention the overhead of the
JVM itself.
Indeed. But I did not say that we’re trying to conserve memory full
stop. We’re trying to conserve memory within the limit set for the
max heap for a particular VM.
The Player currently starts with -Xmx512m, the Module Manager starts
with a default of 2G but surely doesn’t need more than 128-256M, so
theoretically, say if a user wanted to start 4 Players for some reason,
he would need 4*512 plus 256M for the ModuleManager, 2.25 GB RAM would
be needed in the worst case, assuming the whole 512MB are used up by
each Player instance and the ModuleManager goes crazy and needs 256 for
some reason.
The max heap for the Module Manager is basically irrelevant; it’s unlikely
ever to expand its heap from the initial value. But that amount would still
be counted within the heap in a combined application.
Also significant is that Java’s heap has to be contiguous. You might be
surprised to know that even in 2020, there are many users whose machines
cannot allocate a contiguous 2GB region of RAM. There are also some
modules which need a heap of around 1GB to be opened once.
This is easily doable in a single JVM, and will help the
JVM to optimize runtime and memory much better as it could reuse most of
the classes and objects. All the internal Strings, the GUI Actions,
could all be reused, also it’s highly likely that if a user starts
several Players, he won’t start several modules but one and the same
module in several instances, and with the correct implementation most
module images could be reused.
The amount of memory used by classes and Strings which would actually be
duplicates between two Players is negligible. Almost all the memory used
by a Player is for mutable objects and image data. If you had two copies
of the same module open, you might share image data, but you’re still not
going to share other objects. The ability to have n Players open in one
VM would make it even harder to advise anyone as to what they should set
their max heap.
It appears to me that the problem is not the way how Java handles memory
but rather C++ developers misunderstanding and being afraid of Java and
finding things impossible.
If, after reading my explanations, you still think I’ve misunderstood the
capabilities of Java, please do me the favor of pointing out where.
The codebase has completely deteriorated and
looks like Java from 20 years ago,
You’re right on one count here—the codebase looks like Java from 20
years ago because most of it is Java from 20 years ago. You would not
be telling us that the codebase has deterioriated if you had seen the
state of it in 2006.
the idioms used in the code are C/C++
idioms, methods that are several hundred lines long, variables named
this_is_my_name, class fields declared public and used like C-structs,
and an overall design that is not object oriented at all but rather
static C-style code thrown into Java classes.
This is largely code we inherited.
I understand why you want
to run away to a rewrite in C++, but I doubt this will solve the
problems and become a viable replacement, at least in the next 10-15
years, assuming that as much work will be done for that as was done for
Vassal 3 over the last 10-15 years. And even if after this time the
given problems will become solved, they will be replaced by new
problems.
Thanks for the vote of confidence.
I did a significant chunk of the work on VASSAL 3 over the past 16 years.
Far, far too much of that work was remedial—so much effort was lost to
fixing problems due to inapproriate design, buggy code, bugs and
limitations of Java, and lack of tests. Those are all problems we can
avoid.
Anyways I am a Java developer and have no interest in C++, it is a
terrible language, most C++ developers are terrible and know nothing
about clean code, maintainability, refactoring, and object oriented
design, my prophecy is that the new Vassal 4’s C++ code will deteriorate
exactly like Vassal 3’s code deteriorated or even worse thanks to the
existence of the glorious language features named malloc() and the even
more glorious free().
Most developers in any language are terrible and know nothing about
clean code, maintainability, refactoring, or object oriented design. It’s
nothing to do with the language (except for the case of PHP, which is
special).
I suggest you look into what modern C++ is like. No one who has any clue
uses malloc() or free() in C++ (save perhaps for some very unusual
circumstances where one is interfacing with a C API), and if you’re then
going to say you meant new and delete, I can tell you that those get
scant use as well these days. C++11 is dramatically different from C++03
and before, and the bad practices you see with C++03 and before are the
very same bad practices you see across much work from that period.
I will try to help with the current Vassal’s Java
code now and then and would be glad if my pull requests get accepted, I
will try to make the changes as small and as easy to understand as
possible, I understand a little bit about handling legacy code with no
tests underneath, this is the default situation I’m dealing with
professionally in big corporates.
I’m happy to review patches so long as I can see what gain there is in
them.
–
J.