Mercurial > hg > orthanc
changeset 5954:4f726a09798e
MaximumConcurrentDcmtkTranscoders
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Wed, 15 Jan 2025 09:28:27 +0100 |
parents | 684d49e47b5e |
children | 34ba0344f240 |
files | NEWS OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp OrthancServer/Resources/Configuration.json OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h OrthancServer/Sources/main.cpp OrthancServer/UnitTestsSources/ServerIndexTests.cpp OrthancServer/UnitTestsSources/ServerJobsTests.cpp |
diffstat | 10 files changed, 51 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Fri Jan 10 18:27:27 2025 +0100 +++ b/NEWS Wed Jan 15 09:28:27 2025 +0100 @@ -1,6 +1,15 @@ Pending changes in the mainline =============================== +General +------- + +* New configuration options: + - "MaximumConcurrentDcmtkTranscoders" to reduce CPU and memory usage by limiting + the number of concurrent DCMTK transcoders that are simultaneously running + at any given time. + + Maintenance -----------
--- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -50,8 +50,9 @@ namespace Orthanc { - DcmtkTranscoder::DcmtkTranscoder() : - lossyQuality_(90) + DcmtkTranscoder::DcmtkTranscoder(unsigned int maxConcurrentExecutions) : + lossyQuality_(90), + maxConcurrentExecutionsSemaphore_(maxConcurrentExecutions) { } @@ -317,6 +318,8 @@ const std::set<DicomTransferSyntax>& allowedSyntaxes, bool allowNewSopInstanceUid) { + Semaphore::Locker lock(maxConcurrentExecutionsSemaphore_); // limit the number of concurrent executions + target.Clear(); DicomTransferSyntax sourceSyntax;
--- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Wed Jan 15 09:28:27 2025 +0100 @@ -33,6 +33,8 @@ #endif #include "IDicomTranscoder.h" +#include "../MultiThreading/Semaphore.h" + namespace Orthanc { @@ -40,7 +42,8 @@ { private: unsigned int lossyQuality_; - + Semaphore maxConcurrentExecutionsSemaphore_; + bool InplaceTranscode(DicomTransferSyntax& selectedSyntax /* out */, std::string& failureReason /* out */, DcmFileFormat& dicom, @@ -48,7 +51,7 @@ bool allowNewSopInstanceUid); public: - DcmtkTranscoder(); + DcmtkTranscoder(unsigned int maxConcurrentExecutions); void SetLossyQuality(unsigned int quality);
--- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -3561,7 +3561,7 @@ scu.SetCommonClassesProposed(false); scu.SetRetiredBigEndianProposed(true); - DcmtkTranscoder transcoder; + DcmtkTranscoder transcoder(1); for (int j = 0; j < 2; j++) { @@ -3618,7 +3618,7 @@ DicomTransferSyntax sourceSyntax; ASSERT_TRUE(FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, *toto)); - DcmtkTranscoder transcoder; + DcmtkTranscoder transcoder(1); for (int i = 0; i <= DicomTransferSyntax_XML; i++) {
--- a/OrthancServer/Resources/Configuration.json Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/Resources/Configuration.json Wed Jan 15 09:28:27 2025 +0100 @@ -1025,7 +1025,12 @@ // In this mode, many Orthanc features that requires a write access to the // Index DB or the disk storage won't be available at all. // (new in Orthanc 1.12.5) - "ReadOnly" : false + "ReadOnly" : false, + // Maximum number of DCMTK transcoders that are simultaneously running + // at any given time. A value of "0" indicates to use all the + // available CPU logical cores. Prior to Orthanc 1.12.6, there were not limit. + // (new in Orthanc 1.12.6) + "MaximumConcurrentDcmtkTranscoders" : 0 }
--- a/OrthancServer/Sources/ServerContext.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -356,7 +356,8 @@ IStorageArea& area, bool unitTesting, size_t maxCompletedJobs, - bool readOnly) : + bool readOnly, + unsigned int maxConcurrentDcmtkTranscoder) : index_(*this, database, (unitTesting ? 20 : 500), readOnly), area_(area), compressionEnabled_(false), @@ -378,7 +379,7 @@ isExecuteLuaEnabled_(false), isRestApiWriteToFileSystemEnabled_(false), overwriteInstances_(false), - dcmtkTranscoder_(new DcmtkTranscoder), + dcmtkTranscoder_(new DcmtkTranscoder(maxConcurrentDcmtkTranscoder)), isIngestTranscoding_(false), ingestTranscodingOfUncompressed_(true), ingestTranscodingOfCompressed_(true),
--- a/OrthancServer/Sources/ServerContext.h Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/Sources/ServerContext.h Wed Jan 15 09:28:27 2025 +0100 @@ -306,7 +306,8 @@ IStorageArea& area, bool unitTesting, size_t maxCompletedJobs, - bool readOnly); + bool readOnly, + unsigned int maxConcurrentDcmtkTranscoder); ~ServerContext();
--- a/OrthancServer/Sources/main.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/Sources/main.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -64,6 +64,8 @@ static const char* const KEY_DICOM_TLS_ACCEPTED_CIPHERS = "DicomTlsCiphersAccepted"; static const char* const KEY_MAXIMUM_PDU_LENGTH = "MaximumPduLength"; static const char* const KEY_READ_ONLY = "ReadOnly"; +static const char* const KEY_MAXIMUM_CONCURRENT_DCMTK_TRANSCODERS = "MaximumConcurrentDcmtkTranscoders"; + class OrthancStoreRequestHandler : public IStoreRequestHandler { @@ -1519,7 +1521,8 @@ { size_t maxCompletedJobs; bool readOnly; - + unsigned int maxDcmtkConcurrentTranscoders; + { OrthancConfiguration::ReaderLock lock; @@ -1555,6 +1558,13 @@ // New option in Orthanc 1.12.5 readOnly = lock.GetConfiguration().GetBooleanParameter(KEY_READ_ONLY, false); + // New option in Orthanc 1.12.6 + maxDcmtkConcurrentTranscoders = lock.GetConfiguration().GetUnsignedIntegerParameter(KEY_MAXIMUM_CONCURRENT_DCMTK_TRANSCODERS, 0); + if (maxDcmtkConcurrentTranscoders == 0) + { + maxDcmtkConcurrentTranscoders = static_cast<unsigned int>(boost::thread::hardware_concurrency()); + } + // Configuration of DICOM TLS for Orthanc SCU (since Orthanc 1.9.0) DicomAssociationParameters::SetDefaultOwnCertificatePath( lock.GetConfiguration().GetStringParameter(KEY_DICOM_TLS_PRIVATE_KEY, ""), @@ -1569,7 +1579,7 @@ lock.GetConfiguration().GetBooleanParameter(KEY_DICOM_TLS_REMOTE_CERTIFICATE_REQUIRED, true)); } - ServerContext context(database, storageArea, false /* not running unit tests */, maxCompletedJobs, readOnly); + ServerContext context(database, storageArea, false /* not running unit tests */, maxCompletedJobs, readOnly, maxDcmtkConcurrentTranscoders); { OrthancConfiguration::ReaderLock lock; @@ -1974,7 +1984,7 @@ SQLiteDatabaseWrapper inMemoryDatabase; inMemoryDatabase.Open(); MemoryStorageArea inMemoryStorage; - ServerContext context(inMemoryDatabase, inMemoryStorage, true /* unit testing */, 0 /* max completed jobs */, false /* readonly */); + ServerContext context(inMemoryDatabase, inMemoryStorage, true /* unit testing */, 0 /* max completed jobs */, false /* readonly */, 1 /* DCMTK concurrent transcoders */); OrthancRestApi restApi(context, false /* no Orthanc Explorer */); restApi.GenerateOpenApiDocumentation(openapi); context.Stop(); @@ -2025,7 +2035,7 @@ SQLiteDatabaseWrapper inMemoryDatabase; inMemoryDatabase.Open(); MemoryStorageArea inMemoryStorage; - ServerContext context(inMemoryDatabase, inMemoryStorage, true /* unit testing */, 0 /* max completed jobs */, false /* readonly */); + ServerContext context(inMemoryDatabase, inMemoryStorage, true /* unit testing */, 0 /* max completed jobs */, false /* readonly */, 1 /* DCMTK concurrent transcoders */); OrthancRestApi restApi(context, false /* no Orthanc Explorer */); restApi.GenerateReStructuredTextCheatSheet(cheatsheet, "https://orthanc.uclouvain.be/api/index.html"); context.Stop();
--- a/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -621,7 +621,7 @@ FilesystemStorage storage(path); SQLiteDatabaseWrapper db; // The SQLite DB is in memory db.Open(); - ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */); + ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */, 1 /* DCMTK concurrent transcoders */); context.SetupJobsEngine(true, false); ServerIndex& index = context.GetIndex(); @@ -703,7 +703,7 @@ FilesystemStorage storage(path); SQLiteDatabaseWrapper db; // The SQLite DB is in memory db.Open(); - ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */); + ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */, 1 /* DCMTK concurrent transcoders */); context.SetupJobsEngine(true, false); ServerIndex& index = context.GetIndex(); @@ -820,7 +820,7 @@ MemoryStorageArea storage; SQLiteDatabaseWrapper db; // The SQLite DB is in memory db.Open(); - ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */); + ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */, 1 /* DCMTK concurrent transcoders */); context.SetupJobsEngine(true, false); context.SetCompressionEnabled(true); @@ -985,7 +985,7 @@ MemoryStorageArea storage; SQLiteDatabaseWrapper db; // The SQLite DB is in memory db.Open(); - ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */); + ServerContext context(db, storage, true /* running unit tests */, 10, false /* readonly */, 1 /* DCMTK concurrent transcoders */); context.SetupJobsEngine(true, false); context.SetCompressionEnabled(compression);
--- a/OrthancServer/UnitTestsSources/ServerJobsTests.cpp Fri Jan 10 18:27:27 2025 +0100 +++ b/OrthancServer/UnitTestsSources/ServerJobsTests.cpp Wed Jan 15 09:28:27 2025 +0100 @@ -536,7 +536,7 @@ OrthancJobsSerialization() { db_.Open(); - context_.reset(new ServerContext(db_, storage_, true /* running unit tests */, 10, false /* readonly */)); + context_.reset(new ServerContext(db_, storage_, true /* running unit tests */, 10, false /* readonly */, 1 /* DCMTK concurrent transcoders */)); context_->SetupJobsEngine(true, false); }