I did some performance testing against a web application that I helped write this weekend. I used The Grinder and was quite happy with the beta version. This lets you write scripts in Jython and uses the quite nice HTTPClient library. The Grinder, like most other performance tools, has an admin interface (the console) and a set up distributed agents that are given tasks and communicate results back via the network to the console. I used the HTTP client, but it looks like you can ‘grind’ anything you can talk to via java, from databases to email servers.

I did run into a few problems. I’m using cygwin on WinXP, and had some difficulties running java from the command line. The fix was to use the cygpath command, like so:

# to start the agent
CLASSPATH=`cygpath -p -w /home/Owner/work/grinder/grinder-3.0-beta20/lib/grinder.jar:\
$JAVA -cp $CLASSPATH net.grinder.Grinder

The client application that I was testing doesn’t use cookies (it’s a J2ME application, and the MIDP spec doesn’t support cookies out of the box). Or rather, it uses cookies, but only to grab the first one that the server sends, store it off, and then pass it back as a query parameter. This type of configuration isn’t The Grinder’s sweet spot, and I had to do a bit of hacking to make sure the appropriate cookie value was sent with the appropriate client request. It would have been nice to use contexts but The Grinder wraps the HTTPConnection in its own class. Apparently, if you are simulating use by a browser, cookies are apparently handled correctly. One gripe–there’s no javadoc for the main classes available on The Grinder’s website, so you have to grab the source if you want to see interactions between pieces (for example, how net.grinder.plugin.http.HTTPRequest interacts with HTTPClient.HTTPConnection).

I also mucked with some of the properties, primarily initialSleepTime. You’ll want to make sure that you read about these properties–I blithely uncommented what was in the sample grinder.properties and ended up with an obscene value for grinder.sleepTimeFactor.

After all the setup, I was able to hammer our server. I discovered two useful things: an error in our logout code, which threw exceptions around 10% of the time, and also discovered that our connection timeout between Apache and Tomcat was set incorrectly. Changing this from 0 to 1000 fixed the dreaded SEVERE: All threads are busy, waiting. Please increase maxThreads or check the servlet status error that I was getting. In addition to these two useful bugs, by making some assumptions about how the application will be used, I was able to gimmick up some interesting numbers about supportable users.

I like The Grinder a fair bit. It’s got a nice GUI. It’s still under active development. I’m a bit leery of using beta software (especially open source beta software), but a poll on the homepage convinced me to try the beta. By using this, I was also able to pick up snatches of python which is a new language to me (finally got to consult my long unused copy of Learning Python). I considered looking at JMeter, but The Grinder appears to be a bit more recently maintained. It’s no LoadRunner, but then again, it doesn’t pretend to be. All in all, if you’re in the market for a cheap, quick performance tool, The Grinder is worth a look.

25 thoughts on “The Grinder

  1. Kris Thompson says:

    Besides JMeter’s lack of maintaince is there any other strong reason for using Grinder? Do you feel that if users know JMeter they should switch?

  2. Dan Moore says:

    From looking at JMeter, it appears to have a much nicer user interface both for building tests and displaying results. You can build a test visually, which is something that The Grinder just doesn’t let you do (at least V3–I don’t know about The Grinder V2).

    The big plus of The Grinder is being able to use jython to write arbitrary tests. Consider, on the other hand, JMeter, where, if you don’t want to do one of the supported actions (here: http://jakarta.apache.org/jmeter/usermanual/test_plan.html#samplers) , which cover, granted, everything I’d want to do in a test, then I’m not really sure what you’d do. In the example above, I was taking the value of a cookie and setting a query param based on that value, and it’s not clear to me how I’d do it in JMeter.

    I also don’t see POST support in JMeter, whereas The Grinder definitely has that (http://grinder.sourceforge.net/g3/script-gallery.html#fba).

    Also, JMeter seems to be built for use from a single computer, though it does explicitly have support for remote agents (http://jakarta.apache.org/jmeter/usermanual/remote-test.html). The Grinder is set up from the start to have the differentiation between agent (data collector) and console (data displayer). This is a small difference.

    Again, I haven’t used JMeter, this comment is just based on reading the documents at the JMeter site.

  3. Krishna says:

    We have downloaded the source code Grider3 (beta version) but the grinder.jar file is missing (the entire Lib folder itself is missing). Please suggest a solution for the problem.

  4. Sailaja says:

    The following error is displayed when
    java net.grinder.Grinder is given

    Error initialising grinder process: net.grinder.common.GrinderException: Mandato
    ry property ‘grinder.plugin’ not specified
    net.grinder.common.GrinderException: Mandatory property ‘grinder.plugin’ not spe
    at net.grinder.common.GrinderProperties.getMandatoryProperty(GrinderProp
    at net.grinder.engine.process.GrinderProcess.instantiatePlugin(GrinderPr
    at net.grinder.engine.process.GrinderProcess.(GrinderProcess.java:
    at net.grinder.engine.process.GrinderProcess.main(GrinderProcess.java:10)
    The Grinder version 2.8.6 finished

    Inputs reqd?

  5. roobeast says:

    Jmeter does have POST support. It’s selectable on the HTTPRequest component. I have been able to get jmeter to do pretty reasonable stuff like hit a home page, log in as a user with a post, cycle through some account history pages using regexes to pull out urls. You can then loop all this with different users. I’m interested in taking a look at grinder.

  6. windy says:

    Hi Roobeast
    Could you please tell me how you “loop all this with DIFFERENT USERS”?

    Thanks a lot

  7. TP says:

    same problem as sailajabatchu@yahoo.com

    Mandatory property ‘grinder.plugin’ not specified

    any hints?

  8. Dan Moore says:

    Hi TP,

    So, there’s a file called grinder.properties that needs to be in the classpath of the agent scripts. For the Grinder v3 (which is what I used) I didn’t have to have a grinder.plugin property, but I did have to have the grinder.properties file. If you’re using v2, perhaps http://grinder.sourceforge.net/manual/properties.html will help you out. From http://grinder.sourceforge.net/manual/http-plugin.html, it looks like the grinder.plugin property needs to be set to net.grinder.plugin.http.HttpPlugin

  9. Rodrigo says:

    Where does the grinder.propeties file nedd to be placed ???

    I think it is not finding it when running the agent.

  10. alex says:

    I am using grinder2.8.1 aftr getting into a mess trying to use jython and the plugin files. grinder2 seems to be working perfectly fine, but i am encountering a problem in hitting our test site. We r using cookies based authentication and i tried to use the HTTPSniffer for setting the username and password as post parameters. But I am always getting a ‘302 redirection message’ as the output. I am displaying the output by manually inserting sops in the grinder source code. I saw something like authenticationrealm , username and pwd as grinder properties. Could you help me out in setting the correct configuration?


  11. Pingback: Anticlue

  12. vidya says:

    when I am running the below .py script, its not taking the values of the username and password from the file until we explicitly specifies it in the .py script.. But if we are trying to print it, its printing the values. Below is the code, so can u plz help me to find out the problem.

    def page2(self):
    “””POST index.jsp (request 201).”””
    tre = TestRandomise(“users.txt”)
    (user,passwd) = tre.getUserInfo()
    #user = ‘aa’
    #passwd = ‘a’
    result = request201.POST(‘/purchase/Jsp/Common/index.jsp’,
    ( NVPair(‘dummy_username’, user),
    NVPair(‘dummy_password’, passwd),
    NVPair(‘imgLogin.x’, ‘0’),
    NVPair(‘imgLogin.y’, ‘0’), ),
    ( NVPair(‘Content-Type’, ‘application/x-www-form-urlencoded’), ))
    # 1 different values for token_subject found in response; the first matched
    # the last known value of token_subject – don’t update the variable.
    self.token_j_username = \
    httpUtilities.valueFromHiddenInput(‘j_username’) # ‘adt’
    self.token_j_password = \
    httpUtilities.valueFromHiddenInput(‘j_password’) # ‘adttest’

    return result

  13. magudapathy says:


    if i want to test my application using grinder.
    how can i invoke my application?

    What are changes need in grinder.properties file

  14. tal says:

    can the grinder get an XML of users and password to log in with for each preccess ?

  15. moore says:

    Hi Tal,

    To simulate different users for the grinder, this faq post is probably helpful (even though it just pulls the username/pw from a file):

    In order to do it by pulling an XML file down and then parsing it, you just need to write the python to do so (instead of from a flat file like the FAQ does). Here’s a link that might help you do that:

    Disclaimer: I have not tested any of this code.

  16. mauricio cobo says:

    C:\Documents and Settings\hcoboo>java net.grinder.Grinder %GRINDERPROPERTIES%
    15/04/10 05:50:53 PM (agent): The Grinder 3.4
    15/04/10 05:50:53 PM (agent): connected to console at /
    15/04/10 05:50:53 PM (agent): waiting for console signal
    15/04/10 05:51:11 PM (agent): Clearing file store
    15/04/10 05:51:11 PM (agent): Updating file store: “grinder.properties” (6831 by
    15/04/10 05:51:11 PM (agent): Updating file store: “hugo.py” (690 bytes)
    15/04/10 05:51:11 PM (agent): Updating file store: “jdbc.py” (1743 bytes)
    15/04/10 05:51:13 PM (agent): received a start message
    15/04/10 05:51:13 PM (agent): DEBUG MODE: Spawning threads rather than processes
    15/04/10 05:51:13 PM (agent): worker SIS_CEN_006-0 started
    15/04/10 05:51:15 PM (process SIS_CEN_006-0): Error running worker process (: No module named oracle
    from oracle.jdbc import OracleDriver
    File “C:\Documents and Settings\hcoboo\.\SIS_CEN_006-file-store\current\
    jdbc.py”, line 8, in )
    15/04/10 05:51:15 PM (agent): finished, waiting for console signal

  17. mauricio cobo says:


  18. moore says:

    Hi Mauricio,

    I’m not sure what you’re asking…

  19. Sath says:

    mauricio cobo says “IF I HAVE THE LIBRARY (. JAR) OF ORACLE ojdbc14.jar AND DOES NOT WORK”

  20. Sath says:

    Hi Moore,

    I was trying to start Grinder 3.4. I am able to launch the console using the command “java net.grinder.Console”, but not able to run the agents. I used the command “java net.grinder.Grinder” it throws an error “Exception in thread “main” java.lang.NoClassDefFoundError: net/grinder/Grinder”. Can you please help

  21. moore says:

    Thanks Sath.

    Regarding mauricio cobo’s issue, I’m not sure why adding the oracle library into the classpath would inhibit the grinder–probably a dependency collision.

    Regarding your issue, I’d check and make sure that your classpath is set correctly.

    Hope this helps.

  22. Liljana - LiLy says:


    I am trying to connect Jython 2.5.1, by using Grinder 3.4 to Oracle XE 10.g database.

    from java.sql import DriverManager
    from net.grinder.script.Grinder import grinder
    from net.grinder.script import Test
    from oracle.jdbc.driver import OracleDriver

    I set up the classpath like this:
    set JYTHON_HOME=C:jython2.5.1
    set CLASSPATH=”%JYTHON_HOME%jython.jar”
    set CLASSPATH=”%JDBC_HOME%ojdbc14_2.jar”;%CLASSPATH%

    but it keeps throwing the error:
    19.10.10 10:08:11 (process OFFICEVIENNA01-0): Error running worker process (: No module named oracle
    from oracle.jdbc import OracleDriver

    I’ve downloaded the driver from this page:
    I’ve been stragling with this error already 2 days.

    Can somobody tell where is the error. What do I do wrong?

    Maybe suggest me a link or code example or any other code example with another driver and DB that would work.


  23. moore says:

    Hi Liljana,

    It looks like you’re missing a separator in your CLASSPATH variable. Try this:

    set JYTHON_HOME=C:/jython2.5.1
    set CLASSPATH=%JYTHON_HOME%/jython.jar
    set CLASSPATH=%JDBC_HOME%/ojdbc14_2.jar;%CLASSPATH%

    No quotes (not needed unless you have spaces in your path) and forward slashes.

    Hope this helps.

Comments are closed.

© Moore Consulting, 2003-2017 +