AP4R (Asynchronous Process for Rails )
What is AP4R ?
AP4R, Asynchronous Processing for Ruby, is the implementation of reliable asynchronous message processing. It provides message queuing, and also message dispatching. Using asynchronous processing, we can cut down turn-around-time of web applications by queuing, or can utilize more machine power by load-balancing
Features
Business logics can be implemented as simple Web applications, or ruby code, whether it's called asynchronously or synchronously.
Asynchronous messaging is reliable by RDBMS persistence (now MySQL only) or file persistence, under the favor of reliable-msg.
Load balancing over multiple AP4R processes on single/multiple server(s) is supported.
Asynchronous logics are called via various protocols, such as XML-RPC, SOAP, HTTP POST, and more.
How strong is AP4R?
QESTION: I am considering on the use of AP4R for our project named "CLIK" for the time being. CLIK is essentially a Rails front-end to a data crunching job that ultimately creates a climate prediction. Some of these jobs only takes a few seconds to finish, some a few minutes, and intensive calculations 30 minutes or more. Obviously we need to put many of these jobs in the background and get the output after the job is done. Actually we use a separate data processing server on a remote machine using Drb. I explored a few solutions by googling and found projects like "Background Job", "rudeQ", "Workling" etc, which provide queing and background processing. My question is how "AP4R" compares to or is different from these others?
ANWSER: One big difference is robustness. AP4R has 'SAF' function which guarantees a message delivery between your CLIK and AP4R server. As a result, no matter what happens, for example database and N/W trouble, server down and so on, you don't lose your crunched data. A message is stored in a database before sending AP4R, you can resend the message after recovery from system failure.
- But when I wrote my AP4R demo, I'm so disappointed : The architecture is bloated, less support drb, full support message delivery via various web service protocol HTTP, XMLRPC
Spawn
Features
Fork or thread a background process
Very simple, it's just a rails plugin does not need drb server => weak.
If you really need a queue, use Starling, which Blaine Cook of Twitter released, like, yesterday. Or SQS if you need really huge storage. If you just want to fire and forget a local process as you say, I think Spawn is pretty good ( http://rubyforge.org/projects/spawn ). I haven’t actually used it but seems like the best of the forking bunch. That should eliminate the startup overhead. On the other hand, you don’t get any message reliability or cross-machine scheduling. ..I agree that BDrb is shady (actually all of Drb is shady). ap4r is too
bloated. Thruqueue is promising if you make it past the crazy dependencies list. BackgroundFu is like a worse Spawn.”- Spawn is simplest, we cannot manage our process (fire and forget) and not have scheduling
Is AP4R really good?
After a few hours modify Asset Packager, my rails apps auto combine css, js when deploy on production mode, especially i use yuicompressor instead of default jsmin.
:D
ref:http://synthesis.sbecker.net/pages/asset_packager
NuVia GHX project has a big problem about better performance, YSlow show me that my site is very very slow (grade F ). After two days dig into research gzip javascript and optimize extjs library my site get better grade D (yeah).
If you have a NGINX server let config it auto gzip static file to accelerate your site (don't use rails plugin to gzip such as Tiny MCE )
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/xml; #add text/javascript text/css
gzip_disable "MSIE [1-6]\.";
http://wiki.codemongers.com/NginxHttpGzipModule?highlight=%28gzip%29
Compress Your Javascript
First, you can try to make the javascript file smaller itself. There are lots of utilities to “crunch” your files by removing whitespace and comments.
You can do this, but these tools can be finnicky and may make unwanted changes if your code isn’t formatted properly. Here’s what you can do:
1. Run JSLint (online or downloadable version) to analyze your code and make sure it is well-formatted.
2. Use Rhino to compress your javascript. There are some online packers, but Rhino actually analyzes your source code so it has a low chance of changing it as it compresses, and it is scriptable.
Install Rhino (it requires Java), then run it from the command-line:
java -jar custom_rhino.jar -c myfile.js > myfile.js.packed 2>&1
This compresses myfile.js and spits it out into myfile.js.packed. Rhino will remove spaces, comments and shorten variable names where appropriate. The “2>&1″ part means “redirect standard error to the same location as the output”, so you’ll see any error messages inside the packed file itself (cool, eh? Learn more here.).
Using Rhino, I pack the original javascript and deploy the packed version to my website.
Debugging Compressed Javascript
Debugging compressed Javascript can be really difficult because the variables are renamed. I suggest creating a “debug” version of your page that references the original files. Once you test it and get the page working, pack it, test the packed version, and then deploy.
If you have a unit testing framework like jsunit, it shouldn’t be hard to test the packed version.
Eliminating Tedium
Because typing these commands over and over can be tedious, you’ll probably want to create a script to run the packing commands. This .bat file will compress every .js file and create .js.packed:
compress_js.bat:
for /F %%F in ('dir /b *.js') do java -jar custom_rhino.jar -c %%F > %%F.packed 2>&1
Of course, you can use a better language like perl or bash to make this suit your needs.
Optimize Javascript Placement
Place your javascript at the end of your HTML file if possible. Notice how Google analytics and other stat tracking software wants to be right before the closing tag.
This allows the majority of page content (like images, tables, text) to be loaded and rendered first. The user sees content loading, so the page looks responsive. At this point, the heavy javascripts can begin loading near the end.
I used to have all my javascript crammed into the
section, but this was unnecessary. Only core files that are absolutely
needed in the beginning of the page load should be there. The rest,
like cool menu effects, transitions, etc. can be loaded later. You want
the page to appear responsive (i.e., something is loading) up front.
Load Javascript On-Demand
An AJAX pattern is to load javascript dynamically, or when the user runs a feature that requires your script. You can load an arbitrary javascript file from any domain using the following import function:
function $import(src){
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',src);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
// import with a random query parameter to avoid caching
function $importNoCache(src){
var ms = new Date().getTime().toString();
var seed = "?" + ms;
$import(src + seed);
}
The function $import('http://example.com/myfile.js') will add an element to the head of your document, just like including the file directly. The $importNoCache version adds a timestamp to the request to force your browser to get a new copy.
To test whether a file has fully loaded, you can do something like
if (myfunction){
// loaded
}
else{ // not loaded yet
$import('http://www.example.com/myfile.js');
}
There is an AJAX version as well but I prefer this one because it is simpler and works for files in any domain.
Delay Your Javascript
Rather than loading your javascript on-demand (which can cause a noticeable gap), load your script in the background, after a delay. Use something like
var delay = 5;
setTimeout("loadExtraFiles();", delay * 1000);
This will call loadExtraFiles() after 5 seconds, which should load the files you need (using $import).
You can even have a function at the end of these imported files that
does whatever initialization is needed (or calls an existing function
to do the initialization).
The benefit of this is that you still get a fast initial page load, and users don’t have a pause when they want to use advanced features.
In the case of InstaCalc, there are heavy charting libraries that aren’t used that often. I’m currently testing a method to delay chart loading by a few seconds while the core functionality remains available from the beginning.
You may need to refactor your code to deal with delayed loading of components. Some ideas:
- Use SetTimeout to poll the loading status periodically (check for the existence of functions/variables defined in the included script)
- Call a function at the end of your included script to tell the main program it has been loaded
Cache Your Files
Another approach is to explicitly set the browser’s cache expiration. In order to do this, you’ll need access to PHP or Apache’s .htaccess so you can send back certain cache headers (read more on caching).
Rename myfile.js to myfile.js.php and add the following lines to the top:
<?php
header("Content-type: text/javascript; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>
In this case, the cache will expire in (60 * 60 * 24 * 3) seconds or 3 days. Be careful with using this for your own files, especially if they are under development. I’d suggest caching library files that you won’t change often.
If you accidentally cache something for too long, you can use the $importNoCache
trick to add a datestamp like “myfile.js?123456″ to your request (which
is ignored). Because the filename is different, the browser will
request a new version.
Setting the browser cache doesn’t speed up the initial download, but can help if your site references the same files on multiple pages, or for repeat visitors.
Combine Your Files
A great method I initially forgot is merging several javascript files into one. Your browser can only have so many connections to a website open at a time — given the overhead to set up each connection, it makes sense to combine several small scripts into a larger one.
But you don’t have to combine files manually! Use a script to merge the files — check out part 2 for an example script to do this. Giant files are difficult to edit - it’s nice to break your library into smaller components that can be combined later, just like you break up a C program into smaller modules.
Should I Gzip It?
You probably should. I originally said no, because some older browsers have problems with compressed content.
But the web is moving forward. Major sites like Google and Yahoo use it, and the problems in the older browsers aren’t widespread.
The benefits of compression, often a 75% or more reduction in file size, are too good to ignore: optimize your site with HTTP compression.
All done? Keep learning.
Once you’ve performed the techniques above, recheck your page size using the tools above to see the before-and-after difference.
I’m not an expert on these methods — I’m learning as I go. Here are some additional references to dive in deeper:
- Ajax patterns: Performance Optimization
- Think vitamin: Serving Javascript Fast
- Detailed post on page load time
- Detailed Caching Tutorial and online tool to check your cacheability
Ref http://betterexplained.com/articles/speed-up-your-javascript-load-time/
I have worked with ruby on rails for 1 year, try to improve my knowledge.