Project

General

Profile

Actions

Bug #9552

closed

[CWL] arvados-cwl-runner runs too slowly when reusing jobs

Added by Sarah Guthrie over 8 years ago. Updated about 8 years ago.

Status:
Resolved
Priority:
Normal
Assigned To:
Radhika Chippada
Category:
Performance
Target version:
Story points:
0.5

Description

Running a completed UNC pipeline via arvados-cwl-runner --local --enable-reuse takes 1 hour 24 minutes: https://workbench.qr1hi.arvadosapi.com/pipeline_instances/qr1hi-d1hrv-dwpq8wwvf89s6cu
  • First step (merge-fastqs): 17m8s (output size: 2 files totalling 15.1 GiB)
  • Second step (star): 1h7m6s (output size: 6 files totalling 58.6 GiB)
  • Third step (salmon): 2s (output size: 3 files totalling 4.7 MiB)

Subtasks 4 (0 open4 closed)

Task #9553: Review branch 9552-compute-checksum-flagResolvedRadhika Chippada07/06/2016Actions
Task #9735: Review 9552-compute-checksum-final-outputResolved07/06/2016Actions
Task #9734: Compute checksum on final outputResolvedPeter Amstutz07/06/2016Actions
Task #9610: Add compute_checksum flag to cwltool and submit a PRResolvedRadhika Chippada07/15/2016Actions
Actions #1

Updated by Brett Smith over 8 years ago

  • Target version set to 2016-07-20 sprint
Actions #2

Updated by Brett Smith over 8 years ago

  • Story points set to 1.0

This story is timeboxed for this sprint at 2 days. Spend up to that much time diagnosing and fixing the bug. At that time, let's reassess.

Actions #3

Updated by Tom Clegg over 8 years ago

  • Category set to Performance
  • Assigned To set to Tom Clegg
Actions #4

Updated by Radhika Chippada over 8 years ago

  • Assigned To changed from Tom Clegg to Radhika Chippada
Actions #5

Updated by Sarah Guthrie over 8 years ago

The CWL which exhibited this behavior can be found in the git repository on qr1hi: sguthrie/unc under the "cwl" directory.

The command, run in unc/cwl in an environment with ARVADOS_API_TOKEN and ARVADOS_API_HOST set and arvados-cwl-runner installed, is below:

arvados-cwl-runner --local --enable-reuse merge-star-salmon.cwl basic_test.json

Let me know if you need anything else to reproduce the bug

Actions #6

Updated by Radhika Chippada over 8 years ago

  • Status changed from New to In Progress

The time being spent is all happening in our end.

sdk/cwl/arvados_cwl/arvjob.py -> ArvadosJob.done method is parsing through each line of the log to determine the tmpdir, outdir, keepdir using tmpdirre, outdirre, keepre resp, which is taking all the extra time after “finding” the job to be reused. This information is then passed to done.py -> done method, which is using this to set builder.outdir and keepdir.

    self.builder.outdir = outdir
    self.builder.pathmapper.keepdir = keepdir
    return self.collect_outputs("keep:" + record["output"])

For the merge-fastqs job with log 263kb size, it took 11 mins to process the log lines.

2016-07-11 13:16:52 arvados.cwl-runner[33584] INFO: START
2016-07-11 13:16:55 arvados.cwl-runner[33584] INFO: GOT LOG = [u'qr1hi-8i9sb-a4p07cjcfg3906t.log.txt']
2016-07-11 13:27:11 arvados.cwl-runner[33584] INFO: DONE GETTING OUTPUTS

This seems like the most inefficient way of handling the need to set outdir and keepdir. Should this information be stored as metadata on the job record (using properties) by crunch itself? And on older jobs where this information may not be available, set this on first “reuse” to save time in all future reuses?

Actions #7

Updated by Tom Clegg over 8 years ago

Parsing 269KB of log entries is inefficient, but not inefficient enough to explain 11 minutes. Is there something wrong with the regexps? With the Collection class?

Actions #8

Updated by Radhika Chippada over 8 years ago

