63 comments

[ 2.5 ms ] story [ 114 ms ] thread
Further, today bandwidth equals performance. use 100M of memory? suddenly you've clobbered your cache. Use 10K instead, and it'll fit inside your cache neatly.
I just checked, and a small Clojure web app I am working on does indeed take almost 100MB of RSIZE - but it have its only JETTY container and a lot of other overhead that it is not sharing with other deployed apps. Also, a large app with a lot of code would not take much more. Hosting ten small web apps in the same Tomcat or Jetty instance would probably take much less than the 1 GB of RSIZE mentioned in the article.

I do agree though with the goodness of reducing memory use and I like to check memory use and execution speed when I look at comparative benchmarks like Computer Language Benchmarks Game.

I've run into lots of headaches trying to run multiple apps in the same container. It's been a while so maybe this has improved over time.
I'm reading this article while Eclipse restarts after I shutdown the app because it ran out of PermGen space.

I ran web apps that serviced 10x more users off of a 512 meg VPS with SBCL :-|

Anybody up for a sword-fight? jousting?

Curious as I am learning CL. What did framework did you use with SBCL?
Restas + closure-template is my favorite now.
-XX:MaxPermSize=128M
I'm already pushing 3 times that much.
perm (-XX:MaxPermSize) or heap (-Xmx)? They are separate spaces in sun's jvm.
Hello world and hobby projects are not the target for the JVM. It may take a good chunk of RAM to fire it up at all but you can serve far more clients in that same chunk than you could with the number of Ruby processes, for example, you could run in the same memory. Look at how much more performance Lift/Scala can squeeze out of the same box than Rails.
This is certainly true when you have to scale at some high level, but I think that level is a lot higher than most people realize. I worked at yellowpages.com for a while and we were serving a large amount of traffic (the local ads on bing are from yellowpages) with native ruby. The JVM may have been a better option at that scale, but the vast majority of sites won't reach that scale. And ruby handled it just fine. The actual search logic was run on the JVM though.
Sure, but the point is that the JVM makes you pay that memory cost up-front, so it looks a lot more resource-heavy than it really is, whereas the scaling cost of things like PHP and Ruby is back-loaded.

People worry about scaling too much in general, IMO, but you'll actually get more mileage out of your hardware with something Clojure or Scala than you will with Python/PHP/Ruby/Perl.

TLDR: JVM uses too much memory for little/hobby projects.

Response: Learn to manually configure its memory useage, don't just go with the default.

Not really front-page worthy.

Can you throw up a hello world project on github and tell me which arguments to pass it to get the memory lower? I've tried, but maybe I've missed something.
If you’re launching your hello world project in the CLI, you’d just add -Xmx=64m or whatever size you need. 64 tends to be the default and I haven’t personally tried pushing it lower (for my work I actually have to push it up into the 3-6G range. Ah, language processing).
Try it, I did. I can't get a servlet to use under 100MB after getting hit with a moderate amount of traffic. It runs out of heap.
I figured as much. I have the luxury of having sole use of a 16 machine cluster with 16G RAM each so I haven’t had to worry about OutOfMemoryError in a while.
servlet + web server + (guessing) crazy number of libraries - is it still a 'hello world' app?
Use a smaller servlet engine. Most of them assume you will be fine with a larger heap and prepare caching structures, etc with that in mind Others are smaller and lighter.
Which are good for low memory?
I feel like the JVM has already proven its self to be viable as a production VM. The 'helloworld' argument doesn't really hold water because you would never run helloworld in a vm. If you care about fast setup/teardowns or small memory footprints then don't use ANY vm. If you want things like easier security policies, garbage collection and maybe more the point: scalability then the VM is a great platform to develop for.
The point is that it is too expensive RAM-wise to even serve as a gateway drug for hobbyists to venture into more serious JVM based projects.
I feel like when you hobby you run stuff on your local machine. Are you saying that your local machine doesn't have atleast 1GB of memory? Saying that it can't run hobby projects is a bit of a stretch.
Did you read the linked post? For than just skimming the top?

I mentioned specifically what I was doing, and how much RAM it took.

The author is talking about hosting web applications. If you have half a dozen toyapps, which have an audience ranging from 0-10, you couldn't host them on separate JVMs on a VPS. There's not enough RAM for this scenario.
My audience is more like 5k to 10k per day per app. I just got 2k visitors from this post.
Good for you.. Mr. Knuth
Hold on, my rails processes take 80 megs. Am I doing something wrong?
On the JVM it will take over 300MB with JRuby. A simple 'hello world' servlet on the JVM takes over 100MB (once you hit it with a little traffic).
Untrue. JRuby can run an app in under 200 MB easily, and close to 100 MB if tuned right.
I didn't spend a whole lot of time trying to tune it, but I used a few of the standard options. Trinidad, kirk, etc. I was using a real world app, not a hello world, so there were a number of gems and such outside of vanilla rails.

Edit: This ia a real rails app, so it's a bit of a tangent from my post, but I'm looking at it right now. I spun it up with trinidad, dev mode, and requested the home page. It used over 600MB. It's an admittedly heavy homepage, asset wise, but it will run out of heap if I set the max heap any lower than 500MB.

Edit 2: let me try it with MRI

Edit 3: MRI took about 225MB, about half the memory. In this case JRuby is clearly better because we run it in threadsafe mode.

While I see his point regarding excessive memory usage WRT the JVM, I don’t think this matters much. The fact is memory is cheap these days and the convenience of the JVM is something that’s tough to overlook. Furthermore, while a Hello World app may require 100MB when implemented on the JVM, much of that is overhead which will stay relatively constant as your process grows more complex (to a point, obviously). I can run multiple processes on the same JVM instance and stay within reasonable memory bounds.

Also, we need to consider the alternative. Where would we go if we didn’t have the JVM? It’s not like .Net is much better in this regard. We could go without a system as heavyweight as these two but then we lose all the advantages that come along with that weight.

Certainly, those advantages are not needed for a lot of purposes. Looking at what he’s running I would say he probably doesn’t need the weight of the JVM.

That said, I’m pretty sure I couldn’t do my current project anywhere but the JVM (well, okay, they’re all Turing machines so technically I can, but bear with me). I’ll gladly fork over the cash for a beefier VPS if it that’s the cost of the JVM.

Full disclosure: I am considered a Scala evangelist.

The JVM is the one part of Java that is actually Gaining more mindshare. Granted "hello world" is not the ideal usecase - but you are missing the point. The cost you pay for hello world still remains the same up to a moderately sized app, and the more the complexity of your app, the more benefits you start to see from the JVM's memory model.

A better comparison would be a real world app that scales to a number of users - tell me about JVM memory usage and performance then.

You want to develop a server app and 100MB required by container is your concern? BTW This is year 2011 not 1996.
Yup, JVM takes up huge resources. But, when you put the app in production, you can be rest assured it will perform. JVM gives you piece of mind.
Until any given thread consumes too much of the heap and the jvm goes catatonic. See this all the time with jruby with 6 rails app in a single jvm instance.
Maybe you should reconsider how you have designed your setup.

Do some testing to see how much memory you have allocated to the JVM - how much resources each of your rails apps are consuming.. Use a Heap Analyser (or similar) - it could give you good insights into what is hogging up the resources.

I guess you should just run a golang HTTP service behind nginx if memory is your biggest concern.

If that's not good enough go ahead and write the whole thing using C. You can get one hell of a small "Hello, World!" program using C.

I've become a huge fan of golang for this exact reason :)
Yes, Java uses a lot of memory. It uses a lot of memory mostly because it doesn't mmap static shared lib files. Most c library based systems (e.g PHP, Python, Ruby) do. When the system can mmap read only shared lib files, that uses a lot less memory because multiple processes can share them and they are only read in to memory as they are accessed thanks to the page fault mechanism of 386 protected-mode architecture.

Java can't do this because Java self-modifies code (JIT) to run faster while it's running. Once all your classes are loaded into ram though, the memory gets consumed at a much more leisurely pace. However, multiple apps can't reuse each other's already mapped into memory code like they can with PHP, etc. As far as appserver restarts, just pay the money for JRebel already and quit complaining. Your life will be so much better.

I cannot understand why JVM sticks to JIT. JIT's advantage is mainly portability of intermediate code. So once intermediate codes are deployed in server, I don't care whether pre-compile takes 30 minutes or not if memory allocation and computation become more efficient. However this might be stupid idea.
JIT allows a range of optimisations that are not possible with AOT compilation. A JIT has access to more information at runtime such as profiling data and so can perform more informed optimisations. It can also change over the lifetime of the programme if observations change.

Some interesting stuff here http://wikis.sun.com/display/HotSpotInternals/PerformanceTec...

