[Tremor] Implementing Tremor on low-end ARM

Nicholas Vinen hb at x256.org
Sun Nov 23 05:57:34 PST 2008


OK.. I am sort of answering my own question here, which is kind of
silly, but at the same time somewhat valuable.

I took the time to stick in some logging to the Tremor low memory
branch's heap functions. This is the result for playing back a 44kHz 16
bit VBR file. The left hand column is the sum of all allocations (no
subtractions for free, but as it turns out it doesn't matter).

[    28] calloc(28) => 0x8064008  
[    44] calloc(16) => 0x8064028
[   120] calloc(76) => 0x8064040 
[   136] malloc(16) => 0x8064090 
[  1160] malloc(1024) => 0x80640a8
[  1176] malloc(16) => 0x80644b0
[  1192] malloc(16) => 0x80644c8 
[  1208] malloc(16) => 0x80644e0
[  1260] calloc(52) => 0x80644f8
[  1276] malloc(16) => 0x8064530 
[  2300] malloc(1024) => 0x8064548
[  2316] malloc(16) => 0x8064950
[  3340] malloc(1024) => 0x8064968
[  3356] malloc(16) => 0x8064d70
[  4380] malloc(1024) => 0x8064d88
[  4396] malloc(16) => 0x8065190  
[  4412] malloc(16) => 0x80651a8 
[  4428] malloc(16) => 0x80651c0  
[  4444] malloc(16) => 0x80651d8  
[  4474] calloc(30) => 0x80651f0  
[  4494] calloc(20) => 0x8065218  
[  4514] calloc(20) => 0x8065230 
[  4526] calloc(12) => 0x8065248  
[  4538] calloc(12) => 0x8065258
[  4566] calloc(28) => 0x8065268 
[  4581] calloc(15) => 0x8065288
[  7397] calloc(2816) => 0x80652a0
[  7411] malloc(14) => 0x8065da8 
[  7537] malloc(126) => 0x8065dc0
[  7663] malloc(126) => 0x8065e48
[  8171] malloc(508) => 0x8065ed0 
[  8233] malloc(62) => 0x80660d0 
[  8613] malloc(380) => 0x8066118
[  8645] malloc(32) => 0x8066298 
[  8707] malloc(62) => 0x80662c0 
[  9015] malloc(308) => 0x8066308
[  9047] malloc(32) => 0x8066440
[  9109] malloc(62) => 0x8066468 
[  9417] malloc(308) => 0x80664b0
[  9447] malloc(30) => 0x80665e8 
[  9461] malloc(14) => 0x8066610  
[ 10481] malloc(1020) => 0x8066628
[ 10607] malloc(126) => 0x8066a28
[ 11115] malloc(508) => 0x8066ab0
[ 11177] malloc(62) => 0x8066cb0 
[ 11557] malloc(380) => 0x8066cf8
[ 11619] malloc(62) => 0x8066e78
[ 11999] malloc(380) => 0x8066ec0
[ 12031] malloc(32) => 0x8067040
[ 12093] malloc(62) => 0x8067068
[ 12401] malloc(308) => 0x80670b0
[ 12433] malloc(32) => 0x80671e8
[ 12495] malloc(62) => 0x8067210
[ 12803] malloc(308) => 0x8067258
[ 13001] malloc(198) => 0x8067390
[ 13193] malloc(192) => 0x8067460
[ 14633] malloc(1440) => 0x8067528
[ 14833] malloc(200) => 0x8067ad0
[ 15361] malloc(528) => 0x8067ba0
[ 15681] malloc(320) => 0x8067db8
[ 16161] malloc(480) => 0x8067f00
[ 16505] malloc(344) => 0x80680e8
[ 16553] malloc(48) => 0x8068248
[ 17225] malloc(672) => 0x8068280
[ 17705] malloc(480) => 0x8068528
[ 18601] malloc(896) => 0x8068710
[ 20361] malloc(1760) => 0x8068a98
[ 21033] malloc(672) => 0x8069180
[ 21705] malloc(672) => 0x8069428
[ 21801] malloc(96) => 0x80696d0
[ 21999] malloc(198) => 0x8069738
[ 22007] malloc(8) => 0x8069808
[ 22009] malloc(2) => 0x8069818
[ 22045] calloc(36) => 0x8069828
[ 22051] malloc(6) => 0x8069850
[ 22095] malloc(44) => 0x8069860
[ 22133] malloc(38) => 0x8069890
[ 22152] malloc(19) => 0x80698c0
[ 22169] malloc(17) => 0x80698d8
[ 22186] malloc(17) => 0x80698f0
[ 22205] malloc(19) => 0x8069908
[ 22205] free(0x8069908)
[ 22241] calloc(36) => 0x8069908
[ 22249] malloc(8) => 0x8069930 
[ 22304] malloc(55) => 0x8069940
[ 22362] malloc(58) => 0x8069980
[ 22391] malloc(29) => 0x80699c0
[ 22418] malloc(27) => 0x80699e8
[ 22445] malloc(27) => 0x8069a08  
[ 22474] malloc(29) => 0x8069a28  
[ 22474] free(0x8069a28)
[ 22530] malloc(56) => 0x8069a28  
[ 22540] malloc(10) => 0x8069a68
[ 22620] malloc(80) => 0x8069a78  
[ 22630] malloc(10) => 0x8069ad0
[ 22710] malloc(80) => 0x8069ae0
[ 22750] malloc(40) => 0x8069b38
[ 22752] malloc(2) => 0x8069b68
[ 22754] malloc(2) => 0x8069b78
[ 22756] malloc(2) => 0x8069b88
[ 22758] malloc(2) => 0x8069b98
[ 22762] malloc(4) => 0x8069ba8
[ 22778] malloc(16) => 0x8069bb8
[ 22782] malloc(4) => 0x8069bd0
[ 22790] malloc(8) => 0x8069be0
[ 22806] malloc(16) => 0x8069bf0
[ 22822] malloc(16) => 0x8069c08
[ 23846] malloc(1024) => 0x8069c20
[ 23862] malloc(16) => 0x806a028
[ 23938] calloc(76) => 0x806a040
[ 23938] free(0x806a040)
[ 24014] calloc(76) => 0x806a040
[ 24022] malloc(8) => 0x806a090
[ 24030] malloc(8) => 0x806a0a0
[ 28126] calloc(4096) => 0x806a0b0
[ 30174] calloc(2048) => 0x806b0b8
[ 34270] calloc(4096) => 0x806b8c0
[ 36318] calloc(2048) => 0x806c8c8
[ 36334] malloc(16) => 0x806d0d0
[ 37358] malloc(1024) => 0x806d0e8
[ 37374] malloc(16) => 0x806d4f0
[ 37390] malloc(16) => 0x806d508

So, this is good news. Less than 38KB, including at least one (and by
the looks of it, quite a few) buffers. That should give me plenty of
remaining RAM for the rest of the functions :)