I reran the test with the regexp parsing lines commented out completely, thus leaving only the log line reading from Collection in place. This again took 10m to go though the log lines (but doing nothing with each of the lines) in the log Collection. Thus, it appears that the issue is with reading the lines from the log Collection.

2016-07-11 15:58:01 arvados.cwl-runner[58009] INFO: GOT LOG = [u'qr1hi-8i9sb-a4p07cjcfg3906t.log.txt']
2016-07-11 16:08:40 arvados.cwl-runner[58009] INFO: DONE GETTING OUTPUTS
Actions #9

Updated by Tom Clegg over 8 years ago

Radhika Chippada wrote:

I reran the test with the regexp parsing lines commented out completely, thus leaving only the log line reading from Collection in place. This again took 10m to go though the log lines (but doing nothing with each of the lines) in the log Collection. Thus, it appears that the issue is with reading the lines from the log Collection.

That narrows it down. Have you been able to reproduce it outside CWL?

This test script runs in less than one second on shell.qr1hi, using python-arvados-python-client 0.1.20160517202250-2:

import arvados
c=arvados.collection.Collection("2a3d13d2aac3242ac0b92a91b6875c58+87")
f=c.open("qr1hi-8i9sb-a4p07cjcfg3906t.log.txt")
for x in f:
    print x,

Perhaps something breaks the Python SDK's read cache in this context, and every iteration of "for l in log" re-fetches the entire file from the network? That would increase network latency by 1640×, which is the order of magnitude of the slowdown we're seeing.

FWIW I also downloaded the log from afar (browser via keep-web) and although I didn't time it, it was somewhere around 1s, certainly nowhere near 10m.

Actions #10

Updated by Radhika Chippada over 8 years ago

Sorry for the misinformation, but the issue is neither with the regexp parsing nor with the Collection class.

It is taking those 10+ minutes in collect_outputs call in done.py -> done method

    return self.collect_outputs("keep:" + record["output"])

It appears that this is from the cwl tool library?

Actions #11

Updated by Peter Amstutz over 8 years ago

cwltool/draft2tool.py L412:

                        with builder.fs_access.open(files["location"], "rb") as f:
                            contents = f.read(CONTENT_LIMIT)
                            if binding.get("loadContents"):
                                files["contents"] = contents
                            filesize = 0
                            while contents != "":
                                checksum.update(contents)
                                filesize += len(contents)
                                contents = f.read(1024*1024)

Add a flag to skip the loop while contents != "": the make a pull requests against the cwltool repository.

Actions #12

Updated by Radhika Chippada over 8 years ago

Actions #13

Updated by Radhika Chippada over 8 years ago

PR 127 had been merged into cwltool master.

Actions #14

Updated by Radhika Chippada over 8 years ago

  • Target version changed from 2016-07-20 sprint to 2016-08-03 sprint
  • Story points changed from 1.0 to 0.5
Actions #15

Updated by Radhika Chippada over 8 years ago

ad546911

  • Updated cwltool version we are using and now we have compete_checksum flag available
Actions #16

Updated by Tom Clegg over 8 years ago

ad54691 LGTM

Actions #17

Updated by Radhika Chippada over 8 years ago

  • Status changed from In Progress to Resolved
  • % Done changed from 50 to 100

Applied in changeset arvados|commit:4c98448b0966aefbf23b92f3da3a9278d2b73cab.

Actions #18

Updated by Radhika Chippada over 8 years ago

  • Status changed from Resolved to In Progress

Reopening this because in our jenkins environment we run the conformance tests and these fail without checksum computing.

Actions #19

Updated by Radhika Chippada over 8 years ago

Added compute-checksum flag to arvados-cwl-runn at cfa7968

Actions #20

Updated by Tom Clegg over 8 years ago

(More background)

I understand the checksum is supposed to be optional, but the conformance test suite doesn't know this yet.

Meanwhile, a command line flag plus a wrapper script should make it possible to pass conformance tests.

#!/bin/sh
exec arvados-cwl-runner --compute-checksum "$@" 

