wheybags wrote: Tue May 21, 2019 11:58 amthe solution is to get more ram so you never swap out.
That's not quite right. I could add terabytes of RAM, but as long as my server keeps reading data from hard drives that are larger than the amount of RAM (most people have more disk space than RAM), it will sooner or later swap out unused programs to make space for buffers. Try reading stuff from disk, or simply read your disk: `sudo cat /dev/sda > /dev/null`. Unless you never read anything from disk other than the data that is already buffered in RAM, it will fill up much memory as your disk is large. Except any programs program that are in use, of course (so if you used something within the last few, idk, days? Then it won't swap it out).
you're probably someone who can wrangle a c compiler
Thanks for the compliment

But in truth, while I know the theory and can do some basics, I'm not good with low-level stuff. I don't really understand the steps you described. What I do understand is that an implementation, even if hidden under an experimental flag, is a little more involved than it seemed at first (I didn't know of the potential complications).
Do you know of a way that one might work around the problem? I'm thinking of something like a fake client in 5 lines of python that would send the right bytes to trigger a map save, then disconnect. I could have that run every few hours, that would reload it often enough.
wheybags wrote: Tue May 21, 2019 11:58 amor run the game as root (lol pls don't).
# ps aux | grep -e factorio -e ^USER
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 22569 2.8 2.3 1168420 187908 pts/9 Sl+ May06 654:45 bin/x64/factorio
It's in a container though, but good point, I didn't think to create a user when I was setting up a server for some friends!
--------
You know what just occurred to me? Why does it take multiple minutes? It's <200MB and my disk doesn't take
minutes to read that amount of data.
Over the past week (that's why it's taking so long for me to get back to this) I've been running an experiment, leaving a Python process unused for a while, while reading data from disk (so that the kernel would hopefully buffer the disk data and swap out unused processes). I allocated 200MiB of byte array in Python. At first (that evening and the next evening) it didn't want to swap out: I saw that reading files filled up the buffers, but it didn't swap out my process that I used <24h ago. Then I left it for a bit, and by now it has been over a week. Guess what? It finally swapped out! "195412 kB" was reported[1] as being swapped away for the Python process. For comparison, I also didn't play Factorio over this time (I've been busy) and that process reports "135408 kB" as being swapped out.
So now the big test: will reading that data in Python be as slow as when Factorio reads its map data? If Factorio takes multiple minutes for 135MB, then surely 195MB will take even longer. Here's what I did in Python over the past week, with some 'comments' added:
>>> a = bytes([0 for _ in range(int(1024*1024*200))]) # allocate a byte array of 200MiB
>>> len(a) # this was last week
209715200 # seems to work fine
# Checking htop, the memory allocated sounds about right.
# Checking how much is swapped out[1], we get some 2MB, even after I read the whole hard drive to /dev/null and my server has been annoyingly unresponsive (because of that) for hours. I give up for now and let this process sit idle in a screen session
# ... a week goes by ...
# I run [1] again and ~195MB was reported as swapped out. Now I continue the test:
>>> import time # I loaded the module
>>> t=time.time(); print(time.time()-t) # and did a test run
0.0008966922760009766 # doing nothing is super fast, as expected =)
# Checking [1] again, a few kilobytes were loaded back into main memory (probably the REPL part of the process), but nothing significant. The main chunk of memory is still in swap.
>>> t=time.time(); b=sum(a); print(time.time()-t) # "sum()" the byte array, just so that every byte is read again
12.118383646011353 # 12 seconds
# Checking [1] again, I now see 2304kB: we're back to last week's situation: the "a" bytearray is back in main memory.
So it takes 12 seconds to load ~195MB out of swap, a bunch more than the memory my factorio process swaps away. But this is roughly where my knowledge ends, I don't know how to investigate why this is. Maybe Factorio has some weird memory access patterns? Even if I would do random access (loading random pages of 4KB each), 135MB shouldn't take that long... or maybe? I don't know.
My conclusions so far:
- Loading 195MB from swap takes longer than reading a normal 195MB file, but in Factorio, loading 135MB from swap takes forever.
- Buying more RAM will not help, unless you have more RAM memory than ssd/hdd space (and with 4TB of HDD space, I'd have to find awfully large SODIMM RAM modules).
- This is seen as a niche problem, but I wonder if there aren't a lot of people that run their servers just for themselves and some friends, and don't play for a few days, and run into the same issue. It seems easy to measure how long "saving the map" takes, or rather, how long it takes between 0% and 1% (because that's what takes a few minutes: that first percent), and anonymously report to the factorio servers something like "this super small operation, doing 1% of map saving, just took >60 seconds, and the next percentage point was only 0.2 seconds".
Do you have any idea why reading swap data might be so much slower in Factorio than in other software?
Oh, and could you let me know if this was read? I've put quite a bit of time into this, I'd at least like to make sure someone reads this forum
[1] for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n | grep processname (either 'python' or 'factorio' in my case)