Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #35262 > unrolled thread
| Started by | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| First post | 2016-08-11 23:42 +0200 |
| Last post | 2016-08-11 18:24 -0400 |
| Articles | 9 — 3 participants |
Back to article view | Back to comp.lang.java.programmer
Restricting the memory usage of a Java program Cecil Westerhof <Cecil@decebal.nl> - 2016-08-11 23:42 +0200
Re: Restricting the memory usage of a Java program Arne Vajhøj <arne@vajhoej.dk> - 2016-08-11 18:04 -0400
Re: Restricting the memory usage of a Java program Cecil Westerhof <Cecil@decebal.nl> - 2016-08-12 10:34 +0200
Re: Restricting the memory usage of a Java program Martin Gregorie <martin@address-in-sig.invalid> - 2016-08-12 10:08 +0000
Re: Restricting the memory usage of a Java program Arne Vajhøj <arne@vajhoej.dk> - 2016-08-12 09:23 -0400
Re: Restricting the memory usage of a Java program Cecil Westerhof <Cecil@decebal.nl> - 2016-08-13 01:11 +0200
Re: Restricting the memory usage of a Java program Cecil Westerhof <Cecil@decebal.nl> - 2016-08-13 02:52 +0200
Re: Restricting the memory usage of a Java program Arne Vajhøj <arne@vajhoej.dk> - 2016-08-12 21:05 -0400
Re: Restricting the memory usage of a Java program Arne Vajhøj <arne@vajhoej.dk> - 2016-08-11 18:24 -0400
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2016-08-11 23:42 +0200 |
| Subject | Restricting the memory usage of a Java program |
| Message-ID | <8760r7m18z.fsf@Equus.decebal.nl> |
I made a little program for cropping images. When just starting it as
a Java program the memory usage was just way to much. So I wrote the
following script:
#!/usr/bin/env bash
declare -r CLASS=CropImage
declare -r MIN_MEM=128M
declare -r MAX_MEM=256M
# Make sure you are in the right directory.
# Only start the Java application when moving to the right directory was succesful.
cd "${0%/*}" && java "-Xms${MIN_MEM}" "-Xmx${MAX_MEM}" "${CLASS}" &
And now the memory consumption is much less and as far as I can see
without negative consequences for the program.
The values I use (128 MB and 256 MB) are just values I kind of
randomly choose. Is there a way to find ‘optimal’ values?
Bonus question: is there a way to limit the memory usage when the
program is started with:
java CropImage
instead of the script?
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-11 18:04 -0400 |
| Message-ID | <noisp2$12e7$1@gioia.aioe.org> |
| In reply to | #35262 |
On 8/11/2016 5:42 PM, Cecil Westerhof wrote:
> I made a little program for cropping images. When just starting it as
> a Java program the memory usage was just way to much. So I wrote the
> following script:
> #!/usr/bin/env bash
>
> declare -r CLASS=CropImage
> declare -r MIN_MEM=128M
> declare -r MAX_MEM=256M
>
> # Make sure you are in the right directory.
> # Only start the Java application when moving to the right directory was succesful.
> cd "${0%/*}" && java "-Xms${MIN_MEM}" "-Xmx${MAX_MEM}" "${CLASS}" &
>
> And now the memory consumption is much less and as far as I can see
> without negative consequences for the program.
>
> The values I use (128 MB and 256 MB) are just values I kind of
> randomly choose. Is there a way to find ‘optimal’ values?
System.gc();
Runtime rt = Runtime.getRuntime();
long actual_value = rt.totalMemory() - rt.freeMemory();
long good_value = SOME_MAGIC_FACTOR * actual_value;
Arne
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2016-08-12 10:34 +0200 |
| Message-ID | <87wpjml720.fsf@Equus.decebal.nl> |
| In reply to | #35263 |
On Friday 12 Aug 2016 00:04 CEST, Arne Vajhøj wrote:
> On 8/11/2016 5:42 PM, Cecil Westerhof wrote:
>> I made a little program for cropping images. When just starting it
>> as a Java program the memory usage was just way to much. So I wrote
>> the following script: #!/usr/bin/env bash
>>
>> declare -r CLASS=CropImage
>> declare -r MIN_MEM=128M
>> declare -r MAX_MEM=256M
>>
>> # Make sure you are in the right directory. Only start the Java
>> # application when moving to the right directory was succesful. cd
>> # "${0%/*}" && java "-Xms${MIN_MEM}" "-Xmx${MAX_MEM}" "${CLASS}" &
>>
>> And now the memory consumption is much less and as far as I can see
>> without negative consequences for the program.
>>
>> The values I use (128 MB and 256 MB) are just values I kind of
>> randomly choose. Is there a way to find ‘optimal’ values?
>
> System.gc();
> Runtime rt = Runtime.getRuntime();
> long actual_value = rt.totalMemory() - rt.freeMemory();
> long good_value = SOME_MAGIC_FACTOR * actual_value;
It is funny: I was always told that calling gc does not have an effect
on memory and that it can have a negative impact on performance. But I
saw a real difference. Maybe it is a good idea to call it once an
hour?
I added the following to my constructor:
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
long divideValue = 1024 * 1024;
long freeMemory = rt.freeMemory() / divideValue;
long totalMemory = rt.totalMemory() / divideValue;
giveMessage(String.format("Maximum to use %d",
rt.maxMemory() / divideValue));
giveMessage(String.format("Before %d - %d = %d",
totalMemory, freeMemory,
totalMemory - freeMemory));
System.gc();
freeMemory = rt.freeMemory() / divideValue;
totalMemory = rt.totalMemory() / divideValue;
giveMessage(String.format("After %d - %d = %d",
totalMemory, freeMemory,
totalMemory - freeMemory));
}
}, 15, 60, TimeUnit.MINUTES);
The function giveMessage prints the input string with a time stamp to
standard out.
The first time I ran it with:
}, 0, 15, TimeUnit.MINUTES);
I ran it for little more as ten hours and with both I saw that the
free memory was the same after the gc. So it is really useful to get
an indication.
Maybe I should rewrite it as an utility function, so I could use it in
all my applications. And of-course I should log to a (SQLite) database
instead of standard out. (It should be called logMessage instead of
giveMessage.)
I also have an instance running without the gc. I should let it run
for at least a day to see what happens.
They start with:
- script version
09:43:54: Maximum to use 228
09:43:54: Before 123 - 64 = 59
09:43:54: After 123 - 69 = 54
- Java version
09:48:20: Maximum to use 3540
09:48:20: Before 240 - 172 = 68
09:48:20: After 240 - 186 = 54
- Java version without gc
09:49:23: Maximum to use 3540
09:49:23: Before 240 - 172 = 68
09:49:23: After 240 - 172 = 68
When it runs at least a day I will give an update.
It is clear that max memory default is quit large.
Without the script total memory is higher, but not that much. So maybe
I do not need the scripts to curtail memory usage. I save work and
when sometimes the application needs a lot more it is not curtailed.
Of-course 120 MB is a lot on an embedded device and when you would
have 20 Java applications it is going to count also, but at the moment
I am running on a desktop with enough memory and am not running scores
of Java applications.
I can always start limiting memory when it becomes tight and when I
also have some information about the usage …
Just to be sure: maxMemory cannot change during the run of a Java
application?
There is 28 MB difference between -Xmx and what maxMemory returns.
Where did it go?
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2016-08-12 10:08 +0000 |
| Message-ID | <nok76r$g9q$1@dont-email.me> |
| In reply to | #35266 |
On Fri, 12 Aug 2016 10:34:15 +0200, Cecil Westerhof wrote: > Maybe I should rewrite it as an utility function, so I could use it in > all my applications. And of-course I should log to a (SQLite) database > instead of standard out. (It should be called logMessage instead of > giveMessage.) > That never hurts: I maintain a private library of useful stuff that tends to get into most of my programs because they make life easier, such as a command line parsing class and a general tracing and error reporting class, the latter giving runtime control of tracing detail and the option of wtiting tracing detail to a circular buffer that only gets displayed of an error is thrown - it provides a different view to stacktrace. Stacktrace shows where you are while the buffer dump shows how you got there. > There is 28 MB difference between -Xmx and what maxMemory returns. Where > did it go? > Workspace used during JVM initialisation but still there because the gc hasn't (yet) been run? -- martin@ | Martin Gregorie gregorie. | Essex, UK org |
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-12 09:23 -0400 |
| Message-ID | <nokil0$1ce1$1@gioia.aioe.org> |
| In reply to | #35266 |
On 8/12/2016 4:34 AM, Cecil Westerhof wrote:
> On Friday 12 Aug 2016 00:04 CEST, Arne Vajhøj wrote:
>> On 8/11/2016 5:42 PM, Cecil Westerhof wrote:
>>> The values I use (128 MB and 256 MB) are just values I kind of
>>> randomly choose. Is there a way to find ‘optimal’ values?
>>
>> System.gc();
>> Runtime rt = Runtime.getRuntime();
>> long actual_value = rt.totalMemory() - rt.freeMemory();
>> long good_value = SOME_MAGIC_FACTOR * actual_value;
>
> It is funny: I was always told that calling gc does not have an effect
> on memory and that it can have a negative impact on performance. But I
> saw a real difference. Maybe it is a good idea to call it once an
> hour?
I doubt it.
System.gc is not something that makes sense to call as
part of normal execution.
But if one want to know how much heap space is in used
after GC has removed orphan objects, then it makes sense.
> I added the following to my constructor:
> ses.scheduleAtFixedRate(new Runnable() {
> @Override
> public void run() {
> long divideValue = 1024 * 1024;
> long freeMemory = rt.freeMemory() / divideValue;
> long totalMemory = rt.totalMemory() / divideValue;
>
> giveMessage(String.format("Maximum to use %d",
> rt.maxMemory() / divideValue));
> giveMessage(String.format("Before %d - %d = %d",
> totalMemory, freeMemory,
> totalMemory - freeMemory));
> System.gc();
> freeMemory = rt.freeMemory() / divideValue;
> totalMemory = rt.totalMemory() / divideValue;
> giveMessage(String.format("After %d - %d = %d",
> totalMemory, freeMemory,
> totalMemory - freeMemory));
> }
> }, 15, 60, TimeUnit.MINUTES);
>
> The function giveMessage prints the input string with a time stamp to
> standard out.
>
> The first time I ran it with:
> }, 0, 15, TimeUnit.MINUTES);
>
> I ran it for little more as ten hours and with both I saw that the
> free memory was the same after the gc. So it is really useful to get
> an indication.
Yes. It gives an indication of how much heap space is absolutely
required.
If you set Xmx lower than that then you run out of memory.
If you set Xmx just a little bit higher than that then GC run too
frequently and hurt throughput.
If you set Xmx extremely higher than that then GC will run very
rarely and can cause pauses (because it is GC'ing too much).
If you set Xmx sufficient higher then you should see good
throughput and minimal pausing.
> Maybe I should rewrite it as an utility function, so I could use it in
> all my applications.
I am just suggesting it for fine tuning what you want to set Xmx
to. Sort of a debugging tool. Not a production thing.
> Just to be sure: maxMemory cannot change during the run of a Java
> application?
That is my understanding. See previous post.
> There is 28 MB difference between -Xmx and what maxMemory returns.
> Where did it go?
I don't know.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2016-08-13 01:11 +0200 |
| Message-ID | <87fuq9lgzr.fsf@Equus.decebal.nl> |
| In reply to | #35271 |
On Friday 12 Aug 2016 15:23 CEST, Arne Vajhøj wrote:
>> It is funny: I was always told that calling gc does not have an
>> effect on memory and that it can have a negative impact on
>> performance. But I saw a real difference. Maybe it is a good idea
>> to call it once an hour?
>
> I doubt it.
>
> System.gc is not something that makes sense to call as
> part of normal execution.
>
> But if one want to know how much heap space is in used
> after GC has removed orphan objects, then it makes sense.
>
>> I added the following to my constructor:
>> ses.scheduleAtFixedRate(new Runnable() {
>> @Override
>> public void run() {
>> long divideValue = 1024 * 1024;
>> long freeMemory = rt.freeMemory() / divideValue;
>> long totalMemory = rt.totalMemory() / divideValue;
>>
>> giveMessage(String.format("Maximum to use %d",
>> rt.maxMemory() / divideValue));
>> giveMessage(String.format("Before %d - %d = %d",
>> totalMemory, freeMemory,
>> totalMemory - freeMemory));
>> System.gc();
>> freeMemory = rt.freeMemory() / divideValue;
>> totalMemory = rt.totalMemory() / divideValue;
>> giveMessage(String.format("After %d - %d = %d",
>> totalMemory, freeMemory,
>> totalMemory - freeMemory));
>> }
>> }, 15, 60, TimeUnit.MINUTES);
>>
>> The function giveMessage prints the input string with a time stamp
>> to standard out.
>>
>> The first time I ran it with:
>> }, 0, 15, TimeUnit.MINUTES);
>>
>> I ran it for little more as ten hours and with both I saw that the
>> free memory was the same after the gc. So it is really useful to
>> get an indication.
>
> Yes. It gives an indication of how much heap space is absolutely
> required.
>
> If you set Xmx lower than that then you run out of memory.
>
> If you set Xmx just a little bit higher than that then GC run too
> frequently and hurt throughput.
>
> If you set Xmx extremely higher than that then GC will run very
> rarely and can cause pauses (because it is GC'ing too much).
>
> If you set Xmx sufficient higher then you should see good
> throughput and minimal pausing.
I am thinking about setting it to two to four times the max value of
used after gc. It is of-course depending on the type of application
and the way it is used. When the usage changes, the needed memory
requirement can be changed also.
>> Maybe I should rewrite it as an utility function, so I could use it
>> in all my applications.
>
> I am just suggesting it for fine tuning what you want to set Xmx
> to. Sort of a debugging tool. Not a production thing.
That is where the whole exercise started for: getting a good value for
Xmx. When setting this to 256 MB I see that the application when not
really used uses about half of the memory as when Xmx not used. In
that case it could be halved. But I should look for the case that the
application is used of-course. ;-)
By the way: there is now way to get the value for minMemory?
>> Just to be sure: maxMemory cannot change during the run of a Java
>> application?
>
> That is my understanding. See previous post.
But it can, I just saw:
freeAfter freeBefore maxMemory totalAfter totalBefore
"185" "65" "239" "239" "242"
"101" "96" "228" "155" "155"
So first maxMemory was 228. An hour later total was 242 before gc.
After gc total was 239 and maxMemory was changed from 228 to 239.
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2016-08-13 02:52 +0200 |
| Message-ID | <8760r5lccf.fsf@Equus.decebal.nl> |
| In reply to | #35280 |
On Saturday 13 Aug 2016 01:11 CEST, Cecil Westerhof wrote: >>> Just to be sure: maxMemory cannot change during the run of a Java >>> application? >> >> That is my understanding. See previous post. > > But it can, I just saw: > freeAfter freeBefore maxMemory totalAfter totalBefore > "185" "65" "239" "239" "242" > "101" "96" "228" "155" "155" > > So first maxMemory was 228. An hour later total was 242 before gc. > After gc total was 239 and maxMemory was changed from 228 to 239. But it is also given back, the next line (an hour later) reeds: freeAfter freeBefore maxMemory totalAfter totalBefore "120" "42" "228" "174" "174" -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-12 21:05 -0400 |
| Message-ID | <nolro4$1ckv$1@gioia.aioe.org> |
| In reply to | #35280 |
On 8/12/2016 7:11 PM, Cecil Westerhof wrote: > By the way: there is now way to get the value for minMemory? That info is water under the bridge. But if you really want it then look at: ManagementFactory.getRuntimeMXBean().getInputArguments() Arne
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-11 18:24 -0400 |
| Message-ID | <noitvc$1436$1@gioia.aioe.org> |
| In reply to | #35262 |
On 8/11/2016 5:42 PM, Cecil Westerhof wrote: > Bonus question: is there a way to limit the memory usage when the > program is started with: > java CropImage > instead of the script? You can start JVM via JNI (really just your own java executable replacement) with the Xmx you want. But when the JVM is running then I don't know any way via JMX or JNI to change the value. Many JVM's require heap to be contiguous, so trying to increase Xmx later may not be possible. Arne
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web