Bug 158914 - Calc leaks RAM when using macOS accessibility
Summary: Calc leaks RAM when using macOS accessibility
Status: ASSIGNED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Calc (show other bugs)
Version:
(earliest affected)
7.6.4.1 release
Hardware: ARM macOS (All)
: medium normal
Assignee: Patrick Luby (volunteer)
URL:
Whiteboard: target:24.8.0 target:24.2.4 target:24...
Keywords: accessibility
Depends on:
Blocks: a11y-macOS
  Show dependency treegraph
 
Reported: 2023-12-28 21:42 UTC by Allen Belletti
Modified: 2024-05-27 06:17 UTC (History)
8 users (show)

See Also:
Crash report or crash signature:


Attachments
Snapshot of Instruments application after clicking on dozens of empty Calc cells with VoiceOver enabled (1.69 MB, image/png)
2024-05-18 13:26 UTC, Patrick Luby (volunteer)
Details
Patch for debugging AquaA11yWrapper memory leaks (2.11 KB, text/plain)
2024-05-26 00:16 UTC, Patrick Luby (volunteer)
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Allen Belletti 2023-12-28 21:42:04 UTC
I'm currently using the latest 7.6.4.1 Apple Silicon release of LibreOffice Calc on a Mac M1 Mini 16GB. It's kept up to date and currently running MacOS Sonoma 14.2.1. That said, I've been experiencing what appears to be the same issue for quite some time before realizing what was happening.

In short, Calc leaks vast amounts of memory during normal use until finally at ~9GB or so, it is running too slowly to use. At that point, I can save my work, close (which takes minutes) or Force Kill Calc, and then start over. No data is lost, but it's bizarre.

Initially I thought this was related to a particular document in which I was often working. After more testing, it turns out that any document will behave the same way. Even a fresh, empty Calc document on a freshly-started copy of LO will exhibit the issue.

I can reproduce as follows:

1. Start LibreOffice
2. Under "Create:" on the left-hand menu, select "Calc Spreadsheet"

At this point, Activity Monitor shows 362.0 MB "Memory", 296.3 MB "Real Mem", 108.0 MB "Private Mem", and 77.7MB "Shared Mem". The numbers are stable as the application sits, open on a blank sheet "Untitled 1".

3. Click on random cells in the empty document. Not moving around via scroll bars, not typing anything, just selecting one cell and then another and another. Not groups or anything, just moving the pointer and left-clicking.

I've now clicked about 50 times and see the following stabilized memory numbers in Activity Monitor: 1005.0 MB "Memory", 956.0 MB "Real Mem", 750.3 MB "Private Mem", 77.7 MB "Shared Mem". Once again these numbers are stable now that I'm no longer clicking.

Once I start clicking again, the memory footprint resumes growing. In the case of doing real work in a document, Calc will eventually become very slow and ultimately unusable, after which the cycle above begins again.

A few things worth mentioning:

1. Writer does not exhibit any strange behavior.
2. No other application on the Mac (and I use it constantly) behaves strangely.
3. I do have Homebrew installed w/ various dev tools and whatnot.
4. I'm completely aware that this sounds crazy, and that it's surely tied to something about my environment, but I haven't been able to identify it. Am hoping perhaps there are diagnostics and logging that I can run to provide you with additional information. It does seem to be a bug in Calc though, despite being triggered by some unique(?) conditions.
Comment 1 Telesto 2023-12-29 21:29:49 UTC
FWIW: a nasty bug slipped through into 7.6.4.1 which could be -indirectly - responsible for the leaking. You might try 24.2.0.0.beta1 to (double) check if the issue is still occurring

https://dev-builds.libreoffice.org/pre-releases/mac/aarch64/LibreOfficeDev_24.2.0.0.beta1_MacOS_aarch64.dmg
Comment 2 Allen Belletti 2023-12-29 22:54:01 UTC
I installed and tested the development version just now, but it behaves essentially the same. As soon as I've selected a new Calc document, I'm able to leak memory at will. However, I did notice a few additional details which I've confirmed back in 7.6.4.1 as well:

