3

I have difficulties to understand swap policy. I have installed system (ubuntu 13.04 but 12.10 had same issue) with 4gb of swap partition because ux31a has 4 gb of memory.

Problem is that every time system run out of memory and starts to write to swap it stops to respond. Freezes for like 5 min.

So I thought after some readings that maybe I should set swapiness to 10 and I did. After system went out of memory - same issue.

Then I read SSD should not have any swap and I have set to turn swap off when system starts

Now I have swap turned off and my free -m looks like:

             total       used       free     shared    buffers     cached
Mem:          3840       3340        499          0         33       1293
-/+ buffers/cache:       2013       1827
Swap:            0          0   

Unfortunately problem remains unsolved. Looks like buffers/cache eat all memory and when memory gets to 0 I have exactly same issue. I thought buffers/cache should automatically free some memory when needed, but I think it doesn't

What can I do to avoid system freezes?

additional information: when system freezes after a while it may respond to some commends and I was able to get to console on different session (ctrl + alt + f1) and run "top". First processes kswapd0, kworkers have eaten whole CPU.

Thank you in advance for your help

0

I had also issues with kworker eating whole memory. This seemed to help, run as root:

echo N > /sys/module/drm_kms_helper/parameters/poll

There are also other post about it on internet

  • Robert solution does not work on 13.04, any other idea? – Mateusz Juraszek Aug 27 '13 at 6:57
0

I run without swap, just like you, and in order to prevent any such OS freezes I am running a custom-made kernel patch(also pasted below, but tabs became spaces), which works for me, but as I'm not a developer I cannot guarantee that it's not doing anything else that it shouldn't be doing.
I am running the patched kernel in Qubes OS 4.0 's dom0 and VMs, had applied it on top of kernels 4.18.9 and 4.19-rc5 even. It's easy to test it in Qubes's VMs though because dom0's sudo iotop can show the disk thrashing(just reading, no writing) that occurs when the VM is frozen due to almost running out of memory. The problem being that it evicts executable files' code pages so they have to be re-read from disk on every context switch.

Here is code that can emulate high memory usage, you can use it for testing. In short, something like this:

$ stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 + 4000;}' < /proc/meminfo)k --vm-keep -m 4 --timeout 10s

Here is the kernel patch that avoids any OS freezing and just allows the normal triggering of the oom-killer to kill the process that uses the most RAM(tabs replaced by spaces in this pasting, though):

revision 3
preliminary patch to avoid disk thrashing (constant reading) under memory pressure before OOM-killer triggers
more info: https://gist.github.com/constantoverride/84eba764f487049ed642eb2111a20830

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 32699b2..7636498 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -208,7 +208,7 @@ enum lru_list {

 #define for_each_lru(lru) for (lru = 0; lru < NR_LRU_LISTS; lru++)

-#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_ACTIVE_FILE; lru++)
+#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_INACTIVE_FILE; lru++)

 static inline int is_file_lru(enum lru_list lru)
 {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 03822f8..1f3ffb5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2086,9 +2086,9 @@ static unsigned long shrink_list(enum lr
                 struct scan_control *sc)
 {
    if (is_active_lru(lru)) {
-       if (inactive_list_is_low(lruvec, is_file_lru(lru),
-                    memcg, sc, true))
-           shrink_active_list(nr_to_scan, lruvec, sc, lru);
+       //if (inactive_list_is_low(lruvec, is_file_lru(lru),
+       //           memcg, sc, true))
+       //  shrink_active_list(nr_to_scan, lruvec, sc, lru);
        return 0;
    }

@@ -2234,7 +2234,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,

    anon  = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
        lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, MAX_NR_ZONES);
-   file  = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
+   file  = //lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
        lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES);

    spin_lock_irq(&pgdat->lru_lock);
@@ -2345,7 +2345,7 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
             sc->priority == DEF_PRIORITY);

    blk_start_plug(&plug);
-   while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
+   while (nr[LRU_INACTIVE_ANON] || //nr[LRU_ACTIVE_FILE] ||
                    nr[LRU_INACTIVE_FILE]) {
        unsigned long nr_anon, nr_file, percentage;
        unsigned long nr_scanned;
@@ -2372,7 +2372,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
         * stop reclaiming one LRU and reduce the amount scanning
         * proportional to the original scan target.
         */
-       nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE];
+       nr_file = nr[LRU_INACTIVE_FILE] //+ nr[LRU_ACTIVE_FILE]
+           ;
        nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON];

        /*
@@ -2391,7 +2392,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
            percentage = nr_anon * 100 / scan_target;
        } else {
            unsigned long scan_target = targets[LRU_INACTIVE_FILE] +
-                       targets[LRU_ACTIVE_FILE] + 1;
+                       //targets[LRU_ACTIVE_FILE] + 
+                       1;
            lru = LRU_FILE;
            percentage = nr_file * 100 / scan_target;
        }
@@ -2409,10 +2411,12 @@ static void shrink_node_memcg(struct pgl
        nr[lru] = targets[lru] * (100 - percentage) / 100;
        nr[lru] -= min(nr[lru], nr_scanned);

+       if (LRU_FILE != lru) { //avoid this block for LRU_ACTIVE_FILE
        lru += LRU_ACTIVE;
        nr_scanned = targets[lru] - nr[lru];
        nr[lru] = targets[lru] * (100 - percentage) / 100;
        nr[lru] -= min(nr[lru], nr_scanned);
+       }

        scan_adjusted = true;
    }

NOTE: I don't recommend using this in production. As I said, I'm not a developer and this patch is more like a proof of concept: it tries to not evict from RAM the Active(file) pages when under high memory pressure, and thus context switching doesn't have to re-read the executable files from disk during their execution, thus it will not cause OS to freeze due to the slowness of re-reading those executables from disk.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.