@@ -304,6 +304,7 @@ function FarmMonitor:loadConfig()
304304 commandInterval = 1 ,
305305 soilResolution = 128 ,
306306 soilRowsPerTick = 2 ,
307+ perfLogEnabled = false ,
307308 }
308309
309310 local cfg = {}
@@ -322,6 +323,8 @@ function FarmMonitor:loadConfig()
322323 cfg .commandInterval = getInt (" exportIntervals.commands#seconds" , defaults .commandInterval )
323324 cfg .soilResolution = getInt (" soilMap.resolution#value" , defaults .soilResolution )
324325 cfg .soilRowsPerTick = getInt (" soilMap.rowsPerTick#value" , defaults .soilRowsPerTick )
326+ local perfVal = getXMLBool (xmlId , " farmMonitor.performanceLog#enabled" )
327+ cfg .perfLogEnabled = perfVal == true
325328 delete (xmlId )
326329 end )
327330 if not ok then
@@ -348,6 +351,8 @@ function FarmMonitor:loadConfig()
348351 f :write (' <resolution value="' .. defaults .soilResolution .. ' "/>\n ' )
349352 f :write (' <rowsPerTick value="' .. defaults .soilRowsPerTick .. ' "/>\n ' )
350353 f :write (' </soilMap>\n ' )
354+ f :write (' <!-- Performance logging: writes perf.csv to modSettings folder -->\n ' )
355+ f :write (' <performanceLog enabled="false"/>\n ' )
351356 f :write (' </farmMonitor>\n ' )
352357 f :close ()
353358 print (" [FarmMonitor] Created default config.xml at: " .. path )
@@ -362,6 +367,8 @@ function FarmMonitor:loadConfig()
362367 FarmMonitor .commandInterval = cfg .commandInterval * 1000
363368 FarmMonitor .soilResolution = cfg .soilResolution
364369 FarmMonitor .soilRowsPerTick = cfg .soilRowsPerTick
370+ FarmMonitor .perfLogEnabled = cfg .perfLogEnabled
371+ FarmMonitor .perfIdleTimer = 0
365372
366373 print (" [FarmMonitor] Config loaded:" )
367374 print (string.format (" [FarmMonitor] Haupt-Export : %d s" , cfg .mainInterval ))
@@ -371,6 +378,13 @@ function FarmMonitor:loadConfig()
371378 print (string.format (" [FarmMonitor] IPC-Commands : %d s" , cfg .commandInterval ))
372379 print (string.format (" [FarmMonitor] Soil-Aufloesung : %d px" , cfg .soilResolution ))
373380 print (string.format (" [FarmMonitor] Soil-RowsPerTick: %d" , cfg .soilRowsPerTick ))
381+ print (string.format (" [FarmMonitor] Perf-Logging : %s" , cfg .perfLogEnabled and " an" or " aus" ))
382+ end
383+
384+ local function appendPerfLine (fn , modMs , frameDt )
385+ local ts = getDate (" %Y-%m-%dT%H:%M:%S" )
386+ local dtStr = frameDt ~= nil and string.format (" dt=%.1fms" , frameDt ) or " "
387+ print (string.format (" [FarmMonitor] PERF %s %s: %.1fms%s" , ts , fn , modMs , dtStr ))
374388end
375389
376390function FarmMonitor :deleteMap ()
@@ -493,40 +507,62 @@ function FarmMonitor:update(dt)
493507 FarmMonitor :exportAutoDriveMarkers ()
494508 end
495509
510+ local perfOn = FarmMonitor .perfLogEnabled
511+ local heavyFrame = false
512+ local t0
513+
496514 FarmMonitor .timer = FarmMonitor .timer + dt
497515 if FarmMonitor .timer >= FarmMonitor .updateInterval then
498516 FarmMonitor .timer = 0
517+ t0 = perfOn and getTime () or nil
499518 FarmMonitor :collectAndSave ()
519+ if perfOn then appendPerfLine (" collect" , getTime () - t0 , dt ) end
520+ heavyFrame = true
500521 end
501522
502523 FarmMonitor .fieldTimer = FarmMonitor .fieldTimer + dt
503524 if FarmMonitor .fieldTimer >= FarmMonitor .fieldInterval then
504525 FarmMonitor .fieldTimer = 0
526+ t0 = perfOn and getTime () or nil
505527 FarmMonitor :collectAndSaveFields ()
528+ if perfOn then appendPerfLine (" fields" , getTime () - t0 , dt ) end
529+ heavyFrame = true
506530 end
507531
508532 FarmMonitor .vehicleTimer = FarmMonitor .vehicleTimer + dt
509533 if FarmMonitor .vehicleTimer >= FarmMonitor .vehicleInterval then
510534 FarmMonitor .vehicleTimer = 0
535+ t0 = perfOn and getTime () or nil
511536 FarmMonitor :collectAndSaveVehicles ()
537+ if perfOn then appendPerfLine (" vehicles" , getTime () - t0 , dt ) end
538+ heavyFrame = true
512539 end
513540
514541 FarmMonitor .vehicleMetaTimer = FarmMonitor .vehicleMetaTimer + dt
515542 if FarmMonitor .vehicleMetaTimer >= FarmMonitor .vehicleMetaInterval then
516543 FarmMonitor .vehicleMetaTimer = 0
544+ t0 = perfOn and getTime () or nil
517545 FarmMonitor :collectAndSaveVehicleMeta ()
546+ if perfOn then appendPerfLine (" vehicleMeta" , getTime () - t0 , dt ) end
547+ heavyFrame = true
518548 end
519549
520550 FarmMonitor .commandTimer = FarmMonitor .commandTimer + dt
521551 if FarmMonitor .commandTimer >= FarmMonitor .commandInterval then
522552 FarmMonitor .commandTimer = 0
553+ t0 = perfOn and getTime () or nil
523554 FarmMonitor :processCommands ()
555+ if perfOn then appendPerfLine (" commands" , getTime () - t0 , dt ) end
556+ heavyFrame = true
524557 end
525558
526559 FarmMonitor .weatherTimer = FarmMonitor .weatherTimer + dt
527560 if FarmMonitor .weatherTimer >= FarmMonitor .weatherInterval then
528561 FarmMonitor .weatherTimer = 0
562+ t0 = perfOn and getTime () or nil
529563 FarmMonitor :collectAndSaveWeather ()
564+ if perfOn then appendPerfLine (" weather" , getTime () - t0 , dt ) end
565+ heavyFrame = true
530566 end
531567
532568 -- Incremental soil layer export: runs every tick, samples a few rows at a time
@@ -536,6 +572,16 @@ function FarmMonitor:update(dt)
536572 if FarmMonitor .soilState ~= nil then
537573 FarmMonitor :stepSoilExport ()
538574 end
575+
576+ -- Idle baseline: sample frame dt every 5 s on frames with no heavy mod work
577+ if perfOn and not heavyFrame then
578+ FarmMonitor .perfIdleTimer = FarmMonitor .perfIdleTimer + dt
579+ if FarmMonitor .perfIdleTimer >= 5000 then
580+ FarmMonitor .perfIdleTimer = 0
581+ appendPerfLine (" idle" , 0 , dt )
582+ end
583+ end
584+
539585end
540586
541587function FarmMonitor :draw () end
@@ -3015,9 +3061,10 @@ function FarmMonitor:initSoilState()
30153061 cellSize = terrainSize / res ,
30163062 half = terrainSize / 2 ,
30173063 rowsPerTick = FarmMonitor .soilRowsPerTick or 2 ,
3018- layerIdx = 1 , -- C: current layer in round-robin
3019- currentRow = 0 , -- A: next row to sample
3020- values = {}, -- accumulator for current layer
3064+ layerIdx = 1 , -- C: current layer in round-robin
3065+ currentRow = 0 , -- A: next row to sample
3066+ values = {}, -- accumulator for current layer
3067+ layerStartTime = getTime (), -- for perf logging
30213068 }
30223069end
30233070
@@ -3083,10 +3130,15 @@ function FarmMonitor:stepSoilExport()
30833130 print (" [FarmMonitor] ERROR writing layer_" .. name .. " : " .. tostring (writeErr ))
30843131 end
30853132
3133+ if FarmMonitor .perfLogEnabled then
3134+ appendPerfLine (" soil_" .. name , getTime () - st .layerStartTime , nil )
3135+ end
3136+
30863137 -- Advance to next layer (C: round-robin)
3087- st .layerIdx = (st .layerIdx % # st .layers ) + 1
3088- st .currentRow = 0
3089- st .values = {}
3138+ st .layerIdx = (st .layerIdx % # st .layers ) + 1
3139+ st .currentRow = 0
3140+ st .values = {}
3141+ st .layerStartTime = getTime ()
30903142 end
30913143end
30923144
0 commit comments