minetest-mapserver / mapserver

Minetest realtime mapserver, written in go
Other
101 stars 22 forks source link

Initial rendering not using `renderingjobs` count of CPU cores #327

Open dennisjenkins75 opened 1 year ago

dennisjenkins75 commented 1 year ago

Hello.

I've been tinkering with a custom C++ map generator that prebuilds a map.sqlite file, so that in-game mapgen is just set to "singlenode". As part of my development workflow, I want to run the mapserver on it to be able to view it in the mapserver's HTTP UI. I do this in docker, but that should not matter. My goal is to use all of my CPU cores to complete the initial rendering as fast as possible.

The problem is that I am unable to get the mapserver to use more than ~1.3 CPU cores. I have a 16 core (32 thread) AMD CPU, so I have the cores available. I've conducted several experiments (data below). For a sample map of 9095 blocks (~1000 x 1000 x whatever) world, the initial rendering always ranges from 186s and up. During this time, I can verify (htop, xload, other tools) that the mapserver is only using 1, sometimes 1.3 cores. I've tweaked the renderingfetchlimit, renderingjobs, and renderingqueue values. At best I can make it perform WORSE, but never better. In fact, as I decrease renderingjobs the initial rendering phase completes FASTER (I assume due to decreased internal lock contention??)

Please advise. Thank you.

Map server initial rendering timings.

RFL: renderingfetchlimit
RJ:  renderingjobs
RQ:  renderingqueue
MI:  mapblockaccessor.maxitems

Map Radius = 500, 9095 blocks, 1402 tiles

RFL     RJ      RQ      MI              Time (s)        Load Avg

50000   12      1000    500             204             1.77
50000   12       100    500             208
50000   12       200    500             204
50000   12       400    500             207
 1000   12       400    500             251
50000    8       400    500             199
50000    4       400    500             190
50000    4       400    500             189
50000    4      2000    500             188
50000    4        20    500             191
50000    3       400    500             188
50000    2       400    500             186
50000    1       400    500             186
$ ls -lnog tmp/docker/0/map.sqlite 
-rw-r--r-- 1 1458176 Jun 30 17:06 tmp/docker/0/map.sqlite

$ sqlite3 tmp/docker/0/map.sqlite "select count(*) from blocks;"
9095

Logs from renderingjobs = 12, renderingfetchlimit = 50000, renderingqueue = 1000

mapserver-0  | INFO[0000] Starting mapserver                            version=4.7.0
mapserver-0  | INFO[0000] Migrating database, this might take a while depending on the mapblock-count  filename=map.sqlite prefix=sqlite-db
mapserver-0  | INFO[0000] Migration completed                           elapsed=5.659851ms prefix=sqlite-db
mapserver-0  | INFO[0000] Loading colors from filesystem                filename=colors.txt
mapserver-0  | INFO[0000] Loaded custom colors                          count=652
mapserver-0  | INFO[0000] Migrating database                            filename=mapserver.sqlite prefix=mapobjectdb.sqlite
mapserver-0  | INFO[0000] Migration completed                           elapsed=2.879624ms prefix=mapobjectdb.sqlite
mapserver-0  | INFO[0000] Starting http server                          port=8080 webdev=false
mapserver-0  | INFO[0000] using embed mode                             
mapserver-0  | INFO[0000] Starting initial rendering job               
mapserver-0  | INFO[0204] Initial rendering                             elapsed=3m24.323829898s mapblocks=9095 progress%=0 tiles=1402
mapserver-0  | INFO[0204] initial rendering complete                   
mapserver-0  | INFO[0204] Starting incremental rendering job            LastMtime=1688171108
BuckarooBanzay commented 1 year ago

had to look that up myself because it has been ages i've done something on that part, but it looks like the initial rendering is done in a single thread: https://github.com/minetest-mapserver/mapserver/blob/53689acf531c78d4709165f0b806662460a9beff/tilerendererjob/initial.go#L15-L65

why the hell did i write "for true" there?

from the looks of it the process should be scalable with threading, not really a priority for me right now, PR's welcome though.

Why do you need it to be fast anyway? What are you trying do accomplish? :smirk:

S-S-X commented 1 year ago

For Minetest servers I think less threads is better in most cases anyway so if implemented I'd suggest at least ability to configure max threads so that it could be locked to one or few.