Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

The benefit of a compiled application was that all the libraries and classes are loaded one time and sit waiting for input right?

I come from a background working with PHP and the resources/classes that used are loaded each page request which puts an bad load on the server memory. For example, given the PHP core uses 1MB of memory, and a wordpress loads another 7MB of objects - you end up with 8MB being loaded every request.

I assumed this was the same process for other scripting languages like Python and Ruby also.

However, I have started looking at node.js (because JavaScript is so beautiful) and it seems that it is loaded once (and whatever memory needed is only taken once) and then sits around waiting for requests sharing the classes it has loaded among any new threads (is that the right term?) so they don't have to re-load them.

So PHP would take 8MB process * 10 requests = 80MB for ten concurrent requests to wordpress. This sounds like node.js would take 8MB process + 10 requests = ~14MB.

Is this really true? Are there any other scripting languages that do this?

share|improve this question
1  
The answer to both your questions is "Yes." Perhaps you'd like to ask for more specific information. –  S.Lott Jun 27 '11 at 18:47
    
@S.Lott, what are the other languages that share resources rather than re-loading them each request? –  Xeoncross Jun 27 '11 at 19:23
    
Please update the question to reflect the information you're looking for. Please don't add comments to a question you own. –  S.Lott Jun 27 '11 at 19:31
add comment

2 Answers

up vote 2 down vote accepted

As @S.Lott said, the answer is "yes". The more complicated answer is, "There are many ways this can be done." Read on for a full explanation of many of the common ways in which memory can be shared across concurrent requests.

To understand more, you need to understand how memory is actually managed by the operating system, and used by the program.

The operating system assigns memory to processes. Processes are running programs that cannot affect each other's memory. Within a process there can be one or more threads that the operating system knows about. Each thread is attempting to do things, access memory, etc, and can wind up (at the operating system's discretion) being scheduled sequentially or in parallel on one or more CPUs. (Schedulers prefer to keep threads on a single CPU, but not always.) Each thread is then responsible for doing whatever it wants to do. A thread can be, depending on the program, doing one thing or multiple things.

You are familiar with a multiple processes model where memory is assigned to processes that then each do one thing. In this model every process has separate memory. Thus if you have 10 processes, each of which has loaded 8 MB of data, you have 80 MB of memory required. In PHP by default each process may serve many requests over its lifetime, but the maximum number of parallel requests being served is the same as the number of processes you have running.

The next option is multi-threading. So you can load data into the thread, and then multiple threads can read that data. Many languages use multi-threading in this form. For instance Java and Python do that. The disadvantage to this style is that weird things can happen when 2 threads are both doing something with the same memory, and that is no fun to debug.

Moving on, the trick that Node.js uses is simpler. Remember that I said that depending on the program a thread can do one or multiple things? Well Node.js uses a callback style of programming that every time you have an event it does something, registers a callback for the next event, then does something else. With this style a single thread can be waiting for events for many requests. This style can be used in any language, but it is more convenient when you have an entire framework that does the same thing. Some languages actually have facilities to hide all of the callback details from you. If you hear about "green threads" or "cooperative multi-threading", that is what is going on. Examples of languages that use this include Ruby and Racket.

The next trick is that the operating system can be explicitly told to share blocks of memory. This is available with low-level calls to things like mmap, which can be exposed in higher level languages in various ways.

Moving on, the operating system sometimes knows that it can share memory. This is what is happening in the case of compiled languages. Shared libraries can be read from, but not written to. Such read-only memory can be loaded into many processes. You've seen this when shared libraries get loaded into many C programs at once. In principle an interpreted language could use this mechanism itself, and I've seen discussion about doing so, but it generally doesn't make sense and they don't.

And a final trick. Many operating systems (all variants of *nix for example) have the idea of copy-on-write memory. This memory can be shared between any number of processes, but any process that tries to write to it will see the memory copied elsewhere, will be pointed there, and can then read and write from there. This is used to make the fork call efficient. If you're using, for instance, Apache with a pre-fork model, you can take advantage of this by loading a lot of data into the parent Apache process. Then every forked copy will start off sharing a lot of data. Over time that data comes unshared, but if you kill processes after a certain time you can reduce memory pressure. I don't know how easy this is to do with PHP, but it is a very common mod_perl trick, and can let memory be shared.

share|improve this answer
    
thanks for the detailed overview. I'm still a little new to this so I want to verify that there is no way PHP can manage memory as efficiently as the shared memory of Ruby or single process of Node.js correct? Since (to my knowledge) a PHP process can only do one thing at a time I spawn multiple processes to handle multiple tasks concurrently which wastes resources correct? –  Xeoncross Jun 28 '11 at 15:55
    
@Xeoncross: Well the callback style used in Node.js can be used in any language, including PHP. However to do it would be a lot of work. Because it only takes a single blocking call to block everything. So one database call. One filesystem read. One tight loop. And oops, no more concurrency. Plus Apache by default is configured to only accept one request at a time. (Node.js is a similar amount of work, but most of it has already been done for you.) –  btilly Jun 28 '11 at 17:56
    
True, node.js has an asynchronous PostgreSQL library now for non-blocking database calls. I guess it's just too late in the PHP language design for this type of stuff. I also need to take a better look at how Ruby or Python handle this type of thing. –  Xeoncross Jun 28 '11 at 19:08
add comment

Yes.

The issue with PHP is not about the language, it's about the running environment it uses.

Almost any language let's you write any kind of program, not only web pages. One kind of program is a webapp server that starts up, and sits in a loop waiting for requests. In most cases, this is run behind a web server (Apache, Nginx, lighttpd, etc) and gets the requests using a specific communication channel, either using a specific module in the server (like uWSGI, mod_wsgi, jakarta, etc.) or some standard protocol (FastCGI, or even HTTP)

Yes, you could do this in PHP if you want! (using php-cli, or something similar) but I don't think you would be able to use any framework in that operation mode.

share|improve this answer
    
I run PHP as a CGI script listening on port 9000 behind nginx. Does that script keep the classes in memory for each load then? I also have about 10 PHP processes running to handle enough requests - is there any way they can share the resources they load? –  Xeoncross Jun 27 '11 at 19:22
    
CGI is also started per request. That's why FastCGI (which stays up) is faster with basically the same protocol. –  Javier Jun 27 '11 at 19:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.