Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial rendering not using renderingjobs count of CPU cores #327

Open
dennisjenkins75 opened this issue Jul 1, 2023 · 2 comments
Open
Labels
Backend enhancement New feature or request

Comments

@dennisjenkins75
Copy link
Contributor

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
Copy link
Member

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:

func initialRender(ctx *app.App) {
logrus.Info("Starting initial rendering job")
for true {
start := time.Now()
result, err := ctx.MapBlockAccessor.FindNextLegacyBlocks(ctx.Settings, ctx.Config.Layers, ctx.Config.RenderingFetchLimit)
if err != nil {
logrus.Error("Error in initial rendering run, trying to continue: " + err.Error())
continue
}
if len(result.List) == 0 && !result.HasMore {
ctx.Settings.SetBool(settings.SETTING_INITIAL_RUN, false)
ev := InitialRenderEvent{
Progress: 1,
}
ctx.WebEventbus.Emit("initial-render-progress", &ev)
logrus.Info("initial rendering complete")
return
}
tiles := renderMapblocks(ctx, result.List)
t := time.Now()
elapsed := t.Sub(start)
ev := InitialRenderEvent{
Progress: result.Progress,
}
ctx.WebEventbus.Emit("initial-render-progress", &ev)
fields := logrus.Fields{
"mapblocks": len(result.List),
"tiles": tiles,
"progress%": int(result.Progress * 100),
"elapsed": elapsed,
}
logrus.WithFields(fields).Info("Initial rendering")
//tile gc
ctx.TileDB.GC()
}
}

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? 😏

@BuckarooBanzay BuckarooBanzay added enhancement New feature or request Backend labels Jul 1, 2023
@S-S-X
Copy link

S-S-X commented Jul 5, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backend enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants