NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

paperDollTests.py (14707B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\paperDoll\paperDollTests.py
      2 import itertools
      3 import trinity
      4 import blue
      5 import uthread
      6 import weakref
      7 import locks
      8 import walk
      9 from eve.client.script.paperDoll.paperDollImpl import Doll, Factory
     10 from eve.client.script.paperDoll.paperDollLOD import LodQueue
     11 from eve.client.script.paperDoll.paperDollSpawnWrappers import PaperDollCharacter
     12 from eve.common.script.paperDoll.paperDollCommonFunctions import BeFrameNice, Yield
     13 from eve.common.script.paperDoll.paperDollConfiguration import PerformanceOptions
     14 lock = locks.RLock()
     15 DEFAULT_PREPASS_RENDERJOB_NAME = 'RenderTestScene'
     16 
     17 class PerformanceTestResults(dict):
     18 
     19     def __init__(self, iterable = None):
     20         dict.__init__(self)
     21         if iterable:
     22             if type(iterable) == PerformanceTestResults:
     23                 self.update(iterable)
     24 
     25     def PunchIn(self, key):
     26         with lock:
     27             self[key] = blue.os.GetWallclockTime()
     28 
     29     def PunchOut(self, key):
     30         with lock:
     31             self[key] = blue.os.TimeDiffInUs(long(self[key]), blue.os.GetWallclockTime()) / 1000.0
     32 
     33 
     34 class BenchmarkTest(object):
     35 
     36     def __init__(self):
     37         self.testTasklet = None
     38         self.factory = None
     39         self.scene = None
     40         self.usePrepass = False
     41         self.results = PerformanceTestResults()
     42 
     43     def _StartTest(self):
     44         with lock:
     45             self.results.PunchIn('Test execution time')
     46 
     47     def _EndTest(self):
     48         with lock:
     49             self.results.PunchOut('Test execution time')
     50 
     51     def Execute_t(self, callBack = None):
     52         with lock:
     53             self._StartTest()
     54             self._EndTest()
     55             if callBack:
     56                 uthread.new(callBack)
     57 
     58     def Execute(self, callBack = None):
     59         self.results.clear()
     60         self.testTasklet = uthread.new(self.Execute_t, callBack)
     61         uthread.schedule(self.testTasklet)
     62 
     63     def GetResult(self):
     64         return PerformanceTestResults(self.results)
     65 
     66 
     67 class SingleDollTest(BenchmarkTest):
     68 
     69     def __init__(self, startLOD, endLOD, resPath = None):
     70         BenchmarkTest.__init__(self)
     71         self.resPath = resPath
     72         self.startLOD = startLOD
     73         self.endLOD = endLOD
     74         self.lodDelta = (endLOD - startLOD) / abs(endLOD - startLOD) if endLOD != startLOD else 0
     75 
     76     def _StartTest(self):
     77         BenchmarkTest._StartTest(self)
     78         pdc = PaperDollCharacter(self.factory)
     79         pdc.doll = Doll('TestDoll')
     80         if self.resPath:
     81             pdc.doll.Load(self.resPath, self.factory)
     82         pdc.doll.overrideLod = self.startLOD
     83         spawnKey = 'Spawning doll at LOD {0}'.format(self.startLOD)
     84         self.results.PunchIn(spawnKey)
     85         pdc.Spawn(self.scene, usePrepass=self.usePrepass)
     86         while pdc.doll.busyUpdating:
     87             Yield()
     88 
     89         self.results.PunchOut(spawnKey)
     90         while pdc.doll.overrideLod != self.endLOD:
     91             nextLOD = pdc.doll.overrideLod + self.lodDelta
     92             spawnKey = 'Switching from LOD {0} to LOD {1}'.format(pdc.doll.overrideLod, nextLOD)
     93             self.results.PunchIn(spawnKey)
     94             pdc.doll.overrideLod = nextLOD
     95             pdc.Update()
     96             while pdc.doll.busyUpdating:
     97                 Yield()
     98 
     99             self.results.PunchOut(spawnKey)
    100             Yield()
    101 
    102 
    103 class MultiDollTest(BenchmarkTest):
    104 
    105     def __init__(self, numChars = 32, maxLOD0 = 8, maxLOD1 = 16, maxLodQueueActive = None, resPaths = None, debugMode = False):
    106         BenchmarkTest.__init__(self)
    107         self.debugMode = debugMode
    108         self.respathsIterator = itertools.cycle(resPaths) if resPaths else None
    109         self.numChars = numChars
    110         self.maxLOD0 = maxLOD0
    111         self.maxLOD1 = maxLOD1
    112         self.maxLOD2 = numChars - (maxLOD0 + maxLOD1)
    113         self.maxLodQueueActive = maxLodQueueActive or 1
    114         self.paperDollCharacters = []
    115         self.points = []
    116         LodQueue.instance = LodQueue()
    117         PerformanceOptions.maxLodQueueActive = self.maxLodQueueActive
    118         PerformanceOptions.maxLodQueueActiveUp = self.maxLodQueueActive
    119 
    120     def SpawnDolls(self, lod, count):
    121         for i in xrange(count):
    122             pdc = PaperDollCharacter(self.factory)
    123             pdc.disableDel = self.debugMode
    124             pdc.doll = Doll('TestDoll')
    125             if self.respathsIterator:
    126                 spawnKey = 'Loading doll #{0} at LOD {1}'.format(i, lod)
    127                 self.results.PunchIn(spawnKey)
    128                 pdc.doll.Load(self.respathsIterator.next(), self.factory)
    129                 self.results.PunchOut(spawnKey)
    130             spawnKey = 'Spawning doll #{0} at LOD {1} without call to Update'.format(i, lod)
    131             self.results.PunchIn(spawnKey)
    132             pdc.Spawn(self.scene, point=self.points.pop(), lod=99999, updateDoll=False, usePrepass=self.usePrepass)
    133             self.results.PunchOut(spawnKey)
    134             self.paperDollCharacters.append(pdc)
    135             avatar = blue.BluePythonWeakRef(pdc.avatar)
    136             doll = weakref.ref(pdc.doll)
    137             factory = weakref.ref(pdc.factory)
    138             LodQueue.instance.AddToQueue(avatar, doll, factory, lod)
    139 
    140     def _StartTest(self):
    141         BenchmarkTest._StartTest(self)
    142         self.points = zip(range(self.numChars / 2) * 2, [0] * self.numChars, [0] * (self.numChars / 2) + [1] * (self.numChars / 2))
    143         self.SpawnDolls(0, self.maxLOD0)
    144         self.SpawnDolls(1, self.maxLOD1)
    145         self.SpawnDolls(2, self.maxLOD2)
    146         Yield()
    147         while LodQueue.instance.queue:
    148             Yield()
    149 
    150         if not self.debugMode:
    151             del self.paperDollCharacters[:]
    152 
    153 
    154 class Benchmarker(object):
    155 
    156     def __init__(self, factory, scene, usePrepass = False, enablePaperDollOptimizations = True):
    157         if enablePaperDollOptimizations:
    158             PerformanceOptions.EnableOptimizations()
    159         self.factory = factory
    160         self.scene = scene
    161         self.usePrepass = usePrepass
    162         self.test = None
    163         self.clearCacheOnEachIteration = True
    164         self.iterations = 20
    165         self.currentIteration = 0
    166         self.results = PerformanceTestResults()
    167 
    168     def SetTest(self, test):
    169         self.test = test
    170         self.currentIteration = 0
    171         self.results = PerformanceTestResults()
    172         test.factory = self.factory
    173         test.scene = self.scene
    174         test.usePrepass = self.usePrepass
    175 
    176     def ClearCaches(self):
    177         blue.motherLode.ClearCached()
    178 
    179     def ExecuteTest(self, onTestExecution = None):
    180 
    181         def OnTestEnd():
    182             result = self.test.GetResult()
    183             self.results[self.currentIteration] = result
    184             if self.currentIteration < self.iterations - 1:
    185                 if onTestExecution:
    186                     onTestExecution(self.test)
    187                 if self.clearCacheOnEachIteration:
    188                     self.ClearCaches()
    189                 self.test.Execute(callBack=OnTestEnd)
    190                 self.currentIteration += 1
    191 
    192         if onTestExecution:
    193             onTestExecution(self.test)
    194         self.results.PunchIn(self.test.__class__)
    195         if self.clearCacheOnEachIteration:
    196             self.ClearCaches()
    197         self.test.Execute(callBack=OnTestEnd)
    198         while self.currentIteration < self.iterations - 1:
    199             Yield()
    200 
    201         self.results.PunchOut(self.test.__class__)
    202 
    203     def SetAndExecuteTest(self, test):
    204         self.SetTest(test)
    205         self.ExecuteTest()
    206 
    207     def GetAnalyzedResults(self):
    208         statisticalData = {}
    209         keys = self.results.keys()
    210         for key in keys:
    211             if type(key) == int:
    212                 testIterationResults = self.results[key]
    213                 for testKey in testIterationResults.keys():
    214                     record = statisticalData.get(testKey, [])
    215                     record.append(testIterationResults[testKey])
    216                     statisticalData[testKey] = record
    217 
    218             else:
    219                 statisticalData[key] = self.results[key]
    220 
    221         for key in statisticalData.keys():
    222             record = statisticalData[key]
    223             if type(record) is list:
    224                 total = sum(record)
    225                 count = len(record)
    226                 mean = total / count
    227                 maxVal = max(record)
    228                 minVal = min(record)
    229                 sum2 = sum(((x - mean) ** 2 for x in record))
    230                 sum3 = sum((x - mean for x in record))
    231                 try:
    232                     variance = (sum2 - sum3 ** 2 / count) / (count - 1)
    233                 except ZeroDivisionError:
    234                     variance = sum2 - sum3 ** 2 / count
    235 
    236                 stdDev = variance ** 0.5
    237                 statisticalData[key] = {'count': count,
    238                  'total': total,
    239                  'min': minVal,
    240                  'max': maxVal,
    241                  'mean': mean,
    242                  'variance': variance,
    243                  'stdDev': stdDev}
    244 
    245         return statisticalData
    246 
    247 
    248 def CreateEmptyScene():
    249     scene = trinity.Tr2InteriorScene()
    250     light1 = trinity.Tr2InteriorLightSource()
    251     light1.radius = 100.0
    252     light1.position = (0.0, 15.0, 50.0)
    253     scene.lights.append(light1)
    254     light2 = trinity.Tr2InteriorLightSource()
    255     light2.radius = 100.0
    256     light2.position = (0.0, 15.0, -50.0)
    257     scene.lights.append(light2)
    258     light3 = trinity.Tr2InteriorLightSource()
    259     light3.radius = 100.0
    260     light3.position = (50.0, 15.0, 0.0)
    261     scene.lights.append(light3)
    262     return scene
    263 
    264 
    265 def SetupScene(scene = None, sceneFile = None, usePrepass = False):
    266     if not sceneFile:
    267         scene = CreateEmptyScene()
    268     else:
    269         scene = blue.resMan.LoadObject(sceneFile)
    270     if usePrepass:
    271         from trinity.eveSceneRenderJobInterior import CreateEveSceneRenderJobInterior
    272         trinity.renderJobs.UnscheduleByName(DEFAULT_PREPASS_RENDERJOB_NAME)
    273         rj = CreateEveSceneRenderJobInterior(DEFAULT_PREPASS_RENDERJOB_NAME)
    274         scene.shadowUpdatesPerFrame = 0
    275         rj.SetScene(scene)
    276         rj.CreateBasicRenderSteps()
    277         rj.EnableSceneUpdate(True)
    278         rj.EnableVisibilityQuery(True)
    279         rj.Enable()
    280     else:
    281         try:
    282             scene.enableROIs = True
    283         except:
    284             pass
    285 
    286         trinity.device.scene = scene
    287     return scene
    288 
    289 
    290 def CollectCharacterSelectionPaths():
    291     respaths = []
    292     for root, dirs, files in walk.walk('res:/graphics/character/dnafiles/characterselect/'):
    293         for f in files:
    294             respaths.append(root + '/' + f)
    295 
    296     return respaths
    297 
    298 
    299 def RunCrowdSpawnTest(coldCache = True, iterations = 20, respaths = None, maxLodQueueActive = 1, debugMode = False, nrPerLod = None):
    300 
    301     def fun():
    302         results = PerformanceTestResults()
    303         key = 'Loading Factory'
    304         results.PunchIn(key)
    305         sTime = blue.os.GetWallclockTime()
    306         factory = Factory()
    307         if respaths:
    308             factory.clothSimulationActive = False
    309         factory.WaitUntilLoaded()
    310         eTime = blue.os.GetWallclockTime()
    311         results.PunchOut(key)
    312         scene = SetupScene(usePrepass=True)
    313         onTestExecution = None
    314         try:
    315             import pprint
    316             bm = Benchmarker(factory, scene, usePrepass=True)
    317             bm.clearCacheOnEachIteration = coldCache
    318             bm.iterations = 1 if debugMode else iterations
    319             totalDolls = sum(nrPerLod) if nrPerLod else 32
    320             lod0Dolls = nrPerLod[0] if nrPerLod else 8
    321             lod1Dolls = nrPerLod[1] if nrPerLod else 8
    322             test0 = MultiDollTest(totalDolls, lod0Dolls, lod1Dolls, maxLodQueueActive=1, resPaths=respaths, debugMode=debugMode)
    323             bm.SetTest(test0)
    324             bm.ExecuteTest(onTestExecution)
    325             pprint.pprint(bm.GetAnalyzedResults())
    326         finally:
    327             if not debugMode:
    328                 trinity.renderJobs.UnscheduleByName(DEFAULT_PREPASS_RENDERJOB_NAME)
    329 
    330     testTasklet = uthread.new(fun)
    331     uthread.schedule(testTasklet)
    332     try:
    333         while testTasklet.alive:
    334             Yield()
    335 
    336     except RuntimeError:
    337         BeFrameNice()
    338 
    339 
    340 def RunClothedSpawnTest(coldCache = True, iterations = 20, maxLodQueueActive = 1, debugMode = False):
    341     RunCrowdSpawnTest(respaths=CollectCharacterSelectionPaths(), coldCache=coldCache, iterations=iterations, maxLodQueueActive=maxLodQueueActive, debugMode=debugMode)
    342 
    343 
    344 def RunSymmetricalSingleDollLODTest(coldCache = True, iterations = 20, respaths = None, printStatistics = True):
    345 
    346     def fun():
    347         results = PerformanceTestResults()
    348         key = 'Loading Factory'
    349         results.PunchIn(key)
    350         sTime = blue.os.GetWallclockTime()
    351         factory = Factory()
    352         if respaths:
    353             factory.clothSimulationActive = False
    354         factory.WaitUntilLoaded()
    355         eTime = blue.os.GetWallclockTime()
    356         results.PunchOut(key)
    357         scene = SetupScene(usePrepass=True)
    358         onTestExecution = None
    359         if respaths:
    360             respathsIterator = itertools.cycle(respaths)
    361 
    362             def onTestExecution(x):
    363                 x.resPath = respathsIterator.next()
    364 
    365         try:
    366             bm = Benchmarker(factory, scene, usePrepass=True)
    367             bm.clearCacheOnEachIteration = coldCache
    368             bm.iterations = iterations
    369             test0 = SingleDollTest(0, 2)
    370             bm.SetTest(test0)
    371             bm.ExecuteTest(onTestExecution)
    372             if printStatistics:
    373                 import pprint
    374                 pprint.pprint(bm.GetAnalyzedResults())
    375             test1 = SingleDollTest(2, 0)
    376             bm.SetTest(test1)
    377             bm.ExecuteTest(onTestExecution)
    378             if printStatistics:
    379                 pprint.pprint(bm.GetAnalyzedResults())
    380                 pprint.pprint(results)
    381         finally:
    382             trinity.renderJobs.UnscheduleByName(DEFAULT_PREPASS_RENDERJOB_NAME)
    383 
    384     testTasklet = uthread.new(fun)
    385     uthread.schedule(testTasklet)
    386     try:
    387         while testTasklet.alive:
    388             Yield()
    389 
    390     except RuntimeError:
    391         BeFrameNice()
    392 
    393 
    394 def RunSymmetricalSingleNudeLODTest(iterations = 20, coldCache = True, printStatistics = True):
    395     RunSymmetricalSingleDollLODTest(iterations=iterations, printStatistics=printStatistics)
    396 
    397 
    398 def RunSymmetricalSingleClothedDollLODTest(iterations = 20, coldCache = True, printStatistics = True):
    399     RunSymmetricalSingleDollLODTest(iterations=iterations, respaths=CollectCharacterSelectionPaths(), printStatistics=printStatistics)
    400 
    401 
    402 def RunComprehensiveSymmetricalDollLODTest(iterations = 20):
    403 
    404     def fun():
    405         RunSymmetricalSingleNudeLODTest(coldCache=True, iterations=iterations)
    406         RunSymmetricalSingleClothedDollLODTest(coldCache=True, iterations=iterations)
    407         RunSymmetricalSingleNudeLODTest(coldCache=False, iterations=iterations)
    408         RunSymmetricalSingleClothedDollLODTest(coldCache=False, iterations=iterations)
    409 
    410     uthread.new(fun)