1. It's not actually necessary to click -- merely "swirling" the pointer around in circles will trigger the same memory leakage, but *only* when the pointer is over the Calc window. Making the same movements over the desktop or another application have the expected result (no effect).

2. If I carefully confine the pointer to moving only along the horizontal scroll bar (immediately beneath the visible cells) or vertical scroll back (immediately to the right of visible cells), memory does not leak. Perhaps because these are being redrawn by the window manager rather than the Calc app itself?
Comment 3 kdub 2024-01-04 08:52:26 UTC
I just wanted to drop in here and mention that this bug (if others can confirm) does seem to only be on the ARM builds for macOS. I was not able to replicate on x86_64. Here is my info:

Version: 7.6.4.1 (X86_64) / LibreOffice Community
Build ID: e19e193f88cd6c0525a17fb7a176ed8e6a3e2aa1
CPU threads: 12; OS: Mac OS X 14.2.1; UI render: Skia/Metal; VCL: osx
Locale: en-US (en_US.UTF-8); UI: en-US
Calc: threaded
Comment 4 Telesto 2024-01-04 13:14:14 UTC
@Patrick 
You might be interested in this one.
Comment 5 Allen Belletti 2024-01-06 06:25:34 UTC
I'd been meaning to try the Mac/Intel build and @kdub inspired me to do so. TBH, I really expected the issue to disappear but it did not. As far as I can tell, it's behaving identically to the Apple Silicon build.

Version: 7.6.4.1 (X86_64) / LibreOffice Community
Build ID: e19e193f88cd6c0525a17fb7a176ed8e6a3e2aa1
CPU threads: 8; OS: Mac OS X 14.2.1; UI render: Skia/Raster; VCL: osx
Locale: en-US (en_US.UTF-8); UI: en-US
Calc: threaded

Mine appears identical to @kdub's except that he's using a better Mac ;-)

Still looks like something about my environment must be triggering the behavior.
Comment 6 kdub 2024-01-14 04:26:57 UTC
> Mine appears identical to @kdub's except that he's using a better Mac ;-)
> 
> Still looks like something about my environment must be triggering the
> behavior.

Lol, yes, our Macs are almost identical.

Honestly, this is probably pretty obvious, but I would look into anything that captures mouse input. For example, do you have a mouse settings program running in the background or something similar?
Comment 7 Allen Belletti 2024-01-15 20:06:24 UTC
It turns out that @kdub is absolutely correct. I use a Logitech Marble Mouse (the trackball) and in order to enable quick scrolling, I've been running a little tool called "Smart Scroll" (https://www.marcmoini.com/sx_en.html) for years. Long enough to mostly forget it's there.

Smart Scroll has 7 main functions (with many options under each.) Two of them, "Hover Scroll" and "Auto Scroll" seem to trigger this behavior merely by being enabled. The rest do not, as far as I can tell. Fortunately I'm only using "Grab Scroll" which can be enabled with no harmful effects.

For my situation, this constitutes a fix. I've exercised Calc a considerable amount over the last couple of days and memory usage stays where it ought. ~230MB in the case of my most important document. Granted, Visicalc ran in 48K but it was hardly feature complete by modern standards. ;-)

I'm going to reach out to the author of Smart Scroll and let him know what I've found. Perhaps the fact that it shows up with two specific features but not others will provide some sort of hint as to what's happening.

Meanwhile, this does feel a bit like a "double bug", ie, a bug in Smart Scroll triggering another in Calc. I say that only because none of my other apps (including LibreOffice Writer) have this reaction to Smart Scroll. On the other hand, I'm not a front-end guy at all so this is pure speculation. I'll understand if this is promptly closed.

Thanks for your time & attention!

