1

I'm completely new to Groovy, so apologize in advance if I'm missing something obvious.

I'm trying to do some simple REST API scripting in Groovy, but first wanted to understand it's performance for requests/JSON parsing vs Python. I wrote the following script - and am seeing that the imports are taking ~7 seconds. Is there any way to 'include' those in the script, so it doesn't take so long on each run?

def now = new Date()
println now.format("yyyyMMdd-HH:mm:ss.SSS", TimeZone.getTimeZone('UTC'))
@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
@Grab('oauth.signpost:signpost-core:1.2.1.2')
@Grab('oauth.signpost:signpost-commonshttp4:1.2.1.2')

import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.*


for (i = 0; i <1; i++) {
    def Client = new RESTClient("http://www.mocky.io/v2/59821b4a110000a9103964eb" )
    def resp = Client.get(contentType: JSON)
    def myResponseObject = resp.getData()

    println myResponseObject.items[i].id

}
now = new Date()
println now.format("yyyyMMdd-HH:mm:ss.SSS", TimeZone.getTimeZone('UTC'))

I get this output:

~$ time groovy Requests.groovy 
20170802-18:36:24.556
10
20170802-18:36:25.290

real    0m7.173s
user    0m4.986s
sys     0m0.329s

Just the first few lines of Grabs and imports are taking the majority of the runtime , and that's what I'd like to cut down.

cdm
  • 719
  • 2
  • 10
  • 22
  • Possible duplicate of https://stackoverflow.com/questions/254385/how-do-i-auto-load-a-database-jar-in-groovy-without-using-the-cp-switch – bdkosher Aug 02 '17 at 19:20
  • @bdkosher - not quite what I'm looking for - that may work locally but it won't work on another machine. – cdm Aug 02 '17 at 19:41
  • Are you unable to change the command arguments or pre-add jars to .gradle/lib on the other machine? – bdkosher Aug 02 '17 at 20:57
  • @bdkosher Yes - assuming it's running on Jenkins or another developer's machine... – cdm Aug 02 '17 at 21:02
  • Did you try this a second time? I've found that Groovy scripts with Grab download the file once, then cache the dependency so it goes faster the next time. (At least it seems to for me???) – RyanWilcox Aug 03 '17 at 02:18

1 Answers1

3

It's not the import that takes time, but @Grab annotation which comes from Grape - a Groovy dependency management system. Those 3 lines:

@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
@Grab('oauth.signpost:signpost-core:1.2.1.2')
@Grab('oauth.signpost:signpost-commonshttp4:1.2.1.2')

define your script dependencies. Those dependencies are 3rd party libraries provided as a JAR files. Some of them may even have their own dependencies which will be also downloaded to satisfy dependency you have defined (e.g. http-builder requires Apache's HTTP client and core lib).

Running this script takes some time (about 1 second on my laptop), because Groovy has to determine all dependencies and add them to the classpath to satisfy all imports. Keep in mind that your script uses a lot more dependencies than those 3 and all of them have to be resolved.

Using Grape is actually a compromise between using 3rd party libraries in the most easiest way and some overhead that is delegated to Groovy. Alternatively you could run your script with:

groovy -classpath ${GROOVY_CLASSPATH} Request.groovy

where ${GROOVY_CLASSPATH} contains paths to all JAR files you need to successfully run the script. And believe me - you will have to add at least 15 libraries instead of those 3 grapes. Then you will be able to remove all @Grab annotations (they are not needed in this case because you will satisfy groovy script with providing all libs in the classpath) and your script will execute in the blink of an eye - there will be no overhead caused by resolving and loading all dependencies.

Another alternative solution is to use Gradle to manage all dependencies and create so called "fat JAR" that contains all mandatory dependencies inside - in this case you will be able to run your program with java command and all imports will be in place without any dependencies resolving mechanism.

Final conclusion. Grape is a powerful Groovy's feature that has it's own limitations. It allows you to handle dependencies-hell pretty easily, but it comes with its own cost. I hope this answer will help you making a good choice.

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131