Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OwnTone getting stuck when trying to open a large library with Apple Music #1817

Open
aaronk6 opened this issue Sep 29, 2024 · 21 comments
Open

Comments

@aaronk6
Copy link
Contributor

aaronk6 commented Sep 29, 2024

Platform:

  • OwnTone 28.10 on Ubuntu 22.04 (4 CPU cores, 8 GB RAM)
  • macOS 15.0 / Apple Music 1.5.0.174

Steps to reproduce:

  • Have a large library (> 100k tracks).
  • Open Apple Music on macOS.
  • Select the OwnTone library in the sidebar.

It will take a while to load, but will eventually show the full library.

However, this is where it gets stuck:

  • Most album artworks don’t load.
  • Playback doesn’t work (sits at “Connecting…” forever).

At the same time on the server:

  • The OwnTone processes max out all 4 CPU cores.
  • The log output stopped.
  • The Web interface isn’t reachable anymore.
Screenshot 2024-09-29 at 21 18 53

Note that I added the following override to the OwnTone unit file:

[Service]
OOMScoreAdjust=-1000

Without this, the OwnTone process was killed when trying to open the OwnTone library in Apple Music:

owntone.service: A process of this unit has been killed by the OOM killer.

Is there anything I can tweak on my system? Or is this something that needs to be optimized in OwnTone?

Thanks!

@ejurgensen
Copy link
Member

I'm not sure what is going on here. The log isn't showing much, expect maybe some artwork scaling. Can you attach gdb to the process to find out what owntone is doing? Something like this:

  1. Install gdb if you don't have it already
  2. Restart OwnTone and connect with Apple Music
  3. Watch with htop like you did and note the threads getting hot
  4. Attach gdb to the process with: 'sudo gdb -p [PID]'
  5. Enter 'info threads' and see if you can find the id of one of the busy threads
  6. Enter 'thread [id]'
  7. Enter 'bt' (means backtrace)
  8. (you can now quit with 'q')

Hopefully this reveals what those threads are stuck doing.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Sep 30, 2024

Thanks! I’m actually doing this for the first time, so thanks for the detailed steps. Here is what I found out.

Those were the processes consuming CPU time:

Stuck Processes

So I examined 4410 and 4420, which were:

worker (3):

#0  __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:351
#1  0x00007f1c62a08dd7 in av_mallocz () from /lib/x86_64-linux-gnu/libavutil.so.56
#2  0x00007f1c631b9594 in ?? () from /lib/x86_64-linux-gnu/libavcodec.so.58
#3  0x00007f1c631bda54 in ?? () from /lib/x86_64-linux-gnu/libavcodec.so.58
#4  0x00007f1c62efc85f in ?? () from /lib/x86_64-linux-gnu/libavcodec.so.58
#5  0x00007f1c62efd6e0 in avcodec_send_packet () from /lib/x86_64-linux-gnu/libavcodec.so.58
#6  0x0000561ea94d5536 in decode_filter_encode_write (ctx=0x7f1c56d6a7c0, s=0x7f1c483900d8, pkt=<optimized out>, type=AVMEDIA_TYPE_VIDEO) at transcode.c:888
#7  0x0000561ea94d574f in read_decode_filter_encode_write (ctx=<optimized out>) at transcode.c:970
#8  0x0000561ea94d70d1 in transcode_decode (frame=frame@entry=0x7f1c56d6a838, dec_ctx=0x7f1c48390030) at transcode.c:2248
#9  0x0000561ea94d85c9 in artwork_get (evbuf=0x7f1c24060700, path=path@entry=0x7f1c56d6ae30 "/mnt/storage/share/Musik/Library/Artists/Califone/2009 All My Friends Are Funeral Singers (album)/101 Califone - Giving Away the Bride.mp3", in_buf=in_buf@entry=0x0,
    is_embedded=is_embedded@entry=true, data_kind=<optimized out>, req_params=...) at artwork.c:735
#10 0x0000561ea94d8a17 in source_item_embedded_get (ctx=0x7f1c56d6ae30) at artwork.c:1532
#11 0x0000561ea94d7ee3 in process_items (ctx=ctx@entry=0x7f1c56d6ae30, item_mode=item_mode@entry=0) at artwork.c:1886
#12 0x0000561ea94d8f45 in process_group (ctx=ctx@entry=0x7f1c56d6ae30) at artwork.c:1982
#13 0x0000561ea94dacab in artwork_get_item (evbuf=0x7f1c24060700, id=78189, max_w=0, max_h=0, format=format@entry=0) at artwork.c:2032
#14 0x0000561ea94bca3b in daap_reply_extra_data (hreq=0x7f1c24023e70) at httpd_daap.c:1989
#15 0x0000561ea94be769 in daap_request (hreq=0x7f1c24023e70) at httpd_daap.c:2278
#16 0x0000561ea94e3e87 in execute (thr=<optimized out>, arg=0x7f1c2417e670, shared=<optimized out>) at worker.c:91
#17 0x0000561ea950835c in _evthr_read_cmd (which=<optimized out>, args=0x561eab30b630, sock=<optimized out>) at evthr.c:114
#18 _evthr_read_cmd (sock=<optimized out>, which=<optimized out>, args=0x561eab30b630) at evthr.c:98
#19 0x00007f1c62368f58 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#20 0x00007f1c6236a8a7 in event_base_loop () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#21 0x0000561ea950826e in _evthr_loop (args=0x561eab30b630) at evthr.c:159
#22 _evthr_loop (args=0x561eab30b630) at evthr.c:126
#23 0x00007f1c6192fac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#24 0x00007f1c619c1850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

httpd (13):

