Alleviating Memory Pressure on Toshiba AC100

After all the upgrades and tweaks to the AC100 (screen upgrade to 1280×720, cooling improvements and boosting the clock speed by over 40%), only one significant issue remains: it only has 512MB of RAM. Unfortunately, the memory controller initialization is done by the closed-source boot loader, so even if we were to solder in bigger chips (Tegra2 can handle up to 1GB of RAM), it is unlikely in the extreme that it would just work.

So, other than increasing the physical amount of memory, can we actually do anything to improve the situation? Well, as a matter of fact, there are a few things.

Clawing Back Some Memory

By default, the GPU gets allocated a hefty 64MB of RAM out of 512MB that we have. This is quite a substantial fraction of our memory, and it would be nice to claw some of it back if we are not using it. I find the Nvidia’s Tegra binary accelerated driver to be too buggy to use under normal circumstances, so I use the basic unaccelerated frame buffer driver instead. There are two frame buffer allocations on the AC100: the internal display and the HDMI port. The latter is only intended for use with TVs which means we shouldn’t need a resulition of more than 1920×1080 on that port. The highest resolution display we can have on the internal port is 1280×720. That means that the maximum amount of memory used by those two frame buffers is 8100KB + 3600KB 11700KB. To be on the safe side, let’s call that 16MB. That still leaves us 48MB that we should be able to safely reclaim. We can do that by telling the kernel that there is extra memory at certain addresses using the following boot parameters:

mem=448M@0M mem=48M@464M

Make sure the accelerated binary Tegra driver is disabled in your xorg.conf, reboot and you should now have 496MB of usable RAM instead of 448MB. It’s just over an extra 10%, which should make a noticeable difference given how tight the memory is to begin with.

If you aren’t using the HDMI interface, my tests show that it is in fact possible to reduce the GPU memory to just 2MB with no ill effects, when using the 1280×720 display panel, because the frame buffer seems to operate in 16-bit mode by default:

mem=448M@0M mem=62M@450M

That leaves a total of 510MB of for applications.

Memory Compression

In the recent kernels, there are two modules that are very useful when we have plenty of CPU resources but very little memory – just the case on the AC100. They are zcache and zram. On the 3.0 kernels instead of zram we can use frontcache which is similar but has the advantage that it is aware and cooperates with zcache. Since at the time of writing this 3.0 isn’t quite as polished and stable for the AC100 as 2.6.38, let’s focus on zram instead.

Assuming you have compiled zcache support into your kernel, all you need to do to enable it is add the kernel boot paramter “zcache”. From there on, your caches should be compressed, thus increasing the amount they can store.

zram provides a virtual block device backed by RAM, but the contents are compressed, so it should always end up using less than the amount of memory it presents as a block device (unless all of the data is uncompressible, which is very unlikely). To err on the side of caution we shouldn’t set this to more than half of the total memory across all the zram devices. To ensure optimal performance, we should also set the number of zram devices to be the same as the number of CPUs cores in the system to make sure that all CPUs end up being used (each zram device handler is a single thread).

To set the number of zram devices to 2 (Tegra2 has 2 CPU cores), we need to create the file /etc/modprobe.d/zram.conf containing the following line:

options zram num_devices=2

Then once we load the zram module (modprobe zram), we should see device nodes called /dev/zram*. We can configure the devices:

echo <memory_size_in_bytes> > /sys/block/<zram_device>/disksize

The amount of memory assigned to each zram device should be such that their total combined size doesn’t exceed half of the total physical memory in the system.

Then we can create swap headers on those zram devices using mkswap (e.g. mkswap /dev/zram0) and enable swapping to them (swapon -p100 /dev/zram0).

We should now have some compressed RAM for swapping to instead of swapping to a slow SD card.

Tweaks

It turns out that some of the default settings on Linux distributions aren’t as sensible as they could be. By default the amount of stack space each thread is allocated is 8MB. This is unnecessarily large and results in more memory consumption than is necessary. Instead we can set the soft limit to 256KB using “ulimit -s 256”. Ideally we should make this happen automatically at startup by creating a file /etc/security/limits.d/90-stack.conf containing the following:

* soft stack 256

