# HG changeset patch # User Sebastien Jodogne # Date 1606153782 -3600 # Node ID 5e76d5e8167af424a93bcfeb41904f8f6dca4d52 # Parent 6fa05252b085cbdb7dee4025173807c528f7e31c limit the amount of frames to be prefetched diff -r 6fa05252b085 -r 5e76d5e8167a Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp --- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Mon Nov 23 18:09:14 2020 +0100 +++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Mon Nov 23 18:49:42 2020 +0100 @@ -1227,7 +1227,7 @@ assert(converted.get() != NULL); GetViewport().RenderCurrentSceneFromCommand(*converted, sopInstanceUid_, frameNumber_, DisplayedFrameQuality_Low); - GetViewport().cache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG); + GetViewport().framesCache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG); if (isPrefetch_) { @@ -1320,7 +1320,7 @@ assert(converted.get() != NULL); viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); - viewport.cache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); + viewport.framesCache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); } }; @@ -1356,7 +1356,7 @@ boost::shared_ptr viewport_; boost::shared_ptr loader_; OrthancStone::DicomSource source_; - boost::shared_ptr cache_; + boost::shared_ptr framesCache_; std::unique_ptr frames_; std::unique_ptr cursor_; float windowingCenter_; @@ -1390,7 +1390,7 @@ unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); { - FramesCache::Accessor accessor(*cache_, sopInstanceUid, frameNumber); + FramesCache::Accessor accessor(*framesCache_, sopInstanceUid, frameNumber); if (!accessor.IsValid() || (isFullQuality && accessor.GetQuality() == 0)) { @@ -1453,21 +1453,31 @@ } - void SetupPrefetchAfterRendering(DisplayedFrameQuality quality) + /** + * NB: "frame" is only used to estimate the memory size to store 1 + * frame, in order to avoid prefetching too much data. + **/ + void SetupPrefetchAfterRendering(const Orthanc::ImageAccessor& frame, + DisplayedFrameQuality quality) { + const size_t frameSize = frame.GetPitch() * frame.GetHeight(); const size_t cursorIndex = cursor_->GetCurrentIndex(); // Prepare prefetching prefetchQueue_.clear(); - if (1) // TODO - DISABLE PREFETCHING + size_t prefetchedSize = 0; + + if (1) // DISABLE PREFETCHING { - for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16; i++) + for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16 && + prefetchedSize <= framesCache_->GetMaximumSize() / 2; i++) { size_t a = cursor_->GetPrefetchIndex(i); if (a != cursorIndex) { prefetchQueue_.push_back(PrefetchItem(a, i < 2)); + prefetchedSize += frameSize; } } } @@ -1593,19 +1603,19 @@ if (quality == DisplayedFrameQuality_Low) { - FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber); + FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); if (accessor.IsValid() && accessor.GetQuality() == QUALITY_FULL) { // A high-res image was downloaded in between: Use this cached image instead of the low-res RenderCurrentScene(accessor.GetImage(), instance, plane); - SetupPrefetchAfterRendering(DisplayedFrameQuality_High); + SetupPrefetchAfterRendering(frame, DisplayedFrameQuality_High); } else { // This frame is only available in low-res: Download the full DICOM RenderCurrentScene(frame, instance, plane); - SetupPrefetchAfterRendering(quality); + SetupPrefetchAfterRendering(frame, quality); /** * The command "SetupPrefetchAfterRendering()" must be @@ -1621,7 +1631,7 @@ else { assert(quality == DisplayedFrameQuality_High); - SetupPrefetchAfterRendering(quality); + SetupPrefetchAfterRendering(frame, quality); RenderCurrentScene(frame, instance, plane); } } @@ -1744,7 +1754,7 @@ bool softwareRendering) : context_(context), source_(source), - cache_(cache), + framesCache_(cache), fitNextContent_(true), isCtrlDown_(false), flipX_(false), @@ -1752,7 +1762,7 @@ hasFocusOnInstance_(false), focusFrameNumber_(0) { - if (!cache_) + if (!framesCache_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); } @@ -1968,7 +1978,7 @@ const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); - FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber); + FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); if (accessor.IsValid()) { RenderCurrentScene(accessor.GetImage(), instance, frames_->GetFrameGeometry(cursorIndex)); @@ -1986,7 +1996,7 @@ quality = DisplayedFrameQuality_High; } - SetupPrefetchAfterRendering(quality); + SetupPrefetchAfterRendering(accessor.GetImage(), quality); } else { @@ -2467,7 +2477,7 @@ static OrthancStone::DicomSource source_; -static boost::shared_ptr cache_; +static boost::shared_ptr framesCache_; static boost::shared_ptr context_; static std::string stringBuffer_; static bool softwareRendering_ = false; @@ -2517,7 +2527,7 @@ if (found == allViewports_.end()) { boost::shared_ptr viewport( - ViewerViewport::Create(*context_, source_, canvas, cache_, softwareRendering_)); + ViewerViewport::Create(*context_, source_, canvas, framesCache_, softwareRendering_)); viewport->SetMouseButtonActions(leftButtonAction_, middleButtonAction_, rightButtonAction_); viewport->AcquireObserver(new WebAssemblyObserver); viewport->SetAnnotations(annotations_); @@ -2543,7 +2553,7 @@ context_.reset(new OrthancStone::WebAssemblyLoadersContext(1, 4, 1)); context_->SetDicomCacheSize(128 * 1024 * 1024); // 128MB - cache_.reset(new FramesCache); + framesCache_.reset(new FramesCache); annotations_.reset(new OrthancStone::OsiriX::CollectionOfAnnotations); DISPATCH_JAVASCRIPT_EVENT("StoneInitialized");