Does cfa7968 work? It looks like this command line flag won't make a difference, because arvExecutor() says kwargs["compute_checksum"]=False. And arvExecutor already gets all the command line flags. So, instead of adding a new argument to __init__() and a new instance variable, can we just change that line in arvExecutor to say kwargs["compute_checksum"]=kwargs.get("compute_checksum") ...?

Actions #21

Updated by Radhika Chippada over 8 years ago

Removed the instance variable.

Actions #22

Updated by Tom Clegg over 8 years ago

LGTM @ a115812

Actions #23

Updated by Tom Clegg over 8 years ago

The command line flag doesn't seem to be effective...

Test [6/73] Test failed: /usr/bin/cwl-runner --outdir=/tmp/tmpJro1gw --quiet v1.0/template-tool.cwl v1.0/cat-job.json Test CreateFileRequirement ExpressionEngineRequirement.engineConfig feature expected output object { "foo": { "checksum": "sha1$63da67422622fbf9251a046d7a34b7ea0fd4fead", "class": "File", "location": "foo.txt", "size": 22 } } got { "foo": { "basename": "foo.txt", "class": "File", "location": "keep:b3e162ad900be8b7c15ab5552e7c1c1c+112/foo.txt", "size": 22 } } Compare failure expected { "checksum": "sha1$63da67422622fbf9251a046d7a34b7ea0fd4fead", "class": "File", "size": 22 } got { "class": "File", "size": 22 }
Actions #24

Updated by Tom Clegg over 8 years ago

I think what we're missing is a mechanism to pass the compute_checksum flag to the Arvados job that runs the tool. The only case where we propagate kwargs["compute_checksum"] here is the one where we execute a CommandLineTool locally. The conformance test is using the Crunch1 work API, though, so it hits the RunnerJob line:

            if self.work_api == "containers":
                if tool.tool["class"] == "CommandLineTool":
                    runnerjob = tool.job(job_order,
                                         self.output_callback,
                                         **kwargs).next()
                else:
                    runnerjob = RunnerContainer(self, tool, job_order, kwargs.get("enable_reuse"))
            else:
                runnerjob = RunnerJob(self, tool, job_order, kwargs.get("enable_reuse"))

https://github.com/curoverse/arvados/blob/master/sdk/cwl/arvados_cwl/__init__.py#L151

Actions #25

Updated by Radhika Chippada over 8 years ago

Tom, thanks for the hint.

I used crunch2 to run the tests, and most tests passed.

 exec arvados-cwl-runner --compute-checksum --api containers "$@" 

The following tests failed and the rest (including, test 70) passed:

Test [36/73]   v1.0/env-job.json
Test [37/73]   v1.0/env-job.json
Test [39/73]   v1.0/revsort-job.json
Test [45/73]   v1.0/schemadef-job.json
Test [64/73]   v1.0/conflict-job.json

Would it be possible to run the tests using crunch2 in c97qk?

If this env is not ready for crunch2, would it be possible to (1) disable this jenkins job until that time, (2) run just the first 5 or so of the conformance tests (which can only ensure that the environment is setup properly)?

If none of these options are acceptable, please let me know what updates need to be made to RunnerJob. (preferably make this update in a separate ticket ...). We probably also need to create another ticket to see why those 5 tests are failing in crunch2 and fix any issues.

Actions #26

Updated by Radhika Chippada over 8 years ago

  • Target version changed from 2016-08-03 sprint to 2016-08-17 sprint
Actions #27

Updated by Peter Amstutz over 8 years ago

Here's a thought, instead of passing through the --compute-checksum flag to the runner job, there's no reason that the client can't check if the checksums are present, and if not, compute the checksum itself.

Actions #28

Updated by Peter Amstutz over 8 years ago

Implemented branch 9552-compute-checksum-final-output which fills in the checksums before returning the final output object which --compute-checksum is provided.

Actions #29

Updated by Tom Clegg over 8 years ago

9552-compute-checksum-final-output LGTM, thanks!

Actions #30

Updated by Peter Amstutz about 8 years ago

  • Status changed from In Progress to Resolved
Actions

Also available in: Atom PDF