Some users have reported that this can increase the amount of available memory after booting by a a rather substantial amount. Since this is a soft limit, programs that require more stack space can still allocate it by asking for it.

Choice of Software

One of the most commonly used types of software nowdays is a web browser, and unfortunately, most web browsers have become unreasonably bloated in recent years. This is a problem when the amount of memory is as limited as in it is on most ARM machines. Firefox and to a somewhat lesser extent Chrome require a substantial amount of memory. However, there is another reasonably fully featured alternative that works on ARM – Midori. Midori is based on the Webkit rendering engine, the same one that is used by Chrome and Safari. However, it’s memory footprint is approximately half of the other browsers. Unfortunately, it’s JavaScript support isn’t quite as good as on Firefox and Chrome yet, but it is sufficiently good for most things, and if memory pressure is a serious issue, you might want to try it out.

11 replies
  1. donc_oe
    donc_oe says:

    hi gordan,
    you blog is awesome for ac100 users. thanks for that and keep it going, pls 🙂
    anyways, i’ve never been looking into my ac100. do you think it is possible to replace the RAM by some better modules? 1G for example?
    cheers,
    donc_qh-

    • gordan
      gordan says:

      Theoretically? Yes. Tegra2 can address up to 1GB of RAM.

      Realistically? No – because we don’t have the boot loader source code or enough published spec. You would have to modify the boot loader to initialize the memory controller appropriately for the bigger chips.

  2. Marc
    Marc says:

    Congratulation Gordon for your ultra cool modifide linux smartbook ;o)

    Did you do some benchmarking with the different overclocking states? How long is the livetime of the battery now? Is there a movie on youtube with your new display? Is the new diplay glossy or mate? Is flash running with all your improvements?

    • gordan
      gordan says:

      Thank you. 🙂

      Performance wise, CPU heavy things scale completely linearly. For example, compression and encryption go 40% faster at 1400Mhz than at 1000MHz.

      I use the ondemand CPU frequency scaler and haven’t found the battery life to have been obviously affected since unless you are running a long CPU intensive task, the CPU will sleep most of the time anyway.

      Sorry, no video is available, but if you look at the last image on the AC100 screen upgrade post (and read the paragraphs around it), it should give you a reasonable idea of the increase in pixel count.

      The display I used is matte, but glossy ones are also available if that is your preference (same model number).

      Flash works fine if you use the nvidia binary Xorg driver (which means you cannot use the above hack to claw back the frame buffer memory). However, I find the nvidia driver to be very buggy, so I use the frame buffer, which also gives me an extra 62MB of RAM.

  3. David Given
    David Given says:

    Trying the memory recovery options on my 10U causes it to become unbootable — it never even gets past the Toshiba splash screen. (Either option.) This makes me think that the memory layout on the 10U is different to yours.

    I’m using armhf and the framebuffer driver, FWIW, but I don’t think it’s getting as far as starting the kernel let alone userland and X.

    • gordan
      gordan says:

      Hmm, that is quite odd because I have 6x AC100-10U (both Hynix and Micron variants) and 1x AC100-10Z here and it works on all of them.

      I am running 2.6.38 soft-float kernel.

      Can you post your full kernel parameter line and kernel version?

      If you just use parameter mem=448M@0M (without the second mem=) does that work OK?

    • Amyako
      Amyako says:

      mem=500M@0M nvmem=12M@500M

      at least with 3.0.8 it works on 116/117

      cat /proc/meminfo | grep MemTotal
      MemTotal: 499572 kB

      • gordan
        gordan says:

        That’s interesting, so 3.0.8 and 2.6.38 map the frame buffer to a different region of memory. What happens if you remove nvmem parameter ? AFAICT that prameter is no longer used in 2.6.38. Is it back in 3.0.x?

          • gordan
            gordan says:

            Right, so nvmem isn’t being used in 3.0, either. Good, it’s been removed since beforen 2.6.38.

            It is interesting, though, that with 3.0.x the frame buffer is mapped at the top of the memory rather than at the bottom of the top 64MB.

          • Stefan
            Stefan says:

            To increase the confusion even more:
            using a 3.0.19 hardfp kernel, the fb memory seems to be mapped on top of 448M. This causes the 500M@0M to be not usable for me.

Comments are closed.