syncfusion / flutter-widgets

Syncfusion Flutter widgets libraries include high quality UI widgets and file-format packages to help you create rich, high-quality applications for iOS, Android, and web from a single code base.
1.46k stars 680 forks source link

[pdf_viewer] [pdf] Exhausted heap space while scrolling a large pdf file #1289

Closed soeren-schmaljohann-2denker closed 3 months ago

soeren-schmaljohann-2denker commented 11 months ago

I'm loading a big pdf file (89.2 MB) via SfPdfViewer.file. Then after scrolling for a bit I get this error:

Exhausted heap space, trying to allocate 8323104 bytes.
[VERBOSE-2:dart_isolate.cc(1097)] Unhandled exception:
Out of Memory
#0      new _GrowableList (dart:core-patch/growable_array.dart:97:16)
#1      new _GrowableList.filled (dart:core-patch/growable_array.dart:121:20)
#2      PdfReader.readBytes
pdf_reader.dart:97
#3      PdfReader.readData
pdf_reader.dart:172
#4      PdfLexer._read
pdf_lexer.dart:367
#5      PdfLexer.readBytes
pdf_lexer.dart:383
#6      PdfParser._readStream
pdf_parser.dart:682
#7      PdfParser._dictionary
pdf_parser.dart:624
#8      PdfParser.simple
pdf_parser.dart:259
#9      PdfParser._parse
pdf_parser.dart:238
#10     PdfParser.parseOffset
pdf_parser.dart:229
#11     CrossTable.getObject
cross_table.dart:287
#12     PdfCrossTable.getObject
pdf_cross_table.dart:1162
#13     PdfReferenceHolder._obtainObject
pdf_reference_holder.dart:156
#14     PdfReferenceHolder.object
pdf_reference_holder.dart:63
#15     PageResourceLoader.getFormResources.<anonymous closure>
page_resource_loader.dart:104
#16     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#17     PageResourceLoader.getFormResources
page_resource_loader.dart:102
#18     PageResourceLoader.getPageResources
page_resource_loader.dart:26
#19     PdfTextExtractor._getText
pdf_text_extractor.dart:283
#20     PdfTextExtractor._extractText
pdf_text_extractor.dart:189
#21     PdfTextExtractor.extractText
pdf_text_extractor.dart:105
#22     SfPdfViewerState._extractTextAsync
pdfviewer.dart:1345
#23     _RootZone.runUnary (dart:async/zone.dart:1661:54)
#24     _FutureListener.handleValue (dart:async/future_impl.dart:147:18)
#25     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:784:45)

(Tested on a real device, iPhone Xr, iOS 16.5.1)

This is how I load the file:

SfPdfViewer.file(
  _file,
  key: _pdfKey,
  controller: _controller,
  canShowScrollHead: _showScrollHead,
  pageLayoutMode: PdfPageLayoutMode.continuous,
  scrollDirection: PdfScrollDirection.vertical,
  currentSearchTextHighlightColor: primary.withOpacity(0.2),
  otherSearchTextHighlightColor: primary.withOpacity(0.1),
  initialScrollOffset: _lastRead,
  onDocumentLoadFailed: (details) {
    setState(() {
      _error = details.error;
    });
  },
)

Is there any way to reduce the impact on the heap?

deepika134 commented 10 months ago

We tried to reproduce the issue with the provided details, but scrolling is working properly without any exceptions on our side. We suspect it may be a PDF document specific issue, kindly share the following details:

This will be helpful for us to provide a prompt solution at the earliest.

soeren-schmaljohann-2denker commented 10 months ago

Hi, thanks for coming back to me. Here are some of the infos you asked for:

We are still working on providing you a pdf and/or a video of the problem, since the ones we used to reproduce the error are sensitive and can not be distributed publicly.

soeren-schmaljohann-2denker commented 10 months ago

I have a file and video ready now, but github doesn't allow uploads over 25 mb. Where should I upload the files for you?

soeren-schmaljohann-2denker commented 10 months ago

Here is a link to both the file and the video: https://we.tl/t-e03IotrA5b

deepika134 commented 10 months ago

I have a file and video ready now, but github doesn't allow uploads over 25 mb. Where should I upload the files for you?

