Debugging random lagging on Android

My Samsung tablet with Android (4.4.2, rooted) has been experiencing random lagging for a while. This affects me most when I’m playing games on it. Earlier today I finally decided to find the root of the problem.

Finding the cause

The ultimate solution is to know which application is causing the lag and disable it. I first went to Settings > General > Developer Options (If you don’t have it, go to Settings > General > About phone/device and tap “Build number” 7+ times to enable it), and ticked “Show CPU usage”. Then you would see an overlay on the top-right corner of your device showing the top (like the Linux command) processes, similar to the image below.

Then I used my device to play games, and wait for the random lagging to happen. When the device start to response slowly, I watched the CPU usage overlay and see “gzip” topping the list. If you are not familiar with Linux, gzip is a compression tool similar to RAR or 7-Zip.

Wrapping (first attempt)

I was expecting some Android application to cause the lagging, instead it’s a command gzip that can be called by anyone. The problem became finding out who called it. Since my device is rooted, I decided to replace the original gzip binary with a wrapper that can log who called it before actually gzipping. Here is the wrapping bash script I used (first version, read on for second version):

The script does the following: (1) Log the time, user ID (the $EUID variable turns out to be useless, but id worked) and command line parameters to $LOGFILE (a plain text file in the internal storage); then (2) hand over the control to real gzip so that it doesn’t break the gzip functionality.

Then I used Root Explorer to rename /system/bin/gzip to /system/bin/gzip.real, and put my script to /system/bin/gzip (remember to modify the permission to be the same as gzip.real, usually 0755).

After using the device for a while and several lagging happened, I read the logging file and got these lines:

Observe that id produced “uid=2000(shell) gid=2000(shell) ...” and the command called is “gzip -6“. This means gzip was called by the shell user, not a specific application, and the data to be compressed was piped in to gzip and then piped out, since there are no input or output file names. (Spoiler: Actually this has shown “context=u:r:dumpstate:s0” which indicated that it was called by “dumpstate“, but I didn’t realize for the first time.)

Wrapping (second attempt)

Then I decided to take the surveillance up a level, and used the following wrapper in place of the first version:

The difference between it and the previous one is that, it uses Busybox’s “pstree” command to output the process tree of that moment, and “tee” command to record the data piped in and pipe it out again. In order for this to work, I downloaded busybox-armv7l binary (my device has ARMv7 architecture) from the official website and put it to /system/bin/busybox0 with the same permission as gzip.real. You can also use Busybox installer apps and modify the busybox path accordingly.

After a while, I got the following log this time:

Observe that [8691] is the gzip wrapper’s PID, and it’s called by “dumpstate“, which is then called by “debuggerd“. The wrapper also logged the data to be compressed, which is 5 MB long and takes 0.14s to be compressed on my PC instead of a poor mobile device.

Final solution

A quick Google told me this is for developers to debug the system state, and since I’m not a developer in this area, I decided to disable it once for all. This is done by using Root Explorer to revoke the execute permissions from the two binaries /system/bin/{debuggerd,dumpstate}.

Now the lagging is gone.

Use yumdb command with DNF to list explicitly installed packages

Since Fedora 22, DNF has replaced Yum as the default package manager. But not all yum commands have been migrated.

Today I felt like querying what packages I installed explicitly, and a quick Google told me to use yumdb search reason user, but it returned nothing.

I dug into the cause, and it turns out DNF now has its own yumdb (the database, not the command, sadly) at “/var/lib/dnf/yumdb”, along with yum’s “/var/lib/yum/yumdb”, and the command yumdb uses the latter by default.

In the man page of yum.conf, it says the “persistdir” value controls the path of yum’s db files, and it defaults to “/var/lib/yum”; but, yumdb --help tells me that it allows me to specify the location of config file. (Cheering for not touching /etc/yum.conf)

So, here’s what I did:

  1. Create a new fake config file with persistdir set to DNF’s folder.
  2. Calls yumdb with that config file.

Voila.

使用 systemd 的系统关机或重启时,自动执行特定命令

Arch Linux 这种比较潮的系统,已经迁移到了 systemd 这个管理器。这篇文章介绍如何在系统关机或重启时,自动执行特定命令。当然开机时自动启动服务也是一样的道理。

Manpage of Systemd

systemd 是一种系统和服务管理程序,与 Ubuntu 下的 upstart 类似,都是用来替代原始 BSD 或 System V 风格的 init 程序,实现在开机、不同的启动级别以及关机和重启时,执行相应的命令,启动或停止相应的服务。

1. 首先,我们要创建自己的 .service 服务文件。创建 /etc/systemd/system/xiaodu.service 内容如下:(点击下载

其中,ExecStart= 后面替换为自己要执行的命令。我这里是为了在关机或重启前,卸载 bbswitch 模块,以便正常关机。

2. 按照需求将该服务文件链接到特定的位置。例如需要在关机之前执行,则:

# ln -s /etc/systemd/system/xiaodu.service /usr/lib/systemd/system/shutdown.target.wants/

这里的 shutdown.target 指的是关机前需要执行,同样也会在重启之前执行。如果只需在重启之前执行,则需要链接到 reboot.target.wants (可能需要创建该文件夹)。

由于在编写 .service 文件的时候,没有写 [Install] 段落,因此不能直接通过 # systemctl enable xiaodu.service 来启用,只能手动链接。更多信息可以参考 systemd.service 的手册页。

3. 要测试是否生效,可以尝试“启动”该服务 # systemctl start xiaodu.service ,也可以直接关机或重启来检查。

Compiling Custom Linux Kernel With PAE And PF-Patch On Arch Linux

The x86 Linux kernel in the official Arch Linux repository oddly doesn’t have PAE enabled by default. So I decided to compile my own with PAE as well as -pf patch set.

WARNING: Compiling and installing your own kernel can / will take VERY LOOOONG and be DANGEROUS. There are pre-compiled PAE kernels available as well as -pf ones, if that’s only what you want. If you are a regular user who don’t want to take that risk, or even don’t know what Linux kernel is, just follow these links and enjoy your life.

So you still decided to do it manually, huh? Very brave and good choice. So let’s begin.

First let me introduce the kernel we’re going to compile. PAE (Physical Address Extension) makes it possible to use as many as 64GB of physical RAM with 32-bit kernel. PF patch set includes “-ck” patch set, BFS scheduler, BFQ I/O sched, TuxOnIce feature and UKSM patch (the last one comes from China).

1) Get PKGBUILD for “linux-pf” package from AUR. Use yaourt or download here then $ makepkg.

We can also (optionally) edit the PKGBUILD before really start using it. You can change the URL to download Linux kernel, for example to a local mirror. That’ll save you some time. Change the first line of “source” as you want and save.

2) Start compiling and building package.

 — 2.a Choosing base config:

        First you will be asked whether to use “your running kernel’s config”, “make localmodconfig” or “build an all-inclusive kernel like stock -ARCH“.

The second choice should be used with caution, because it means that you only compile the drivers you loaded now, and if you add a new device later (even a USB mouse you don’t use now), it will NOT get recognized and run by your custom kernel.

Here I recommend the last choice, though it’ll take longer than the second, it’s the best choice for most people.

— 2.b Manually config:

  Since the default config for “linux-pf” still comes with PAE (CONFIG_HIGHMEM64G) disabled, we need to alter that choice. Here we can use “make menuconfig” (you can also use GUI-based ones), and change “Process type and features” — “High Memory Support” to the 64G choice. (You can also manually modify “.config” file and change “CONFIG_HIGHMEM64G” to “y”.)

 — 2.c Wait for compiling.

If it’s not too late to say it now (which it definitely is, ha~ha), you can change “/etc/makepkg.conf” (before you start the whole thing) and make the compiling multithreaded (useful for systems with Dual/Quad core CPUs). Read the docs for how.

3) Install the compiled kernel.

There should be two packages, for kernel and its headers. After installiation, (backup your grub.cfg and) # mkinitcpio -p linux-pf , # grub-mkconfig -o /boot/grub/grub.cfg , then restart the computer to use the new kernel.


This is the first time I post here in English. Hope it is English anyway.

Linux 下 GNOME 声音设置里只有“假输出”

这几天换用 Arch Linux 之后遇到两次了,今天终于找到了解决方法。

在网上查了相关资料,在中文社区没有找到比较靠谱的解释。于是查了一下这个假输出,英文原文是 “Dummy Output”(在 Launchpad 的翻译站上找到的),换用英文 Google 后得到了以下解决方法(适用于 GNOME 3 / Unity 等桌面环境)。

Reference: http://forums.opensuse.org/english/get-technical-help-here/tumbleweed/465124-pulseaudio-only-dummy-output.html

遇到这个问题的原因是,我用 gnome-session-quit –logout 注销了,再进来就没有声音了,查看上面的声音设置,只有一个“假输出”(图是恢复后的了)。

解决方法就是——将你的用户加入 audio 组,并重启 pulseaudio。

顺便说一句:Infinality 补丁版的 FreeType 渲染效果太 TMD 好了!麻麻再也不用担心 Linux 上的字体丑了~