nunodonato's avatar

Best way to handle millions of calculations

Hi folks

I'm importing a file with many rows of data, on which I need to do some individual calculations and produce a result for each row. Because it takes quite a while, I'm doing this on a job. However, as the file grows bigger and bigger (millions of rows), the job starts taking way too long, and the whole process becomes too slow (eventually timing out). Increasing the timeout is not a real solution because the job will still take hours to complete.

I'm thinking of parallelizing this, making each individual row its own job so that I could benefit from several queue workers at once.

However, I would be dispatching the jobs as I read through the file. I've never dispatched millions of jobs in such a short time. Do I need to prepare for this more than just the basic queue config? Are there limits (on Redis?) that I'm not aware of?

Any other tips or advice from similar experiences? thanks in advance.

0 likes
2 replies
LaryAI's avatar
Level 58

Handling millions of calculations efficiently requires a combination of strategies to ensure that your system can process the data in a timely manner without overwhelming your resources. Here are some steps and considerations to help you manage this:

  1. Batch Processing: Instead of dispatching a job for each row, consider processing the data in batches. This reduces the overhead of job dispatching and can significantly improve performance. For example, you could process 1000 rows per job.

  2. Queue Configuration: Ensure your queue system is properly configured to handle a large number of jobs. If you're using Redis, make sure it has enough memory allocated and is properly tuned for high throughput.

  3. Parallel Processing: Utilize multiple queue workers to process jobs in parallel. This can be achieved by scaling your workers horizontally. For instance, if you have 10 workers and each processes a batch of 1000 rows, you can process 10,000 rows concurrently.

  4. Chunking the File: If the file is too large to read into memory at once, read and process it in chunks. This can be done using PHP's fgetcsv or similar functions to read a portion of the file, process it, and then move to the next portion.

  5. Database Optimization: If your calculations involve database operations, ensure your database is optimized. This includes indexing, query optimization, and possibly using a read-replica for read-heavy operations.

  6. Monitoring and Logging: Implement monitoring to track the performance of your jobs and log any errors. This will help you identify bottlenecks and optimize further.

  7. Consider Using a Distributed System: For extremely large datasets, consider using a distributed processing system like Apache Kafka for message brokering and Apache Spark for processing.

Here's a basic example of how you might implement batch processing in Laravel:

use Illuminate\Support\Facades\Bus;
use App\Jobs\ProcessDataBatch;

function processLargeFile($filePath) {
    $batchSize = 1000;
    $handle = fopen($filePath, 'r');
    $batch = [];

    while (($row = fgetcsv($handle)) !== false) {
        $batch[] = $row;

        if (count($batch) === $batchSize) {
            Bus::batch([
                new ProcessDataBatch($batch)
            ])->dispatch();

            $batch = []; // Reset batch
        }
    }

    // Dispatch any remaining rows
    if (!empty($batch)) {
        Bus::batch([
            new ProcessDataBatch($batch)
        ])->dispatch();
    }

    fclose($handle);
}

In this example, ProcessDataBatch is a job that processes a batch of rows. Adjust the batch size and number of workers based on your system's capacity and performance requirements.

1 like
JussiMannisto's avatar

Take a look at Laravel's new concurrency features.

Every job has some overhead due to data serialization/deserialization and queue driver operations. You should look at other options before trying to dispatch millions of jobs in a short period of time. I'd create jobs with batches of rows, e.g. max 1000 rows per job.

1 like

Please or to participate in this conversation.