We maintain the confidentiality of the information disclosed by our customers to us. Therefore, any documents shared with Syncfusion will only be used to replicate the issue and will not be shared with anyone else. So kindly share the original input document or share the input document after removing confidential information in the following mail ID support@syncfusion.com

deepika134 commented 10 months ago

Here is a link to both the file and the video: https://we.tl/t-e03IotrA5b

Thanks for sharing the details . We will check this and let you know the details .

deepika134 commented 10 months ago

We tried to replicate the issue with the provided details, but the scrolling is working fine on our side. For your reference we have attached the tested sample along with the output screen record of the same and it can be downloaded from the attachment. Kindly check the issue in the shared sample and let us know if you are still facing the same issue on your side. github_1289.zip

soeren-schmaljohann-2denker commented 10 months ago

Hello,

the error seems to only appear when using a real device, not a simulator.

soeren-schmaljohann-2denker commented 10 months ago

Hi,

could you please try it again on a physical device?

soeren-schmaljohann-2denker commented 10 months ago

Hi,

I could also reproduce the error on a physical iPhone X, iOS 16.5.1, using the version 22.1.39 of the package.

In the example, I'm not loading the pdf directly from the asset, since in our actual app, we have to download the file and then manually decrypt it. Here is the example used:

class PdfScreenState extends State<PdfScreen> {
  Uint8List? _bytes;  

  @override
  void initState() {
    super.initState();
    _loadAndDecryptPdf();
  }

  Future<void> _loadAndDecryptPdf() async {
    // _updateLastRead();
    setState(() {
      _error = null;
      _bytes = null;
    });

    final bytes = await rootBundle.load('assets/test.pdf');
    setState(() {
      _bytes = Uint8List.view(bytes.buffer);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
        builder: (_) {
          if (_bytes != null) {
            final primary = Theme.of(context).colorScheme.primary;
            return SfPdfViewer.memory(
              _bytes!,
              key: _pdfKey,
              controller: _controller,
              canShowScrollHead: _showScrollHead,
              pageLayoutMode: PdfPageLayoutMode.continuous,
              onPageChanged: (details) => DatabaseManager.instance
                  .saveLastRead(widget.id, _controller.scrollOffset),
              scrollDirection: PdfScrollDirection.vertical,
              currentSearchTextHighlightColor: primary.withOpacity(0.2),
              otherSearchTextHighlightColor: primary.withOpacity(0.1),
            );
          } else {
            return const LoadingScreen();
          }
        },
      ),
    );
  }
}

This is the error, I am getting:

Exhausted heap space, trying to allocate 67108880 bytes.

════════ Exception caught by widgets library ═══════════════════════════════════
The following OutOfMemoryError was thrown building FutureBuilder<Map<int, List<dynamic>>?>(dirty, dependencies: [Directionality, MediaQuery, _ViewScope], state: _FutureBuilderState<Map<int, List<dynamic>>?>#02390):
Out of Memory

The relevant error-causing widget was
SfPdfViewer-[LabeledGlobalKey<SfPdfViewerState>#d6d47]
pdf_screen.dart:226
When the exception was thrown, this was the stack
#0      List._grow (dart:core-patch/growable_array.dart:376:19)
#1      List.addAll (dart:core-patch/growable_array.dart:304:9)
#2      new PdfStream
pdf_stream.dart:33
#3      PdfParser._readStream
pdf_parser.dart:683
#4      PdfParser._dictionary
pdf_parser.dart:624
#5      PdfParser.simple
pdf_parser.dart:259
#6      PdfParser._parse
pdf_parser.dart:238
#7      PdfParser.parseOffset
pdf_parser.dart:229
#8      CrossTable.getObject
cross_table.dart:287
#9      PdfCrossTable.getObject
pdf_cross_table.dart:1162
#10     PdfReferenceHolder._obtainObject
pdf_reference_holder.dart:156
#11     PdfReferenceHolder.object
pdf_reference_holder.dart:63
#12     PageResourceLoader.getFormResources.<anonymous closure>
page_resource_loader.dart:104
#13     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#14     PageResourceLoader.getFormResources
page_resource_loader.dart:102
#15     PageResourceLoader.getPageResources
page_resource_loader.dart:26
#16     PdfTextExtractor._getText
pdf_text_extractor.dart:286
#17     PdfTextExtractor._extractText
pdf_text_extractor.dart:192
#18     PdfTextExtractor.extractText
pdf_text_extractor.dart:108
#19     SfPdfViewerState.build.<anonymous closure>.<anonymous closure>
pdfviewer.dart:2418
#20     new _GrowableList.generate (dart:core-patch/growable_array.dart:136:28)
#21     SfPdfViewerState.build.<anonymous closure>
pdfviewer.dart:2386
#22     _FutureBuilderState.build
async.dart:612
#23     StatefulElement.build
framework.dart:5198
#24     ComponentElement.performRebuild
framework.dart:5086
#25     StatefulElement.performRebuild
framework.dart:5251
#26     Element.rebuild
framework.dart:4805
#27     StatefulElement.update
framework.dart:5274
#28     SingleChildRenderObjectElement.update
framework.dart:6442
#29     ComponentElement.performRebuild
framework.dart:5111
#30     Element.rebuild
framework.dart:4805
#31     StatelessElement.update
framework.dart:5162
#32     SingleChildRenderObjectElement.update
framework.dart:6442
#33     ComponentElement.performRebuild
framework.dart:5111
#34     StatefulElement.performRebuild
framework.dart:5251
#35     Element.rebuild
framework.dart:4805
#36     BuildOwner.buildScope
framework.dart:2780
#37     WidgetsBinding.drawFrame
binding.dart:903
#38     RendererBinding._handlePersistentFrameCallback
binding.dart:358
#39     SchedulerBinding._invokeFrameCallback
binding.dart:1284
#40     SchedulerBinding.handleDrawFrame
binding.dart:1214
#41     SchedulerBinding._handleDrawFrame
binding.dart:1072
#42     _invoke (dart:ui/hooks.dart:142:13)
#43     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:359:5)
#44     _drawFrame (dart:ui/hooks.dart:112:31)
════════════════════════════════════════════════════════════════════════════════
[ServicesDaemonManager] interruptionHandler is called. -[FontServicesDaemonManager connection]_block_invoke
Exhausted heap space, trying to allocate 67108880 bytes.

════════ Exception caught by widgets library ═══════════════════════════════════
Out of Memory
The relevant error-causing widget was
SfPdfViewer-[LabeledGlobalKey<SfPdfViewerState>#d6d47]
pdf_screen.dart:226
════════════════════════════════════════════════════════════════════════════════
Exhausted heap space, trying to allocate 67108880 bytes.

════════ Exception caught by widgets library ═══════════════════════════════════
Out of Memory
The relevant error-causing widget was
SfPdfViewer-[LabeledGlobalKey<SfPdfViewerState>#d6d47]
pdf_screen.dart:226
════════════════════════════════════════════════════════════════════════════════
Exhausted heap space, trying to allocate 67108896 bytes.
* thread #29, name = 'DartWorker', stop reason = EXC_BAD_ACCESS (code=1, address=0x30)
    frame #0: 0x000000010592c41c Flutter`dart::Debugger::ShouldPauseOnException(dart::DebuggerStackTrace*, dart::Instance const&) + 64
Flutter`dart::Debugger::ShouldPauseOnException:
->  0x10592c41c <+64>: ldrb   w8, [x21, #0x31]
    0x10592c420 <+68>: cbnz   w8, 0x10592c4c4           ; <+232>
    0x10592c424 <+72>: mov    w8, #0x1
    0x10592c428 <+76>: strb   w8, [x21, #0x31]
Target 0: (Runner) stopped.
Lost connection to device.

Here is a link to both the PDF and a video of the crash: https://we.tl/t-b6p3mC5Vpa

Here is the flutter doctor -v output:

[✓] Flutter (Channel stable, 3.10.5, on macOS 13.4.1 22F770820d darwin-arm64, locale en-GB)
    • Flutter version 3.10.5 on channel stable at /Users/soeren/Library/Flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 796c8ef792 (6 weeks ago), 2023-06-13 15:51:02 -0700
    • Engine revision 45f6e00911
    • Dart version 3.0.5
    • DevTools version 2.23.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /Users/soeren/Library/Android/sdk
    • Platform android-33, build-tools 33.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E300c
    • CocoaPods version 1.12.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] VS Code (version 1.80.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.68.0

[✓] Connected device (4 available)
    • iPhoneX (mobile)           • 581694fd762e0ab6fb3970d494f25143219cba47 • ios            • iOS 16.5.1 20F75
    • iPhone 14 Pro Max (mobile) • A389E3D2-B3DC-44E9-BA9D-9B70202AA99C     • ios            • com.apple.CoreSimulator.SimRuntime.iOS-16-4 (simulator)
    • macOS (desktop)            • macos                                    • darwin-arm64   • macOS 13.4.1 22F770820d darwin-arm64
    • Chrome (web)               • chrome                                   • web-javascript • Google Chrome 114.0.5735.198

[✓] Network resources
    • All expected network resources are available.

• No issues found!
deepika134 commented 10 months ago

Currently, we do not have the iPhone XR and iPhone X physical devices. Alternatively, we have checked with iPad 5th generation [iOS version 15.7], and it is working fine. We did not encounter any crash issues on our end.

tsgregoryv commented 7 months ago

I was able to reproduce the issue using Flutter web on Chrome/Safari on iOS devices with a large PDF (physical device only). The PDF loads normally in the viewer, but will crash when you begin to scroll. If you split the same PDF into smaller files, then the crash does not occur. The crash does not seem to occur on iOS simulators.

I've noticed on some previous gen iPad Pros it works just fine, but I've reproduced the issue on all of Apple's current lineup of iPad & iPad PRO devices using iOS 17 (iPad Pro 6th gen, iPad 10th gen, iPad Air 5th gen, and iPad mini 6th gen).

a-mawlawi commented 5 months ago

@deepika134 we faced the same problem, and I can provide you with the PDF file, it's happens if you scroll down and up fast, please note that the issue only appears on real IOS devices and not on Android.

yasseralsamman commented 5 months ago

Same here, the way the plugin is trying to reload every page on scrolling has a role in this, even though it is already loaded. trying to do a fast scroll on a large pdf causes the crash.

ramkumarsync commented 3 months ago

We have fixed the high memory consumption when loading large documents, and the fix for the same will be available in version 22.2.11.

Kindly update the syncfusion_flutter_pdfviewer to the latest version to overcome this issue.

a-mawlawi commented 3 months ago

@ramkumarsync The latest version live is 24.2.4 and it's not fixed in this version.

tsgregoryv commented 3 months ago

@ramkumarsync Can you clarify a bit?

Did you mean to tag a release from 5 months ago? The changelog for the tagged release is not referencing the same problems that we are having.

Are you stating that your team has created a new patch which will be available in the near future? Or did you intend to tag the previous release?

Thank you again for your help.

ramkumarsync commented 3 months ago

@ramkumarsync Can you clarify a bit?

Did you mean to tag a release from 5 months ago? The changelog for the tagged release is not referencing the same problems that we are having.

Are you stating that your team has created a new patch which will be available in the near future? Or did you intend to tag the previous release?

Thank you again for your help.

The problem that occurred when scrolling through a large PDF document was due to text extraction and that was resolved. We have mentioned in our changelog the same in version v22.2.11. Please find the changelog for your reference: https://pub.dev/packages/syncfusion_flutter_pdf/versions/22.2.11/changelog#22211---08292023.

Could you please check with the latest version and check whether the issue is resolved?

If the issue still occurs, kindly share the document. It will help us analyze the issue deeper and provide a better solution.

ramkumarsync commented 3 months ago

@ramkumarsync The latest version live is 24.2.4 and it's not fixed in this version.

We suspect that the issue you are facing could be specific to the document. Kindly share the document in which you're facing the issue, it will help us analyze the issue deeper and provide a better solution at the earliest.

If you feel the document should not be shared publicly here, you can create a ticket in our support portal and share the details there. We will check and revert soon.

a-mawlawi commented 3 months ago

@ramkumarsync I opened a ticket and attached the pdf that will crash, ticket number is 555476

ramkumarsync commented 3 months ago

@ramkumarsync I opened a ticket and attached the pdf that will crash, ticket number is 555476

Thank you for sharing the document in the support ticket. Please follow the support ticket to track further status.