So, it's interesting that although realloc is defined, and there are
instances of it in the code, it doesn't seem to be called under these
circumstances. Possibly because I only played one file.

So, this is my plan: I will statically allocate these memory blocks. I
expect in some cases, certain files will require larger blocks, so I
will identify those cases and preallocate enough for any reasonable
case. I guess I will have to add error returns if these limits exceeded.
Then, I will simply replace malloc() with a function which returns one
of the static buffers - which will be determined by the size, and the
order in which they are asked for. In the few cases where the buffer is
freed, I can store a bit which indicates whether it's in use and just
re-use it. Since 98%+ of the memory is not freed until after playback
finishes, this is not a big deal.

The only reason I think that such a scheme would fail would be if two
different files could result in vastly different sizes of blocks being
allocated. However, since my player will only support a limited range of
formats anyway (probably just 16 bit mono and stereo, 22kHz - 48kHz), I
should be able to determine the worst cases and allocate accordingly.

I can't really think of the advantage of dynamically allocating in this
situation, and I would think this situation is fairly common with
embedded devices, especially those dedicated to audio playback. Since I
need to have enough memory free to play back any reasonable file, why
not just reserve it from the beginning and keep it reserved? Perhaps a
patch to do this would have some popularity as it removes the
requirement to have any heap management.

Any thoughts along these lines would be appreciated.


- Nicholas


P.S. I realize that Ogg files can contain various kinds of metadata
blocks but in my application I think other than author/title/etc. I can
just skip them, and this should make memory management a bit easier.



Nicholas Vinen wrote:
> Hi,
>
> I am implementing an open hardware/software portable Ogg player. From
> the messages I have read in the archive for this mailing list, the CPU I
> have chosen should be sufficient:
>
> AT91SAM7S (ARM7) : 55MHz, 64kB single cycle RAM, 256kB flash.
>
> I believe it will take around 40kB of the RAM. Including decoding
> buffers (it will need to be double buffered), 48kB is fine. My file
> system code is under 8kB, and that will leave 8kB for display/user
> interface/misc.
>
> If necessary I think it would be possible to store some tables in flash
> and read them out directly.
>
> Is this correct?
>
> I've been looking through the Tremor code and I notice that it uses
> dynamic memory allocation. Since I only need to be able to decode one
> file at a time, I imagine I should be able to use (mostly) static
> allocation. Has anybody done this before?
>
> Also, since the chip won't be running any kind of operating system, I'm
> tempted to remove calls to most C library functions (fread, fseek,
> ftell, fwrite, fprintf, malloc, realloc, free). The file operations just
> seem to be some defaults in helper functions so I imagine I can just
> remove them. Changing to static allocation wherever possible should
> reduce/eliminate the calls to memory allocation. I suppose I could get a
> heap implementation from somewhere and point it to all the spare memory.
> If someone can comment as to whether this is a good idea vs. statically
> allocating, please let me know.
>
>
>
> Thanks,
>
> Nicholas.
>
> _______________________________________________
> Tremor mailing list
> Tremor at xiph.org
> http://lists.xiph.org/mailman/listinfo/tremor
>   



More information about the Tremor mailing list