Cheers,
Allen
Comment 8 Allen Belletti 2024-02-03 22:41:03 UTC
Talked to the Smart Scroll author a bit. He mentioned that the tool sends "Accessibility requests [...] in order to find out if the mouse cursor is over an edge of a scrollable area." He also says that they're sent as infrequently as possible, "typically only while the cursor is moving."

That matches what we're seeing here, as memory is only leaked when moving the cursor and even then, only over most of the Calc window (per the last paragraph of my Comment #2 here).

It does sound like Calc is somehow leaking memory while handling these requests, since the leak does not show up in any other application, even within LibreOffice. It's probably not a code path that sees heavy use in "normal" circumstances.

Fortunately for me, I'm able to turn off the features of Smart Scroll which trigger the bug while still retaining the features that I need. So for my personal situation, that's a 100% workaround. Feel free to close this, or let it lie until someone else runs into something similar.

Of course, if some ambitious soul does want to investigate, I'm happy to run a debug version or otherwise help out with testing, replication, and data-gathering.

Appreciate the interest on what's really a very obscure situation!

Cheers,
Allen
Comment 9 Stéphane Guillou (stragu) 2024-05-15 03:36:02 UTC
@Michael: as this touches on macOS accessibility events, any thoughts?

@Allen, might be worth testing a more recent version, if you haven't already, to see if things have changed. 24.2.3 or above ideally.
Comment 10 Michael Weghorn 2024-05-15 05:43:30 UTC
(In reply to Stéphane Guillou (stragu) from comment #9)
> @Michael: as this touches on macOS accessibility events, any thoughts?

I remember Noel fixed some Calc memory leak last year (see commit 8e886993f32b7db11a99bdecf06451e6de6c3842 ), but at least that fix was already included in daily builds last December (already tested according to comment 2).
Apart from that, I don't have any ideas right now without doing further analysis.
Comment 11 Patrick Luby (volunteer) 2024-05-15 21:29:48 UTC
(In reply to Allen Belletti from comment #7)
> It turns out that @kdub is absolutely correct. I use a Logitech Marble Mouse
> (the trackball) and in order to enable quick scrolling, I've been running a
> little tool called "Smart Scroll" (https://www.marcmoini.com/sx_en.html) for
> years. Long enough to mostly forget it's there.
> 
> Smart Scroll has 7 main functions (with many options under each.) Two of
> them, "Hover Scroll" and "Auto Scroll" seem to trigger this behavior merely
> by being enabled. The rest do not, as far as I can tell. Fortunately I'm
> only using "Grab Scroll" which can be enabled with no harmful effects.

I downloaded the trial version of Smart Scroll. I confirmed that "Hover Scroll" and "Auto Scroll" are enabled and, when I opened a new, empty Calc document, I noticed the same increasing memory usage as I clicked on random cells.

I'll run Xcode's Instruments application's memory leak detection tool and see if I can see where this increasing memory is being allocated:

Version: 24.8.0.0.alpha1+ (AARCH64) / LibreOffice Community
Build ID: 988efda2c0add0c037279283aee7e8c4e7ea14a0
CPU threads: 8; OS: macOS 14.4.1; UI render: Skia/Metal; VCL: osx
Locale: en-CA (en_CA.UTF-8); UI: en-US
Calc: threaded
Comment 12 Patrick Luby (volunteer) 2024-05-18 13:26:50 UTC
Created attachment 194184 [details]
Snapshot of Instruments application after clicking on dozens of empty Calc cells with VoiceOver enabled
Comment 13 Patrick Luby (volunteer) 2024-05-18 13:41:56 UTC
(In reply to Patrick Luby (volunteer) from comment #12)
> Created attachment 194184 [details]
> Snapshot of Instruments application after clicking on dozens of empty Calc
> cells with VoiceOver enabled

So I profiled my LibreOffice local master build using the Instruments applications and here is what I saw:

1. I didn't need Smart Scroll to reproduce the rapid increase in memory when clicking on empty cells. Instead, enabling macOS' built-in VoiceOver feature also triggered this behavior. Note: I have changed the title of this bug to reflect that.

2. The rapidly increasing memory usage is due to Calc creating a special accessibility object for each selected cell (i.e. an ScAccessibleCell).

3. Closing the Calc document frees all of the ScAccessibleCell cells.

Technically there isn't a leak since all this memory for ScAccessibleCells is freed when you close the Calc document, but these ScAccessibleCell apparently use a lot of memory. In attachment #194184 [details], I had clicked on less than 50 cells in an empty Calc document and that resulted in Calc holding 100 MB of ScAccessibleCells.

Next step: see if we can reduce the memory load when using Calc with accessibility enabled. Not sure what can be done, but I will walk through the code and see if maybe some parts of ScAccessibleCells can be reclaimed immediately after reuse.
Comment 14 Patrick Luby (volunteer) 2024-05-19 17:40:44 UTC
(In reply to Michael Weghorn from comment #10)
> I remember Noel fixed some Calc memory leak last year (see commit
> 8e886993f32b7db11a99bdecf06451e6de6c3842 ), but at least that fix was
> already included in daily builds last December (already tested according to
> comment 2).
> Apart from that, I don't have any ideas right now without doing further
> analysis.

So I added the following debug patch to see if there was any ScAccessibleCell were never getting deleted. The good news is that when you close a Calc document, the number of undeleted ScAccessibleCell instances goes back down to zero.

But what I found interesting is that while VoiceOver is enabled, clicking on a cell causes roughly 2K new ScAccessibleCell instances to be allocated. A few of those instances gets deleted very soon after it is allocated, but all the rest are cached somewhere until the Calc document is closed.

So, the next thing to investigate is which code is requesting so many new ScAccessibleCell instances for each cell:

diff --git a/sc/source/ui/Accessibility/AccessibleCell.cxx b/sc/source/ui/Accessibility/AccessibleCell.cxx
index b27fbb90671a..0d6beafa37c8 100644
--- a/sc/source/ui/Accessibility/AccessibleCell.cxx
+++ b/sc/source/ui/Accessibility/AccessibleCell.cxx
@@ -49,6 +49,8 @@
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::accessibility;
 
+static std::map<ScAccessibleCell*, ScAccessibleCell*> aAccessibleCellMap;
+
 rtl::Reference<ScAccessibleCell> ScAccessibleCell::create(
         const uno::Reference<XAccessible>& rxParent,
         ScTabViewShell* pViewShell,
@@ -79,10 +81,15 @@ ScAccessibleCell::ScAccessibleCell(
 {
     if (pViewShell)
         pViewShell->AddAccessibilityObject(*this);
+aAccessibleCellMap[this] = this;
 }
 
 ScAccessibleCell::~ScAccessibleCell()
 {
+std::map<ScAccessibleCell*, ScAccessibleCell*>::iterator it = aAccessibleCellMap.find(this);
+if (it != aAccessibleCellMap.end())
+aAccessibleCellMap.erase(it);
+fprintf(stderr, "ScAccessibleCell count; %lu\n", aAccessibleCellMap.size());
     if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
     {
         // increment refcount to prevent double call off dtor
Comment 15 Patrick Luby (volunteer) 2024-05-19 18:04:30 UTC
(In reply to Patrick Luby (volunteer) from comment #14)
> But what I found interesting is that while VoiceOver is enabled, clicking on
> a cell causes roughly 2K new ScAccessibleCell instances to be allocated. A
> few of those instances gets deleted very soon after it is allocated, but all
> the rest are cached somewhere until the Calc document is closed.

I've narrowed the problem down to the following patch:

https://git.libreoffice.org/core/+/8e886993f32b7db11a99bdecf06451e6de6c3842%5E!

Before that patch, the code reused the same ScAccessibleCell instance for the 2K requests that we are seeing for each selected cell.

Apparently, that caused the data in the reused ScAccessibleCell to be stale under certain circumstances (e.g. deleting the cell's contents) so we can't now I think we need to move higher up the stack and figure out what Calc code needs 2K ScAccessibleCell instances for each cell.
Comment 16 Patrick Luby (volunteer) 2024-05-21 15:00:27 UTC
(In reply to Patrick Luby (volunteer) from comment #15)
> Before that patch, the code reused the same ScAccessibleCell instance for
> the 2K requests that we are seeing for each selected cell.

The 2K requests are coming from macOS. From what I see, macOS queries accessible tables for a list of its accessible children. What's really interesting is that macOS does this query 8 times in a row and each time we are returning the same range of visible cells. So that causes a lot of duplicate memory to be allocated in Calc.

An additional cause of the excessive memory usage appears to be that each request is cached somewhere in Calc and so all previous requests are held in memory and are not deleted until the document is closed.

So my next steps are to see if I can do either or both of following:

1. See if I can reduce the duplicate macOS requests for the range of visible cells. Maybe macOS is trying to resolve the difference between the total number of cells in the table (i.e. rows times columns) and the number of visible cells.

2. When macOS releases the native object, somehow notify Calc to delete the native object's ScAccessibleCell pointer.
Comment 17 Commit Notification 2024-05-25 07:03:03 UTC
Michael Weghorn committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/4d2c41e8171139e210d94b0c3c2b6b3d6392665a

related tdf#158914 sc a11y: Release references when disposing sheet

It will be available in 24.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 18 Patrick Luby (volunteer) 2024-05-26 00:16:10 UTC
Created attachment 194356 [details]
Patch for debugging AquaA11yWrapper memory leaks
Comment 19 Commit Notification 2024-05-26 07:53:30 UTC
Michael Weghorn committed a patch related to this issue.
It has been pushed to "libreoffice-24-2-4":

https://git.libreoffice.org/core/commit/661eed7b8e5412a0c6f952dc30a529683a2f5986

related tdf#158914 sc a11y: Release references when disposing sheet

It will be available in 24.2.4.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 20 Commit Notification 2024-05-26 07:53:32 UTC
Patrick Luby committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/0735a4306da86c6fa0390b85f1f391ec404b2699

Related tdf#158914: fix memory leaks by calling (auto)release selectors

It will be available in 24.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 21 Commit Notification 2024-05-26 07:53:36 UTC
Michael Weghorn committed a patch related to this issue.
It has been pushed to "libreoffice-24-2":

https://git.libreoffice.org/core/commit/e7a660709c153239bfec8ddb445d0ee7ed790215

related tdf#158914 sc a11y: Release references when disposing sheet

It will be available in 24.2.5.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 22 Patrick Luby (volunteer) 2024-05-26 16:04:29 UTC
Update: the recent commits don't fix this bug but they do eliminate a bunch of memory leaks in the macOS native code that connects LibreOffice's internal C++ code to the macOS' accessibility subsystem.

Now that those leaks are fixed, I am working on the following patch:

https://gerrit.libreoffice.org/c/core/+/167961

The patch significantly reduces memory usage when macOS' accessibility subsystem  interacts with a Calc document. However, I still need to find a fix for tdf#157568 before I can commit the patch.

I will post again when I have some news to report.
Comment 23 Commit Notification 2024-05-27 04:04:49 UTC
Patrick Luby committed a patch related to this issue.
It has been pushed to "libreoffice-24-2":

https://git.libreoffice.org/core/commit/c24d9bef5502fb9176f5838bbf15eadcbee1e742

Related tdf#158914: fix memory leaks by calling (auto)release selectors

It will be available in 24.2.5.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 24 Commit Notification 2024-05-27 06:17:27 UTC
Patrick Luby committed a patch related to this issue.
It has been pushed to "libreoffice-24-2-4":

https://git.libreoffice.org/core/commit/92ed1c31467db58d4feca4cf5dc556bac32fcc5e

Related tdf#158914: fix memory leaks by calling (auto)release selectors

It will be available in 24.2.4.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.