> For the complete documentation index, see [llms.txt](https://docs.joobq.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.joobq.io/guides/parallelism-and-concurrency.md).

# Parallelism & Concurrency

JoobQ provides robust parallelism and concurrency mechanisms to maximize the efficiency of job processing. Understanding and configuring parallelism and concurrency in JoobQ helps you make the most out of available resources, reducing job execution time and increasing system throughput. This section explains how parallelism and concurrency work in JoobQ and how to effectively manage them.

### Overview of Parallelism and Concurrency

**Parallelism** refers to executing multiple tasks simultaneously across multiple processors or cores, while **concurrency** refers to managing multiple tasks at the same time, even if they aren't necessarily executing simultaneously. JoobQ uses both approaches to improve job throughput by allowing multiple workers to process different jobs concurrently, taking advantage of multicore systems.

JoobQ provides these mechanisms through the use of **workers** and **queues**. Each queue can have multiple workers assigned, and each worker runs in its own fiber, enabling concurrent job execution.

### Configuring Parallelism with Workers

The key to leveraging parallelism in JoobQ lies in configuring the number of workers assigned to each queue. More workers mean more jobs can be processed in parallel, leading to increased throughput.

#### Assigning Workers to a Queue

When creating a queue in JoobQ, you can specify the number of workers that should process jobs from that queue.

```crystal
queue = JoobQ::Queue(ExampleJob).new("concurrent_queue", total_workers: 5)
```

* **`total_workers`**: Defines the number of worker threads that will concurrently fetch and execute jobs from the queue.

In the above example, 5 workers are created for the `concurrent_queue`, allowing 5 jobs to be processed concurrently.

### Worker Management

Each worker is responsible for fetching jobs from the queue, executing them, and handling retries or failures. Workers run in separate fibers, enabling efficient concurrency within the application.

#### Worker Lifecycle

* **Start Workers**: Workers are started when the queue is started by calling the `start` method.

  ```crystal
  queue.start
  ```

  This method will initialize all the workers and begin processing jobs concurrently.
* **Stop Workers**: Workers can be stopped gracefully by calling the `stop!` method, which signals all active workers to terminate.

  ```crystal
  queue.stop!
  ```

### Example Usage of Concurrency and Parallelism

Below is an example of configuring a queue with multiple workers to achieve concurrency:

```crystal
require "joobq"

# Define a job
struct ExampleJob
  include JoobQ::Job
  property x : Int32

  def initialize(@x : Int32)
  end

  def perform
    puts "Performing job with x = #{x}"
  end
end

# Configure the queue with 5 workers for concurrency
queue = JoobQ::Queue(ExampleJob).new("concurrent_queue", total_workers: 5)

# Add jobs to the queue
20.times do |i|
  queue.add(ExampleJob.new(x: i).to_json)
end

# Start the queue, enabling concurrent job processing
queue.start
```

In this example:

* **`total_workers: 5`** indicates that there are 5 workers processing jobs from the queue concurrently, which allows multiple jobs to be executed in parallel.
* **`queue.add`** adds 20 jobs to the queue, which will be distributed among the available workers for concurrent execution.

### Balancing Parallelism and Resource Usage

While increasing the number of workers can improve job throughput, it is important to balance parallelism with resource usage to avoid overwhelming the system.

#### Key Considerations

* **CPU and Memory**: More workers mean higher CPU and memory usage. Ensure your system has enough resources to handle the number of workers you configure.
* **Job Complexity**: Simple jobs may benefit from a higher number of workers, while complex, CPU-intensive jobs may require fewer workers to avoid overloading the system.
* **I/O Bound Jobs**: If jobs are I/O bound (e.g., making API calls or reading from a database), adding more workers can help improve throughput, as the workers can continue processing other jobs while waiting for I/O to complete.

### Monitoring Worker Performance

Monitoring worker activity is crucial for understanding how well your concurrency settings are working. JoobQ provides metrics that help you track worker performance, such as:

* **Active Workers**: Number of workers actively processing jobs at a given time.
* **Job Throughput**: Number of jobs completed per second by all workers.
* **Worker Utilization**: Indicates how effectively each worker is being utilized. High utilization suggests good resource usage, while low utilization may indicate too many idle workers.

You can retrieve these metrics via the JoobQ metrics API or by calling the `queue.info` method:

```crystal
queue_info = queue.info
puts queue_info.to_json
```

The output will include details about the number of active workers, job completion rates, and other relevant metrics.

### Best Practices for Parallelism and Concurrency

* **Start with a Conservative Number of Workers**: Begin with a modest number of workers and gradually increase until you find the optimal balance between throughput and resource consumption.
* **Monitor System Resources**: Use monitoring tools to keep an eye on CPU and memory usage to ensure that adding more workers does not degrade overall system performance.
* **Use Metrics to Tune Settings**: Leverage the metrics provided by JoobQ to understand worker activity and tune the number of workers accordingly.
* **Different Queues for Different Loads**: If your system processes different types of jobs (e.g., CPU-intensive vs. I/O-bound), consider creating separate queues with different concurrency settings tailored to the job types.

***

Parallelism and concurrency are crucial for maximizing the efficiency of job processing in JoobQ. By configuring the appropriate number of workers and understanding how to monitor and balance resource usage, you can ensure that your system processes jobs effectively, without overwhelming system resources.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.joobq.io/guides/parallelism-and-concurrency.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