(comment deleted)
I see. Thank you for sharing that with me.
The JVM (at least the Oracle/Sun version) has some scary seeming memory allocation policies. One of the biggest offenders is its complete unwillingness to ever shrink the system allocated memory, even if the heap is 95% empty. For instance, if your application has a huge peak allocation period (whether your fault or an issue with soft references sticking about when you really don't want them), it will put memory pressure on the OS for the rest of its (process) life. If the JVM has an option of garbage collecting large amounts of objects or growing the heap, it generally prefers growing the heap. You can run quite a few Java applications with amazingly small heaps at everything will be fine (except for performance due to GC overhead).

The abstraction breaker here is that your application often has a set of ideal GC settings, which need to be set. You cannot forget about the garbage collector when using the JVM.

A blanket statement for a fairly specific use case seems irresponsible.
What blanket statement did I make? That I don't use the JVM? That doesn't seem like a blanket statement to me.
Great comment:

You can allocate as much or as little memory as your application needs. I run many personal web projects on a JVM sitting on top of a free-tier AWS EC2 micro-instance. I have tomcat6 instances running with <32MB footprint.

Perhaps you need to better understand what you're putting on the JVM and why it needs what it does

Please throw up a 'hello world' servlet on github and let me know which arguments to pass it to reduce the memory usage. I've tried, but I may have missed something, and yes I've tried all the obvious things like setting the heap size.

I think the commenter you're quoting is confusing the heap size with the total size. Or I'm missing something and would love for someone to show me what I'm missing.

I don't know about tomcat, as its memory footprint can be quite big. But Jetty's hello world is a 5 lines in Bash, and takes 9 MB:

http://wiki.eclipse.org/Jetty/Tutorial/Jetty_HelloWorld

Java ecosystem is too big, and it is common for newcomers to overlook the juicy parts. The mainstream frameworks and libraries reflect the mainstream use of java: big apps for medium/big companies.

It's taking 57.6MB for me. That's Real Mem in the macs Activity Monitor.
Well, I am using this on Ubuntu Lucid, with jdk 1.6.0_25-b06

You may wanna try playing with some variables. With the following command line:

   java -cp .:servlet-api-2.5.jar:jetty-all-7.0.2.v20100331.jar -client -XX:MaxPermSize=1M -Xmx2M -Xms2M HelloWorld

I've added -client -XX:MaxPermSize=1M -Xmx2M -Xms2M. It took it down to 7Mb from 9Mb. However, this should not concern you in VPS/Amazon EC2 instances, as you can always run linux there, and these problems should not come by.
This is on my linux VPS (64bit)

$ java -cp .:servlet-api-2.5.jar:jetty-all-7.0.2.v20100331.jar -client -XX:MaxPermSize=1M -Xmx2M -Xms2M HelloWorld Error occurred during initialization of VM Too small initial heap for new size specified

I can't get it to run in under 30MB RES according to top. This is after hitting it with a little traffic, i'm not sure if you hit yours with any traffic.

Ah, 64bit JVM. It likes to think it is of itself as enterprise. One thing that may help is -XX:+UseCompressedOops, and even -Xmn1M.

Note that depending on the enverionment it may say it is too small, so you may have to ramp up a bit some of these stats. I also get it if I set lower than then ones I gave.

Note that jvm is very tunnable[1,2]. Also note that you can use a 32 bit jdk in a 64bit machine. It won't get you beyond 2GB vm, but if you are going for small memory, this is not something that matters (and it should allow you to get to a very small memory footprint).

Also note that there are other JVMs, like Oracle's JRockit (with extra memory options[3]), and KVM[4] (designed for small memory footprint[5]).

But hey, that is lower than 32 MB already!

Edit

You can also try some other lesser drastic measures[6,7]. Note that you are getting in less mainstream use of the JVM, and things can get a little crazy in this area.

[1] http://www.oracle.com/technetwork/java/javase/tech/vmoptions...

[2] http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp

[3] http://download.oracle.com/docs/cd/E15289_01/doc.40/e15060/t...

[4] http://en.wikipedia.org/wiki/K_virtual_machine

[5] http://java.sun.com/products/cldc/wp/

[6] http://www.coderanch.com/t/202896/Performance/java/Ways-redu...

[7] http://stackoverflow.com/questions/4893192/process-memory-vs...

In j2ee (and servlet is part of j2ee, you should know that) there is no such thing as standalone servlet. Servlet is a part of the framework which includes all of j2ee interfaces and implementations.
I fired up an application written in play framework with -Xms64m -Xmx100m and hit it with ab -n 500 -c 20 http://localhost:9000/ the RES column in top remained under 86m. The application does alot more than "hello world", I can speed it up and decrease memory consumption by substituting groovy based templates with java based templates using a module called japid. If you want to use JVM for hobbyist apps start using frameworks which are not based on j2ee.
(comment deleted)
"hello world" - win xp 32 bit, sun jdk 6:

public static void main(String[] args) throws Exception { Thread.sleep(10000); System.out.println("hello world"); }

Heap - 5M, Used heap - below 2M. All defaults.

(the "sleep" is there to have time to connect Java VisualVM)

Sorry, I missed you are talking about "'hello world' web app", anyway there is no such thing a 'hello world' web app, there are very different application/web servers out there and you can't obviously compare jetty vs built-in jdk 6 com.sun.net.httpserver.HttpServer and WebSphere.
If one actually has a true practical reason to be concerned that processes won't consume less than $1 worth of RAM, I have to wonder why anything involving a managed environment such as the JVM was ever up for consideration in the first place.

I'd figure when dealing with that kind of memory constraint the only real contenders would be things like C, FORTH, or maybe PICAXE BASIC.