#0  __strchrnul_avx2 () at ../sysdeps/x86_64/multiarch/strchr-avx2.S:65
#1  0x00007f1c619100e2 in __find_specmb (format=0x7f1c6238dea0 "Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s); close change was %d (%s)") at ./stdio-common/printf-parse.h:111
#2  __vfprintf_internal (s=s@entry=0x7f1c3d7f8690, format=format@entry=0x7f1c6238dea0 "Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s); close change was %d (%s)", ap=ap@entry=0x7f1c3d7f8c60, mode_flags=mode_flags@entry=2)
    at ./stdio-common/vfprintf-internal.c:1255
#3  0x00007f1c6192349a in __vsnprintf_internal (string=0x7f1c3d7f8830 "", maxlen=<optimized out>, format=0x7f1c6238dea0 "Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s); close change was %d (%s)", args=0x7f1c3d7f8c60,
    mode_flags=2) at ./libio/vsnprintf.c:114
#4  0x00007f1c6236d153 in evutil_vsnprintf () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#5  0x00007f1c6236e2c8 in event_logv_ () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#6  0x00007f1c6236e549 in event_warn () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#7  0x00007f1c6237df85 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#8  0x00007f1c6236cfcf in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#9  0x00007f1c6236732e in evmap_io_add_ () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#10 0x00007f1c62368178 in event_add_nolock_ () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#11 0x00007f1c623684ac in event_add () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#12 0x00007f1c6235f5d5 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#13 0x00007f1c6235e647 in bufferevent_enable () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#14 0x00007f1c6236af6f in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#15 0x00007f1c6235db65 in bufferevent_setfd () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#16 0x00007f1c62380b42 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#17 0x00007f1c62370c35 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#18 0x00007f1c62368f58 in ?? () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#19 0x00007f1c6236a8a7 in event_base_loop () from /lib/x86_64-linux-gnu/libevent-2.1.so.7
#20 0x0000561ea950826e in _evthr_loop (args=0x561eab4a4100) at evthr.c:159
#21 _evthr_loop (args=0x561eab4a4100) at evthr.c:126
#22 0x00007f1c6192fac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#23 0x00007f1c619c1850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Does this help?

I also want to mention that the system is a VM running with libvirt/qemu. I’m using the “Enable shared memory” option, so I can mount my music library using virtiofs. If you suspect that this might have something to do with the issue I’m seeing, I’m happy to set up a bare metal system.

@ejurgensen
Copy link
Member

ejurgensen commented Sep 30, 2024

Yes, it helps, but unfortunately doesn't pinpoint the cause. It shows that the worker thread is busy extracting and rescaling embedded artwork from 101 Califone - Giving Away the Bride.mp3, but I'm not sure if it's stuck on that particular file. The last call is ffmpeg's avcodec_send_packet() allocating memory, so if that is somehow spinning then memory consumption will explode, which would explain the OOM killer. When you watch the process, do you then see the memory consumption keep going up? If you interrupt again with gdb, is the thread then still working on the same file?

The gdb dump indicates the httpd thread isn't doing anything, and that's as it should be, since cpu intensive stuff should only be in the worker threads. However, your htop screenshot says thread 4420 is pretty busy, so that's odd if its the httpd thread. Are you sure that's the case? I think you can get htop to show the thread names directly with Setup (F2) > Display > Show custom thread names

@aaronk6
Copy link
Contributor Author

aaronk6 commented Oct 2, 2024

When you watch the process, do you then see the memory consumption keep going up?

The yellow area in htop’s mem graph is actually going up steadily, but not the process’s memory consumption, at least not significantly (video attached below). However, at the same time, kern.log is filling rapidly with these messages until the disk is eventually full:

