immich-app / immich

High performance self-hosted photo and video management solution.
https://immich.app
GNU Affero General Public License v3.0
52.66k stars 2.79k forks source link

Performance Issue on Raspberry Pi during Upload #14328

Closed deadash closed 1 day ago

deadash commented 1 day ago

The bug

When running Immich on resource-constrained devices like Raspberry Pi, concurrent file uploads and image processing tasks lead to high CPU usage, significantly impacting upload speeds. The system should prioritize file uploads by temporarily pausing image processing tasks until the upload is complete.

The OS that Immich Server is running on

Raspberry Pi OS (Debian based)

Version of Immich Server

v1.120.2

Version of Immich Mobile App

v1.21.0.build.184

Platform with the issue

Your docker-compose.yml content

from https://github.com/immich-app/immich/blob/main/docker/docker-compose.prod.yml

Your .env content

# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=./library
# The location where your database files are stored
DB_DATA_LOCATION=./postgres

# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC

# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release

# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=postgres

# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Reproduction steps

  1. Deploy Immich on Raspberry Pi
  2. Start uploading multiple images (e.g., 100+ photos)
  3. System simultaneously processes previously uploaded images (thumbnail generation, EXIF extraction, etc.)
  4. CPU usage spikes to nearly 100%
  5. Upload speed significantly decreases

Relevant log output

No response

Additional information

Add upload state control in file-upload.interceptor.ts:

export class FileUploadInterceptor implements NestInterceptor {
  private static isUploading = false;

  // Get upload status
  public static isFileUploading(): boolean {
    return FileUploadInterceptor.isUploading;
  }

  async intercept(context: ExecutionContext, next: CallHandler<any>): Promise<Observable<any>> {
    FileUploadInterceptor.isUploading = true;
    try {
      // Execute upload
      return await next.handle().toPromise();
    } finally {
      // Set status to false after 30 seconds delay when upload completes
      setTimeout(() => {
        FileUploadInterceptor.isUploading = false;
      }, 30000);
    }
  }
}

Then check this status in other image processing services:

if (FileUploadInterceptor.isFileUploading()) {
  // Queue the task to process after upload completes
  return;
}

This improvement would significantly enhance the user experience on low-performance devices by preventing resource contention between uploads and processing tasks. It ensures that uploads complete faster by temporarily deferring resource-intensive processing tasks. The implementation would:

  1. Prioritize file uploads over processing tasks
  2. Queue processing tasks during active uploads
  3. Resume processing after uploads complete (with a 30-second buffer)
  4. Better resource management for constrained devices