Giter Site home page Giter Site logo

Comments (9)

kraih avatar kraih commented on May 28, 2024

We already have a benchmark script that can be adapted for this. Filling the queue with a million jobs is pretty slow though.

from minion.

kraih avatar kraih commented on May 28, 2024

I've brought back the GIN index after benchmarking a bit. There is a huge performance gain for job_info and maybe a tiny one for repair. dcc95da

from minion.

kraih avatar kraih commented on May 28, 2024

It appears our main bottleneck now is one query in repair.

  # Jobs with missing parents (can't be retried)
  $db->query(
    "update minion_jobs as j
     set finished = now(), result = to_json('Parent went away'::text),
       state = 'failed'
     where parents <> '{}' and cardinality(parents) <> (
       select count(*) from minion_jobs where id = any (j.parents)
     ) and state = 'inactive'"
  );

nytprof

from minion.

kraih avatar kraih commented on May 28, 2024

This is what the query plan looks like currently.

                                                                              QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Update on minion_jobs j  (cost=0.29..1987548.66 rows=41838 width=187) (actual time=267.343..267.343 rows=0 loops=1)
   ->  Index Scan using minion_jobs_state_priority_id_idx on minion_jobs j  (cost=0.29..1987548.66 rows=41838 width=187) (actual time=267.341..267.341 rows=0 loops=1)
         Index Cond: (state = 'inactive'::minion_state)
         Filter: ((parents <> '{}'::bigint[]) AND (cardinality(parents) <> (SubPlan 1)))
         Rows Removed by Filter: 42005
         SubPlan 1
           ->  Aggregate  (cost=47.10..47.11 rows=1 width=8) (actual time=0.006..0.006 rows=1 loops=42005)
                 ->  Index Only Scan using minion_jobs_pkey on minion_jobs  (cost=0.29..47.08 rows=10 width=0) (actual time=0.001..0.005 rows=5 loops=42005)
                       Index Cond: (id = ANY (j.parents))
                       Heap Fetches: 210025
 Planning time: 0.318 ms
 Execution time: 267.425 ms
(12 rows)

from minion.

kraih avatar kraih commented on May 28, 2024

Btw. i do all profiling with our benchmark script, so my results can be reproduced.

from minion.

kraih avatar kraih commented on May 28, 2024

Perhaps we could just get rid of the UPDATE query in repair, and modify our dequeue query to also accept jobs where one or more parents are missing.

  return $self->pg->db->query(
    "update minion_jobs
     set started = now(), state = 'active', worker = ?
     where id = (
       select id from minion_jobs as j
       where delayed <= now() and (parents = '{}' or cardinality(parents) = (
         select count(*) from minion_jobs
         where id = any(j.parents) and state = 'finished'
       )) and queue = any(?) and state = 'inactive' and task = any(?)
       order by priority desc, id
       limit 1
       for update skip locked
     )
     returning id, args, retries, task", $id,
    $options->{queues} || ['default'], [keys %{$self->minion->tasks}]
  )->expand->hash;

That would mean a dependency is considered resolved if the parent job is missing or in the state finished.

(parents = '{}' or cardinality(parents) = (
  select count(*) from minion_jobs
  where id = any(j.parents) and state = 'finished'
))

Would be interesting to see if this subquery could be modified to do that efficiently.

from minion.

kraih avatar kraih commented on May 28, 2024

Ok, repair is now two orders of magnitude faster. 😄 5d069b1

from minion.

kraih avatar kraih commented on May 28, 2024

I've been trying to replicate my job_info results from yesterday but am failing. The query still looks much more efficient in EXPLAIN ANALYZE, but with our benchmark script the old query is actually faster...

test=# explain analyze select id, args, attempts, array(select id from minion_jobs where j.id = any(parents)) as children, extract(epoch from created) as created, extract(epoch from delayed) as delayed, extract(epoch from finished) as finished, parents, priority, queue, result, extract(epoch from retried) as retried, retries, extract(epoch from started) as started, state, task, worker from minion_jobs as j where id = 10000;
                                                             QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using minion_jobs_pkey on minion_jobs j  (cost=0.29..563.43 rows=1 width=190) (actual time=4.070..4.073 rows=1 loops=1)
   Index Cond: (id = 10000)
   SubPlan 1
     ->  Seq Scan on minion_jobs  (cost=0.00..555.11 rows=489 width=8) (actual time=4.025..4.025 rows=0 loops=1)
           Filter: (j.id = ANY (parents))
           Rows Removed by Filter: 10005
 Planning time: 0.532 ms
 Execution time: 4.121 ms
(8 rows)

test=# explain analyze select id, args, attempts, array(select id from minion_jobs where parents @> ARRAY[j.id]) as children, extract(epoch from created) as created, extract(epoch from delayed) as delayed, extract(epoch from finished) as finished, parents, priority, queue, result, extract(epoch from retried) as retried, retries, extract(epoch from started) as started, state, task, worker from minion_jobs as j where id = 10000;
                                                                QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using minion_jobs_pkey on minion_jobs j  (cost=0.29..168.12 rows=1 width=190) (actual time=0.099..0.101 rows=1 loops=1)
   Index Cond: (id = 10000)
   SubPlan 1
     ->  Bitmap Heap Scan on minion_jobs  (cost=24.39..159.80 rows=50 width=8) (actual time=0.057..0.057 rows=0 loops=1)
           Recheck Cond: (parents @> ARRAY[j.id])
           ->  Bitmap Index Scan on minion_jobs_parents_idx1  (cost=0.00..24.38 rows=50 width=0) (actual time=0.039..0.039 rows=0 loops=1)
                 Index Cond: (parents @> ARRAY[j.id])
 Planning time: 0.284 ms
 Execution time: 0.178 ms
(9 rows)

from minion.

kraih avatar kraih commented on May 28, 2024

Think we are in a pretty good spot now overall. Been running benchmarks with a million jobs in the queue and everything feels snappy. Closest to feeling like a bottleneck now would be stats and maybe enqueue, but not enough to make either a priority.

from minion.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.