Oct  2 16:33:51 homeserver kernel: [64633.077750] Memory cgroup stats for /system.slice/owntone.service:
Oct  2 16:33:51 homeserver kernel: [64633.077757] anon 254877696
Oct  2 16:33:51 homeserver kernel: [64633.077757] file 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] kernel_stack 278528
Oct  2 16:33:51 homeserver kernel: [64633.077757] pagetables 954368
Oct  2 16:33:51 homeserver kernel: [64633.077757] percpu 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] sock 503808
Oct  2 16:33:51 homeserver kernel: [64633.077757] shmem 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] file_mapped 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] file_dirty 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] file_writeback 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] swapcached 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] anon_thp 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] file_thp 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] shmem_thp 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] inactive_anon 254857216
Oct  2 16:33:51 homeserver kernel: [64633.077757] active_anon 4096
Oct  2 16:33:51 homeserver kernel: [64633.077757] inactive_file 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] active_file 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] unevictable 16384
Oct  2 16:33:51 homeserver kernel: [64633.077757] slab_reclaimable 9962048
Oct  2 16:33:51 homeserver kernel: [64633.077757] slab_unreclaimable 1974256
Oct  2 16:33:51 homeserver kernel: [64633.077757] slab 11936304
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_refault_anon 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_refault_file 1728278
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_activate_anon 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_activate_file 295426
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_restore_anon 0
Oct  2 16:33:51 homeserver kernel: [64633.077757] workingset_restore_file 119773
Oct  2 16:33:51 homeserver kernel: [64633.077759] Tasks state (memory values in pages):
Oct  2 16:33:51 homeserver kernel: [64633.077759] [  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
Oct  2 16:33:51 homeserver kernel: [64633.077760] [    874]     0   874   358639    64781   966656        0         -1000 owntone
Oct  2 16:33:51 homeserver kernel: [64633.077762] Out of memory and no killable processes...
Oct  2 16:33:51 homeserver kernel: [64633.078325] websocket invoked oom-killer: gfp_mask=0x1100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=-1000
Oct  2 16:33:51 homeserver kernel: [64633.078329] CPU: 1 PID: 1735 Comm: websocket Not tainted 5.15.0-122-generic #132-Ubuntu
Oct  2 16:33:51 homeserver kernel: [64633.078332] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
Oct  2 16:33:51 homeserver kernel: [64633.078333] Call Trace:
Oct  2 16:33:51 homeserver kernel: [64633.078334]  <TASK>
Oct  2 16:33:51 homeserver kernel: [64633.078336]  show_stack+0x52/0x5c
Oct  2 16:33:51 homeserver kernel: [64633.078339]  dump_stack_lvl+0x4a/0x63
Oct  2 16:33:51 homeserver kernel: [64633.078341]  dump_stack+0x10/0x16
Oct  2 16:33:51 homeserver kernel: [64633.078343]  dump_header+0x53/0x228
Oct  2 16:33:51 homeserver kernel: [64633.078346]  out_of_memory.cold+0x4d/0x97
Oct  2 16:33:51 homeserver kernel: [64633.078349]  mem_cgroup_out_of_memory+0x13f/0x160
Oct  2 16:33:51 homeserver kernel: [64633.078353]  try_charge_memcg+0x687/0x740
Oct  2 16:33:51 homeserver kernel: [64633.078355]  ? kernel_init_free_pages.part.0+0x4a/0x70
Oct  2 16:33:51 homeserver kernel: [64633.078358]  ? get_page_from_freelist+0x353/0x540
Oct  2 16:33:51 homeserver kernel: [64633.078361]  charge_memcg+0x45/0xb0
Oct  2 16:33:51 homeserver kernel: [64633.078363]  __mem_cgroup_charge+0x2d/0x90
Oct  2 16:33:51 homeserver kernel: [64633.078365]  __add_to_page_cache_locked+0x2d8/0x350
Oct  2 16:33:51 homeserver kernel: [64633.078367]  ? scan_shadow_nodes+0x40/0x40
Oct  2 16:33:51 homeserver kernel: [64633.078370]  add_to_page_cache_lru+0x4d/0Oct  2 22:38:06 homeserver kernel: [86487.094860]  out_of_memory.cold+0x4d/0x97

It shows that the worker thread is busy extracting and rescaling embedded artwork from 101 Califone - Giving Away the Bride.mp3, but I'm not sure if it's stuck on that particular file.

I tried it again today, and this time it was stuck on another file. I then attached the debugger and made another backtrace. I detached the debugger again, let it run for a few seconds, reattached the debugger, and did another backtrace. It was sitting at the same file. While I did this, the kern.log messages I pasted above had already started to appear.

I think you can get htop to show the thread names directly with Setup (F2) > Display > Show custom thread names

That worked. There is indeed some significant CPU usage on websocket and httpd:

Screenshot 2024-10-02 at 23 10 06

Here’s a video that shows how the situation unfolds:

Screen.Recording.2024-10-02.at.23.01.06.mp4

It might make sense to test this without the virtualization layer in between, just to narrow things down. Let me know your thoughts!

@ejurgensen
Copy link
Member

Great investigation, but unfortunately I am even more confused now. Seems something is eating memory, apparently not owntone directly, but something that owntone is triggering? The httpd thread being busy is puzzling, and even more so the websocket thread, since when you connect with Apple Music there are no websockets involved at all.

I also have no idea why kern.log goes bananas. I'm not sure how to interpret the kernel log output you shared, but the internet tells me anon is memory consumption, and if that's 256 mb (or 258 like htop says) then it seems a tad high but not problematic.

It might make sense to test this without the virtualization layer in between, just to narrow things down. Let me know your thoughts!

Yes, that would be a good idea. Also just due to the fact that I'm at a loss about the above, so won't be able to help you fix it.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Oct 10, 2024

Yeah, it's really weird. I'll see if I can reproduce the issue on a native, vanilla Ubuntu system. That will hopefully give us a better idea of what's going on. However, I won't get a chance to do this until likely end of October. I'll be in touch then!

@aaronk6
Copy link
Contributor Author

aaronk6 commented Oct 28, 2024

I tested this on a dedicated Ubuntu 24.04 system and there the process was also killed:

2024-10-28T21:51:27.354618+01:00 owntone kernel: oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0,oom_memcg=/system.slice/owntone.service,task_memcg=/system.slice/owntone.service,task=owntone,pid=6741,uid=0
2024-10-28T21:51:27.354626+01:00 owntone kernel: Memory cgroup out of memory: Killed process 6741 (owntone) total-vm:1422932kB, anon-rss:255672kB, file-rss:22144kB, shmem-rss:0kB, UID:0 pgtables:1228kB oom_score_adj:0

However, it seems that the following service override (added to /etc/systemd/system/owntone.service.d/override.conf) fixes the issue:

[Service]
MemoryMax=2G

I didn’t try lower values, but VIRT in htop is around 1400M and RES is around 400M. I’m not sure which value is the one to look at, but I figured it won’t hurt to give it some headroom either way.

I then went back to my virtualized Ubuntu 22.04 system, added MemoryMax=2G there as well, and just connected using Apple Music. No crash so far. It has been happily generating artworks for the past 30 minutes (in my earlier experiments, it would crash after 1 minute or so). I’ll leave it running over night and report back in the next couple of days.

@ejurgensen
Copy link
Member

Was it still working? Seems it isn't a leak, but I have no idea why the image conversion would then require so much mem.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Oct 31, 2024

Yes, it successfully scanned all artworks and has been stable over the past 2 days. I didn’t mention this earlier, but without the MemoryMax option, I was also encountering crashes when browsing the library via the web UI or via the Remote app on iOS, or also sometimes just randomly while playing tracks from the local library. These also seem to be fixed by increasing MemoryMax. I realized that the standard systemd unit that comes with OwnTone has MemoryMax set to 256M. Apparently that’s not enough for large libraries.

systemd reports that it’s using 1.7G on my system:

$ sudo systemctl status owntone
● owntone.service - DAAP/DACP (iTunes), RSP and MPD server, supports AirPlay and Remote
     Loaded: loaded (/etc/systemd/system/owntone.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/owntone.service.d
             └─override.conf
     Active: active (running) since Mon 2024-10-28 22:58:35 CET; 2 days ago
       Docs: man:owntone(8)
   Main PID: 3222715 (owntone)
      Tasks: 18 (limit: 9394)
     Memory: 1.7G (max: 2.0G swap max: 32.0M available: 219.6M)
        CPU: 3h 29min 15.885s
     CGroup: /system.slice/owntone.service
             └─3222715 /usr/sbin/owntone -f

For my use case, it’s acceptable to leave MemoryMax at 2G. However, if you’re interested in analyzing this further, I’m here to help and can run further tests. Otherwise I suggest I resolve this issue, but maybe we could add a hint to the troubleshooting section at https://github.com/owntone/owntone-server/blob/master/docs/library.md. What do you think?

@ejurgensen
Copy link
Member

Idk, adding a doc workaround is last resort. OwnTone is supposed to be pretty light-weight, and that's hardly what you are seeing. Just now, I tested myself with Apple Music and my somewhat smaller library (just 2k songs), and memory consumption peaked at only 25MB.

I hope you can help with some more testing:

  • Create a new user on your Mac (this is just so Apple Music starts clean - you can remove the user again after the test)
  • On your dedicated Ubuntu, stop OwnTone and rename /var/cache/owntone/artwork.db to something else (after the test, put it back)
  • Start OwnTone with Valgrind Massif: sudo valgrind --tool=massif --massif-out-file=$HOME/owntone.massif --trace-children=yes /usr/sbin/owntone -f
  • When OwnTone has started, log into the new user, open Apple Music and open the library
  • Now it should start reading the library and artwork (really slowly). Let it do that for like 10 minutes. Then quit Apple Music.
  • Now end OwnTone with Ctrl+C. Wait until owntone.massif gets written.
  • Share owtone.massif here. It shouldn't contain anything sensitive. You can read it with ms_print.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 4, 2024

I’m happy to try these steps in the next couple of days. Will report back!

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 10, 2024

Here is the file: owntone.massif.zip

Before I logged in to the fresh macOS account and started Apple Music, I let OwnTone settle (finish library scanning, smart playlists, Spotify, etc.)

Also, for the record, I changed --massif-out-file to point to /tmp/owntone.massif since I got an error writing it to my home dir, even though it was running as root: Error: can not open xtree output file '/home/aaron/owntone.massif'.

Here is a screenshot I took after quitting Apple Music (after letting it run for 10 minutes) and right before hitting Ctrl+C on the OwnTone process:

Screenshot 2024-11-10 at 13 39 05

Let me know if this is helpful.

@ejurgensen
Copy link
Member

Thanks for testing, pretty interesting. It confirms that there is no memory leak, so that's good to get confirmed. Memory consumption peaks at 182MB, which is pretty high, but strangely still quite far from the 2G you had to set as max. The report below shows the allocation. It confirms that it's the artwork processing that's using it.

The report also indicates that only some of the artwork requests are memory heavy, so I think I will try to make a version of OwnTone with special logging/handling of those requests. So that would be the next thing I would ask you to test.

Btw, good that you included the sizes of the cache db's. They are pretty large, especially that 1.3 GB artwork cache. However, that in itself isn't necessarily a problem. If my math is right, it's just 13KB per track, so really not too bad. And the internet says sqlite can support large databases.

As I recall, when Apple Music loads the library the first time, it requests artwork for every single track in your library. That's of course wildly ineffective for a 100k library. But I can't do much about that.

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 37 512,559,081,040       11,733,624       11,226,651       506,973            0
 38 526,673,955,855       11,749,136       11,241,915       507,221            0
 39 537,965,492,248       11,751,592       11,244,363       507,229            0
 40 554,902,793,272       11,736,384       11,229,323       507,061            0
 41 569,016,145,156       11,751,624       11,244,355       507,269            0
 42 583,131,210,525       11,752,056       11,244,811       507,245            0
 43 596,733,700,957       39,270,928       38,711,874       559,054            0
 44 607,832,016,938      182,617,576      182,059,234       558,342            0
99.69% (182,059,234B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->66.86% (122,098,882B) 0x608FC14: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| ->49.11% (89,690,535B) 0x605A4C9: av_buffer_alloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| | ->37.55% (68,580,975B) 0x605A551: av_buffer_allocz (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| | | ->37.55% (68,580,975B) 0x605AE2D: av_buffer_pool_get (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| | | | ->21.42% (39,108,175B) 0x4E8548E: avcodec_default_get_buffer2 (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | ->21.42% (39,108,175B) 0x4DBC43A: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | | ->21.42% (39,108,175B) 0x51B99BE: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | | | ->21.42% (39,108,175B) 0x51BC06B: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | | |   ->21.42% (39,108,175B) 0x4DBA524: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | | |     ->21.42% (39,108,175B) 0x4DBAB23: avcodec_send_packet (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | | | | | |       ->21.42% (39,108,175B) 0x172E26: decode_filter_encode_write (transcode.c:888)
| | | | | | |       | ->21.42% (39,108,175B) 0x174AF0: transcode_decode (transcode.c:2248)
| | | | | | |       |   ->21.42% (39,108,175B) 0x176058: artwork_get (artwork.c:735)
| | | | | | |       |     ->21.42% (39,108,175B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| | | | | | |       |       ->21.42% (39,108,175B) 0x175930: process_items (artwork.c:1886)
| | | | | | |       |         ->21.42% (39,108,175B) 0x176A84: process_group (artwork.c:1982)
| | | | | | |       |           ->21.42% (39,108,175B) 0x178772: artwork_get_item (artwork.c:2032)
| | | | | | |       |             ->21.42% (39,108,175B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| | | | | | |       |               ->21.42% (39,108,175B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| | | | | | |       |                 ->21.42% (39,108,175B) 0x181646: execute (worker.c:91)
| | | | | | |       |                   ->21.42% (39,108,175B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| | | | | | |       |                     ->21.42% (39,108,175B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| | | | | | |       |                       ->21.42% (39,108,175B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | | | | | |       |                         ->21.42% (39,108,175B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | | | | | |       |                           ->21.42% (39,108,175B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| | | | | | |       |                             ->21.42% (39,108,175B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| | | | | | |       |                               ->21.42% (39,108,175B) 0x89B5A93: start_thread (pthread_create.c:447)
| | | | | | |       |                                 ->21.42% (39,108,175B) 0x8A42A33: clone (clone.S:100)
| | | | | | |       |                                   
| | | | | | |       ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | | | | | |       
| | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | | | | | 
| | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | | | | 
| | | | ->16.14% (29,472,800B) 0x7349E3C: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |   ->16.14% (29,472,800B) 0x7572A0A: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |     ->16.14% (29,472,800B) 0x7572B40: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |       ->16.14% (29,472,800B) 0x74C6C13: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |         ->16.14% (29,472,800B) 0x74C75A9: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |           ->16.14% (29,472,800B) 0x731E65A: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |             ->16.14% (29,472,800B) 0x732283C: ??? (in /usr/lib/x86_64-linux-gnu/libavfilter.so.9.12.100)
| | | |               ->16.14% (29,472,800B) 0x172D10: filter_encode_write (transcode.c:855)
| | | |                 ->16.14% (29,472,800B) 0x172D10: filter_encode_write (transcode.c:838)
| | | |                   ->16.14% (29,472,800B) 0x174BB2: transcode_encode (transcode.c:2289)
| | | |                     ->16.14% (29,472,800B) 0x176079: artwork_get (artwork.c:742)
| | | |                       ->16.14% (29,472,800B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| | | |                         ->16.14% (29,472,800B) 0x175930: process_items (artwork.c:1886)
| | | |                           ->16.14% (29,472,800B) 0x176A84: process_group (artwork.c:1982)
| | | |                             ->16.14% (29,472,800B) 0x178772: artwork_get_item (artwork.c:2032)
| | | |                               ->16.14% (29,472,800B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| | | |                                 ->16.14% (29,472,800B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| | | |                                   ->16.14% (29,472,800B) 0x181646: execute (worker.c:91)
| | | |                                     ->16.14% (29,472,800B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| | | |                                       ->16.14% (29,472,800B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| | | |                                         ->16.14% (29,472,800B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | | |                                           ->16.14% (29,472,800B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | | |                                             ->16.14% (29,472,800B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| | | |                                               ->16.14% (29,472,800B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| | | |                                                 ->16.14% (29,472,800B) 0x89B5A93: start_thread (pthread_create.c:447)
| | | |                                                   ->16.14% (29,472,800B) 0x8A42A33: clone (clone.S:100)
| | | |                                                     
| | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | | 
| | ->11.56% (21,108,472B) 0x493AADB: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | | ->11.56% (21,108,472B) 0x493B69E: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |   ->11.56% (21,108,472B) 0x493C444: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |     ->11.56% (21,108,472B) 0x48F35AC: avformat_open_input (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |       ->11.56% (21,108,472B) 0x172375: open_input (transcode.c:1429)
| | |         ->11.56% (21,108,472B) 0x17318C: transcode_decode_setup (transcode.c:1946)
| | |           ->11.56% (21,108,472B) 0x175E9A: artwork_get (artwork.c:651)
| | |             ->11.56% (21,108,472B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| | |               ->11.56% (21,108,472B) 0x175930: process_items (artwork.c:1886)
| | |                 ->11.56% (21,108,472B) 0x176A84: process_group (artwork.c:1982)
| | |                   ->11.56% (21,108,472B) 0x178772: artwork_get_item (artwork.c:2032)
| | |                     ->11.56% (21,108,472B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| | |                       ->11.56% (21,108,472B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| | |                         ->11.56% (21,108,472B) 0x181646: execute (worker.c:91)
| | |                           ->11.56% (21,108,472B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| | |                             ->11.56% (21,108,472B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| | |                               ->11.56% (21,108,472B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |                                 ->11.56% (21,108,472B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |                                   ->11.56% (21,108,472B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| | |                                     ->11.56% (21,108,472B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| | |                                       ->11.56% (21,108,472B) 0x89B5A93: start_thread (pthread_create.c:447)
| | |                                         ->11.56% (21,108,472B) 0x8A42A33: clone (clone.S:100)
| | |                                           
| | ->00.00% (1,088B) in 1+ places, all below ms_print's threshold (01.00%)
| | 
| ->17.55% (32,050,862B) 0x608FF80: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| | ->17.12% (31,257,086B) 0x6090A2C: av_fast_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| | | ->17.12% (31,257,086B) 0x5300253: av_fast_padded_malloc (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   ->17.10% (31,228,819B) 0x4E160A9: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   | ->17.10% (31,228,819B) 0x51BE90E: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   | | ->17.10% (31,228,819B) 0x4E16529: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   | |   ->17.10% (31,228,819B) 0x4E168ED: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   | |     ->17.10% (31,228,819B) 0x4E16B8B: avcodec_send_frame (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | |   | |       ->17.10% (31,228,819B) 0x172D27: encode_write (transcode.c:803)
| | |   | |         ->17.10% (31,228,819B) 0x172D27: filter_encode_write (transcode.c:866)
| | |   | |           ->17.10% (31,228,819B) 0x172D27: filter_encode_write (transcode.c:838)
| | |   | |             ->17.10% (31,228,819B) 0x174BB2: transcode_encode (transcode.c:2289)
| | |   | |               ->17.10% (31,228,819B) 0x176079: artwork_get (artwork.c:742)
| | |   | |                 ->17.10% (31,228,819B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| | |   | |                   ->17.10% (31,228,819B) 0x175930: process_items (artwork.c:1886)
| | |   | |                     ->17.10% (31,228,819B) 0x176A84: process_group (artwork.c:1982)
| | |   | |                       ->17.10% (31,228,819B) 0x178772: artwork_get_item (artwork.c:2032)
| | |   | |                         ->17.10% (31,228,819B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| | |   | |                           ->17.10% (31,228,819B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| | |   | |                             ->17.10% (31,228,819B) 0x181646: execute (worker.c:91)
| | |   | |                               ->17.10% (31,228,819B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| | |   | |                                 ->17.10% (31,228,819B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| | |   | |                                   ->17.10% (31,228,819B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |   | |                                     ->17.10% (31,228,819B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |   | |                                       ->17.10% (31,228,819B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| | |   | |                                         ->17.10% (31,228,819B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| | |   | |                                           ->17.10% (31,228,819B) 0x89B5A93: start_thread (pthread_create.c:447)
| | |   | |                                             ->17.10% (31,228,819B) 0x8A42A33: clone (clone.S:100)
| | |   | |                                               
| | |   | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | |   | 
| | |   ->00.02% (28,267B) in 1+ places, all below ms_print's threshold (01.00%)
| | |   
| | ->00.43% (793,776B) in 1+ places, all below ms_print's threshold (01.00%)
| | 
| ->00.20% (357,485B) in 1+ places, all below ms_print's threshold (01.00%)
| 
->13.37% (24,412,160B) 0x7FFE962: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| ->13.36% (24,403,968B) 0x8000CF4: evbuffer_add (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | ->13.36% (24,403,968B) 0x1718C2: avio_evbuffer_write (transcode.c:1001)
| | | ->13.36% (24,403,968B) 0x48D008E: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |   ->13.36% (24,403,968B) 0x48D11CC: avio_write (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |     ->13.36% (24,403,968B) 0x4948DE6: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |       ->13.36% (24,403,968B) 0x49B614C: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |         ->13.36% (24,403,968B) 0x49B686A: ??? (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |           ->13.36% (24,403,968B) 0x49B8E9C: av_interleaved_write_frame (in /usr/lib/x86_64-linux-gnu/libavformat.so.60.16.100)
| | |             ->13.36% (24,403,968B) 0x172969: encode_write.part.0 (transcode.c:820)
| | |               ->13.36% (24,403,968B) 0x172D38: encode_write (transcode.c:804)
| | |                 ->13.36% (24,403,968B) 0x172D38: filter_encode_write (transcode.c:866)
| | |                   ->13.36% (24,403,968B) 0x172D38: filter_encode_write (transcode.c:838)
| | |                     ->13.36% (24,403,968B) 0x174BB2: transcode_encode (transcode.c:2289)
| | |                       ->13.36% (24,403,968B) 0x176079: artwork_get (artwork.c:742)
| | |                         ->13.36% (24,403,968B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| | |                           ->13.36% (24,403,968B) 0x175930: process_items (artwork.c:1886)
| | |                             ->13.36% (24,403,968B) 0x176A84: process_group (artwork.c:1982)
| | |                               ->13.36% (24,403,968B) 0x178772: artwork_get_item (artwork.c:2032)
| | |                                 ->13.36% (24,403,968B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| | |                                   ->13.36% (24,403,968B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| | |                                     ->13.36% (24,403,968B) 0x181646: execute (worker.c:91)
| | |                                       ->13.36% (24,403,968B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| | |                                         ->13.36% (24,403,968B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| | |                                           ->13.36% (24,403,968B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |                                             ->13.36% (24,403,968B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| | |                                               ->13.36% (24,403,968B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| | |                                                 ->13.36% (24,403,968B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| | |                                                   ->13.36% (24,403,968B) 0x89B5A93: start_thread (pthread_create.c:447)
| | |                                                     ->13.36% (24,403,968B) 0x8A42A33: clone (clone.S:100)
| | |                                                       
| | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
| | 
| ->00.00% (8,192B) in 1+ places, all below ms_print's threshold (01.00%)
| 
->13.30% (24,279,784B) 0x605A996: av_buffer_realloc (in /usr/lib/x86_64-linux-gnu/libavutil.so.58.29.100)
| ->13.29% (24,266,748B) 0x4E1619B: avcodec_default_get_encode_buffer (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| | ->13.29% (24,266,748B) 0x4E16270: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| |   ->13.29% (24,266,748B) 0x4E165A8: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| |     ->13.29% (24,266,748B) 0x4E168ED: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| |       ->13.29% (24,266,748B) 0x4E16B8B: avcodec_send_frame (in /usr/lib/x86_64-linux-gnu/libavcodec.so.60.31.102)
| |         ->13.29% (24,266,748B) 0x172D27: encode_write (transcode.c:803)
| |           ->13.29% (24,266,748B) 0x172D27: filter_encode_write (transcode.c:866)
| |             ->13.29% (24,266,748B) 0x172D27: filter_encode_write (transcode.c:838)
| |               ->13.29% (24,266,748B) 0x174BB2: transcode_encode (transcode.c:2289)
| |                 ->13.29% (24,266,748B) 0x176079: artwork_get (artwork.c:742)
| |                   ->13.29% (24,266,748B) 0x1764C6: source_item_embedded_get (artwork.c:1532)
| |                     ->13.29% (24,266,748B) 0x175930: process_items (artwork.c:1886)
| |                       ->13.29% (24,266,748B) 0x176A84: process_group (artwork.c:1982)
| |                         ->13.29% (24,266,748B) 0x178772: artwork_get_item (artwork.c:2032)
| |                           ->13.29% (24,266,748B) 0x15A416: daap_reply_extra_data (httpd_daap.c:1989)
| |                             ->13.29% (24,266,748B) 0x15C3A8: daap_request (httpd_daap.c:2278)
| |                               ->13.29% (24,266,748B) 0x181646: execute (worker.c:91)
| |                                 ->13.29% (24,266,748B) 0x1A5B0B: _evthr_read_cmd (evthr.c:114)
| |                                   ->13.29% (24,266,748B) 0x1A5B0B: _evthr_read_cmd (evthr.c:98)
| |                                     ->13.29% (24,266,748B) 0x8010B3B: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| |                                       ->13.29% (24,266,748B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
| |                                         ->13.29% (24,266,748B) 0x1A5A2B: _evthr_loop (evthr.c:159)
| |                                           ->13.29% (24,266,748B) 0x1A5A2B: _evthr_loop (evthr.c:126)
| |                                             ->13.29% (24,266,748B) 0x89B5A93: start_thread (pthread_create.c:447)
| |                                               ->13.29% (24,266,748B) 0x8A42A33: clone (clone.S:100)
| |                                                 
| ->00.01% (13,036B) in 1+ places, all below ms_print's threshold (01.00%)
| 
->04.38% (8,007,416B) 0x85BEABA: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
| ->04.38% (8,007,416B) 0x85C3C55: sqlite3Malloc (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   ->03.34% (6,093,896B) 0x85D5AEB: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | ->02.01% (3,667,088B) 0x85D66A4: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | ->02.01% (3,667,088B) 0x85D084C: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |   ->02.01% (3,667,088B) 0x8541B98: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     ->01.01% (1,846,672B) 0x8542FD2: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     | ->01.01% (1,846,672B) 0x854A098: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     |   ->01.01% (1,846,672B) 0x854DE30: sqlite3BtreeInsert (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     |   | ->01.01% (1,846,672B) 0x8610C55: sqlite3VdbeExec (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     |   | | ->01.01% (1,846,672B) 0x8617660: sqlite3_step (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | |     |   | |   ->01.01% (1,846,672B) 0x14473B: cache_artwork_add_impl (cache.c:1500)
|   | |     |   | |     ->01.01% (1,846,672B) 0x1B3064: command_cb_sync (commands.c:85)
|   | |     |   | |       ->01.01% (1,846,672B) 0x1B3064: command_cb (commands.c:142)
|   | |     |   | |         ->01.01% (1,846,672B) 0x8010A57: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
|   | |     |   | |           ->01.01% (1,846,672B) 0x801248E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.7.0.1)
|   | |     |   | |             ->01.01% (1,846,672B) 0x1463B3: cache (cache.c:1722)
|   | |     |   | |               ->01.01% (1,846,672B) 0x89B5A93: start_thread (pthread_create.c:447)
|   | |     |   | |                 ->01.01% (1,846,672B) 0x8A42A33: clone (clone.S:100)
|   | |     |   | |                   
|   | |     |   | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
|   | |     |   | 
|   | |     |   ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
|   | |     |   
|   | |     ->01.00% (1,820,416B) in 1+ places, all below ms_print's threshold (01.00%)
|   | |     
|   | ->01.31% (2,398,048B) 0x85D6560: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | ->01.11% (2,021,712B) 0x85D084C: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | | ->01.11% (2,021,712B) 0x85421D0: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | |   ->01.11% (2,021,712B) 0x854846B: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | |     ->01.10% (2,017,336B) 0x854851D: ??? (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | |     | ->01.10% (2,017,336B) 0x8612857: sqlite3VdbeExec (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | |     |   ->01.10% (2,017,336B) 0x8617660: sqlite3_step (in /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6)
|   | | |     |     ->01.10% (2,017,336B) 0x136B5E: db_blocking_step (db.c:1491)
|   | | |     |     | ->01.10% (2,017,336B) 0x136B5E: db_get_one_int (db.c:1878)
|   | | |     |     |   ->01.10% (2,017,336B) 0x136C8E: db_build_query_check (db.c:2058)
|   | | |     |     |     ->01.10% (2,017,336B) 0x13AD0A: db_build_query_group_artists (db.c:2271)
|   | | |     |     |       ->01.10% (2,017,336B) 0x13AD0A: db_query_start (db.c:2410)
|   | | |     |     |         ->01.10% (2,017,336B) 0x18509C: pipelist_create (pipe.c:978)
|   | | |     |     |           ->01.10% (2,017,336B) 0x1851AF: pipe_listener_cb (pipe.c:1010)
|   | | |     |     |             ->01.10% (2,017,336B) 0x185386: init (pipe.c:1149)
|   | | |     |     |               ->01.10% (2,017,336B) 0x182DFF: input_init (input.c:916)
|   | | |     |     |                 ->01.10% (2,017,336B) 0x181354: player_init (player.c:3902)
|   | | |     |     |                   ->01.10% (2,017,336B) 0x133BE9: main (main.c:792)
|   | | |     |     |                     
... yada yada ...

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 10, 2024

Thanks for testing, pretty interesting. It confirms that there is no memory leak, so that's good to get confirmed. Memory consumption peaks at 182MB, which is pretty high, but strangely still quite far from the 2G you had to set as max. The report below shows the allocation. It confirms that it's the artwork processing that's using it.

Interesting findings. Regarding the memory usage, I just checked my main OwnTone server and it’s currently using 1.8G according to systemd:

$ sudo systemctl status owntone
● owntone.service - DAAP/DACP (iTunes), RSP and MPD server, supports AirPlay and Remote
     Loaded: loaded (/etc/systemd/system/owntone.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/owntone.service.d
             └─override.conf
     Active: active (running) since Thu 2024-11-07 06:30:11 CET; 3 days ago
       Docs: man:owntone(8)
   Main PID: 207666 (owntone)
      Tasks: 18 (limit: 9394)
     Memory: 1.8G (max: 2.0G swap max: 32.0M available: 119.8M)
        CPU: 5h 35min 44.266s
     CGroup: /system.slice/owntone.service
             └─207666 /usr/sbin/owntone -f

Seeing that it was started at 6:30 in the morning didn’t make sense to me—I clearly did not do that myself. So I checked the logs and saw that it was in fact restarted because it exceeded the 2G:

Nov 07 06:30:06 homeserver systemd[1]: owntone.service: A process of this unit has been killed by the OOM killer.
Nov 07 06:30:06 homeserver systemd[1]: owntone.service: Main process exited, code=killed, status=9/KILL
Nov 07 06:30:06 homeserver systemd[1]: owntone.service: Failed with result 'oom-kill'.
Nov 07 06:30:06 homeserver systemd[1]: owntone.service: Consumed 1h 20min 59.279s CPU time.
Nov 07 06:30:11 homeserver systemd[1]: owntone.service: Scheduled restart job, restart counter is at 2.
Nov 07 06:30:11 homeserver systemd[1]: Stopped DAAP/DACP (iTunes), RSP and MPD server, supports AirPlay and Remote.

I did not rescan the library on the main server with Apple Music within in the past 3 days. So I’m suspecting that there’s another cause for the high memory consumption. Usually, I don’t use Apple Music to listen to music at all, and instead control OwnTone via Home Assistant or the iTunes Remote app on iOS (and have OwnTone stream to multiple AirPlay speakers in the house). While the artwork generation may have room for optimization according to the report, it might not be the issue for the excessive memory consumption. Would it help to start the OwnTone with the valgrind command and leave it running for hours/days while I’m using it like I normally do?

The report also indicates that only some of the artwork requests are memory heavy, so I think I will try to make a version of OwnTone with special logging/handling of those requests. So that would be the next thing I would ask you to test.

Yes, happy to test this!

As I recall, when Apple Music loads the library the first time, it requests artwork for every single track in your library. That's of course wildly ineffective for a 100k library. But I can't do much about that.

Yes, it does that, but it’s not a big issue since browsing and playback works while it’s still fetching the artworks.

@ejurgensen
Copy link
Member

So I’m suspecting that there’s another cause for the high memory consumption

Yes, I agree. There's a big step from the artwork 200MB to that 2GB limit.

Would it help to start the OwnTone with the valgrind command and leave it running for hours/days while I’m using it like I normally do?

Yes, if you can live with the poor performance. If Valgrind/massif could say what's eating those GB's it would be a breakthrough.

But before you try that, I thought of a simple test you could try, which is to just disable caching by changing the config setting cache_daap_threshold to 0. Remember to also uncomment the line. As far as I can tell, this should disable all caching, including artwork caching. It would be interesting to see if this has a drastic effect on memory consumption.

When you make this test, I suggest you temporarily also set the cache_dir setting to some empty dir. You can then check that OwnTone is not creating any .db files in that dir, which verifies that caching was indeed disabled.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 11, 2024

I’ve set cache_dir to /var/owntone_test and cache_daap_threshold = 0. /var/owntone_test remained in fact empty.

Once library scanning and Spotify scanning had completed, the memory usage was at ~25 MB. This matches the value I get with caching enabled.

I then started playback on a large playlist via the iTunes Remote app. Memory usage got to ~50 MB, which is also not significantly different from the value I see when cache is enabled. So I will leave it running over the next hours (or days) to see if the RAM usage increases over time (with cache disabled).

By the way, the documentation still includes the deprecated cache_path setting. PR here: #1824

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 11, 2024

Quick update: After 1.5h, it grew to 180 MB.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 12, 2024

More numbers:

10h — 262M
12h — 292M
21h — 968M

I’ll restart OwnTone with valgrind now, hoping to collect some useful insights.

@ejurgensen
Copy link
Member

Interesting. Growing numbers indicate a memleak so maybe I was wrong to exclude that. Will be very good to see what Valgrind/massif says.

@aaronk6
Copy link
Contributor Author

aaronk6 commented Nov 14, 2024

After restarting OwnTone with valgrind yesterday, memory consumption didn’t grow excessively. I’m a bit puzzled what’s different now, but I’ll anyway attach the massif file. When I just stopped the process, the memory usage was at 213M (after 20h runtime). So clearly not what I was seeing in my previous test where it was at 968M after 21h.

owntone2_cache_disabled.massif.zip

I’ll give it another go with caching enabled (even though my test from Nov 12 had caching disabled).

When I get a chance next week, I’ll also see if I can pinpoint certain usage patterns that drive up memory consumption.

@ejurgensen
Copy link
Member

Yes, quite strange. The massif report is just showing 10-20MB mem usage at the end, ref the below. I wonder how that translates to those 213MB. Guess there is something I don't understand about memory statistics.

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 81 3,411,922,490,496        9,981,536        9,403,646       577,890            0
 82 3,415,946,579,086        9,930,472        9,352,553       577,919            0
 83 3,419,970,704,452       10,036,352        9,458,085       578,267            0
 84 3,423,994,790,603       10,144,928        9,566,186       578,742            0
 85 3,428,018,974,746        9,992,048        9,413,356       578,692            0
 86 3,432,043,163,711       10,109,584        9,531,460       578,124            0
 87 3,436,067,249,475        9,934,376        9,355,279       579,097            0
 88 3,440,772,093,652        5,345,672        5,000,165       345,507            0
 89 3,447,103,584,769        5,345,720        5,000,221       345,499            0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants