views:

271

answers:

14

Hello,

This has always been on my mind while programming, so i thought i'd spit it out before it actually gets to me.

What should i be more worried about? The memory the application consumes, or the performance it takes. By this i mean should i be focused upon using less memory for of the application and using more performance (eg. loading via database, and dumping it after use), or using less performance and using more memory (eg. caching)

My conditions for the application: - It's a server application, so it's not meant to be ran on desktops, etc, I have 6GB of ram, and I have a quad-core

+2  A: 

There's no one right choice - it depends on your application and its requirements. However, it's often a one-or-the-other choice - you can't often (if ever) maximize performance and reduce memory consumption. If this is any kind of critical system, the maximum bounds for memory and/or lowest bounds for performance should be specified by the customer - if they aren't, they should be.

Thomas Owens
+1  A: 
  1. Make it work.

You're going to get different answers and it honestly depends per-application. There is no blanket answer that covers all cases except for:

  1. Make it work.

Software can be overthought.

Getting specific, most operating systems are pretty good at caching disk I/O -- if you're doing a lot of heavy work with, say, a SQLite database, by the time you're a few connections in the operating system will likely have thrown the whole thing in memory anyway. Don't outthink the OS, in most cases.

Jed Smith
A: 

It depends on many factors. Which of the two will be limiting first? Do other applications need to run on the same server? Which is the harder to extend?

Paul
+6  A: 

Consider the amount of data you will be dealing with and the responsiveness you require. Put some thought into the design. Build it to be maintainable, and get it working.

Then profile, and address your actual bottlenecks.

retracile
This answer is quite incomplete as to be unhelpful -- I think it needs examples for a couple cases of responsiveness. How long should it take to generate a webpage for a user? Send an email? Index the contents in a CMS? The answer is different, and more complex than "the responsiveness you need."
BobMcGee
@BobMcGee The answer is as specific and complete as the question was. The question doesn't tell us if this has web pages, if there is a CMS involved, if email is an issue. The question needed a general answer that suggested stepping back and thinking about what should matter to the asker. Once he knows that and has an appropriate design to address that, then maintainability and correctness come before performance.
retracile
A: 

It depends

Ask a tangible question!

EDIT: If you think about caching at the design phase, then go back to start and start it again (caching is always a compromise solution)!

frunsi
+1  A: 

Even with your specs given this still depends on the workload your application is going to see.

  • If you are processing small amounts of data at a time, you may optimize performance by prefetching the next N chunks and thereby increasing memory consumption.
  • If your data is rather large, it may pretty soon fill your main memory completely and reading ahead will lead to thrashing (e.g., reading ahead forces writing data back to disk/database before it is completely processed; then you need this data back in memory and thereby force swapping of these read-ahead values).

So, first get a working version of your app. Then do profiling and see what the bottlenecks are. (Premature optimization is the root of all evil! -- Donald E. Knuth)

BjoernD
+1  A: 

They both are important. You might want to cache certain objects in memory for having a better performance which might increase the memory footprint. On the other hand if your application is spending a lot of time with garbage collection (as in .net), or having unmanaged resources which have not yet released the memory, you are going to have performance issues

ram
+1  A: 

I think you should work to achieve a balance between both memory and processor usage.

If you're working on a server component, I would be worried about making it work with multiple users. How many users can your application serve? Can you bring more users using same resources?

Rubens Farias
+1  A: 

You can think of performance in terms of throughput and response time. Find ways to measure these two factors, and to setup the type of load that your system needs to handle and work from there. The memory/processing time (what you are calling "performance") decisions come once you have measured your throughput/response time under load. In general, you should try to use as much of the CPU as possible (to get the best throughput), so you can exploit all of the memory you have available.

Francis Upton
+1  A: 

This question is as old as programming itself. The answer is, unfortunately, "it depends." If you are writing an application for a system that has 32 GB of RAM, and your software is the only thing that will be running, you should write your code to take advantage of that. If, on the other hand, you are writing code that will run on an embedded system, you should probably use as little memory as possible. What's MOST important is that you are aware of these trade offs, profile your code, and optimize whatever the biggest bottleneck is.

Benson
+8  A: 

Your question has drawn a lot of Zen Buddhism-like responses. I hope to do better.

Your memory limit is hard: If you exceed it, even if there's virtual memory, your app will crawl and you'll be the laughing stock of all.

Your CPU time is unlimited: Your app will take whatever time it needs; hopefully it will be sufficiently parallel that all 4 CPUs will be, for the most part, cooking with full steam until your app is finished.

Many Computer Science problems have a variety of solutions with various tradeoffs of memory against time. So: Be generous with memory until you use at least about half of it (if that helps; don't waste memory for the heck of it!) but stop while there's enough memory left that you don't need to worry about exceeding the limit, even in exceptional cases or accidentally.

Now that you've allocated your memory resources, you can try to tweak some more small performance gains out of your code. But don't bother overdoing it.

Done.

P.S. If it doesn't work correctly and reliably, all the preceding effort is worthless. Keep that in mind all the time!

Good luck.

Carl Smotricz
The CPU time vs. hard memory limit formula is correct in theory, but in practice you can easily increase memory (add or replace RAM chips), but the CPU power is limited and increasing it is much more expensive!
frunsi
I understood your point, and you are right (with being generous with memory). But in current practice the decision is often to waste memory, especially in server applications. Because memory is cheap and easy to extend!
frunsi
We're mostly on the same page. But I'd like to point out that in a corporate environment the practical cost of upgrading memory can be wildly uncorrelated with the actual purchase cost. I've been in situations where it was considered simpler to buy a new machine than to increase memory for the existing one [sigh]. I also agree that many development efforts squander resources for lack of better knowledge.
Carl Smotricz
+2  A: 

It really depends on the kind of program. If you can control the target machines it makes it a bit easier. If you know that even at the extremes, you aren't going to run out of memory, then you ight as well use all you want. There is no advantage in memory not used by anything.

In general I think of things in several categories.

Supplemental programs, If the program is not performing the primary use of the machine then It should try and conserve memory, While not a server thing the examples I usually think of in this case are Desktop widgets and Tomboy.. They are not the primary use, so they shouldn't take too many resources away from the system, that could potentially impair the performance of the primary application.

General applications, These have simple priorities. Firstly do the job required, then if it's slow, make it faster. You shouldn't need to worry about memory too much unless you are being foolhardy (or using python or java :-) )

Many instance applications. If you expect the user to have many instances of the application either as multiple tasks or just multiple instances within the same task (like multiple firefox windows/tabs), Because things multiply you need to keep a handle on memory usage. Speed s not so much an issue of making operations faster as ensuring that idle instances are not actually doing any processing.

Jumbo applications, If your application actually has a huge task to perform, like say image manipulation, then you should consider memory usage from the outset. I suspect Evolution consumes a lot of ram (currently 142 meg on my machine) because they had a jumbo task but didn't realise it. I have a lot of email, mostly incoming from lists,

If you can control your target environment then you can just have as much ram as needed, It's easier for you. If other users are going to have your program then requiring more memory is still easier for you, but it's not friendly to the users.

I'm doing development on an OLPC XO, Largely trying to make the system nice with supplemental programs. That means I'm really focused on low memory usage, but even on a system that is that memory restricted I find that there is not much use in further reducing memory usage. After boot it has over 150 meg free. Which is enough to run all of the lightweight apps you want but most of the heavier apps will be a strain. There is very little middle ground. Further optimising a 2 meg app to only use one meg doesn't give you that much more elbowroom if you are running an app like firefox.

Lerc
Just a note: These days choice of algorithms and libraries matters far more than programming language. Yes, Java and Python use more memory than C, but when you add in the various levels of DBMS, caching, and so forth, choice of algorithms and approaches is far more important.
BobMcGee
I agree absolutely about libraries, and I was considering writing another response discussing that topic. For all that people say 'Make it work first then profile and optimise'. That is useless if you are heavily library dependant. If you make it work first then profile and find that your system is too slow/bloaty due to a library that your program is built upon, usually the only way to fix things is to rewrite. This need not be the case if the library has clearly defined bounds of behaviour and a good interface, but too many libs want to control your program structure (like GTK etc.)
Lerc
+1  A: 

What do your customers require?

You should have at least some idea of what platform your users will be running it on. You also need to have some idea of the performance requirements (transactions per second, or whatever). Produce some conservative estimates of the minimum spec platform you will require, then design to that.

You also seem to be a bit confused in your post - using less memory is not an end goal if the purpose is to use it for caching (i.e. you are actually using the memory saved to improve performance). In which case, go for whatever gives you most bang-per-developer-hour.

Robert Tuck
+1  A: 

It's best not to think about it in the abstract, but in terms of a concrete design.

  1. If you run out of RAM, you'll be sorry, so keep your data structure as clean and simple as possible, even if it seems that you might have to code some loops that might seem inefficient. Complexifying code and data structure because of concerns about performance is the essence of premature optimization. And, as much as people inveigh against premature optimization and claim they don't do it, they do it anyway, to a scary degree.

  2. When it is working and doing what you need it to do, and if you actually have one or more performance problems, then deal with performance. The usual method is to use a profiling tool, but this is the method I prefer.

Be careful of multi-cores. Parallelism and threads allow you to get multiple agents working overlapped in time, such as disk heads, CPUs, or human clients. If, for example, your processes are I/O bound, trying to do them on multiple cores won't help much and might hurt. If there is only a single physical disk drive, you might not gain much by trying to overlap I/O bound threads, and it might hurt. On the other hand, if you've got a thread per user, that might make sense because such threads spend most of their time waiting for the user.

Mike Dunlavey
I concur on IO bound. Especially given that newer Intel architectures which seem to be much faster while disk speeds haven't increased in proportion. This makes a good case for using more memory - you are more likely to be disk bound and putting more in memory will keep the CPU working.
AngerClown