Ticket #1862: profiler2.2.patch

File profiler2.2.patch, 13.5 KB (added by giannis, 10 years ago)

based on the previous patch and suggestions

  • binaries/data/config/default.cfg

     
    326326; > PROFILER
    327327hotkey.profile.toggle = "F11"               ; Enable/disable real-time profiler
    328328hotkey.profile.save = "Shift+F11"           ; Save current profiler data to logs/profile.txt
    329 hotkey.profile2.enable = "F11"              ; Enable HTTP/GPU modes for new profiler
     329hotkey.profile2.toggle = "Ctrl+F11"         ; Enable/disable HTTP/GPU modes for new profiler
    330330
    331 profiler2.http.autoenable = false           ; Enable HTTP server output at startup (default off for security/performance)
     331profiler2.autoenable = false                ; Enable HTTP server output at startup (default off for security/performance)
    332332profiler2.script.enable = false             ; Enable Javascript profiling. Needs to be set before startup and can't be changed later. (default off for performance)
    333 profiler2.gpu.autoenable = false            ; Enable GPU timing at startup (default off for performance/compatibility)
    334333profiler2.gpu.arb.enable = true             ; Allow GL_ARB_timer_query timing mode when available
    335334profiler2.gpu.ext.enable = true             ; Allow GL_EXT_timer_query timing mode when available
    336335profiler2.gpu.intel.enable = true           ; Allow GL_INTEL_performance_queries timing mode when available
  • source/main.cpp

     
    161161#endif
    162162            return IN_HANDLED;
    163163        }
    164         else if (hotkey == "profile2.enable")
     164        else if (hotkey == "profile2.toggle")
    165165        {
    166             g_Profiler2.EnableGPU();
    167             g_Profiler2.EnableHTTP();
     166            g_Profiler2.Toggle();
    168167            return IN_HANDLED;
    169168        }
    170169        break;
     
    179178{
    180179    JSContext* cx = g_GUI->GetScriptInterface()->GetContext();
    181180    JSAutoRequest rq(cx);
    182    
     181
    183182    PROFILE3("dispatch events");
    184183
    185184    SDL_Event_ ev;
     
    294293    bool need_update = true;
    295294
    296295    // If we are not running a multiplayer game, disable updates when the game is
    297     // minimized or out of focus and relinquish the CPU a bit, in order to make 
     296    // minimized or out of focus and relinquish the CPU a bit, in order to make
    298297    // debugging easier.
    299298    if(g_PauseOnFocusLoss && !g_NetClient && !g_app_has_focus)
    300299    {
  • source/ps/GameSetup/GameSetup.cpp

     
    433433
    434434    const size_t cacheSize = ChooseCacheSize();
    435435    g_VFS = CreateVfs(cacheSize);
    436    
     436
    437437    // Work out whether we are a dev version to make sure saved files
    438438    // (maps, etc) end up in version control.
    439439    const OsPath readonlyConfig = paths.RData()/"config"/"";
     
    451451        size_t priority = (i+1)*2;  // mods are higher priority than regular mountings, which default to priority 0
    452452        size_t userFlags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_REPLACEABLE;
    453453        size_t baseFlags = userFlags|VFS_MOUNT_MUST_EXIST;
    454        
     454
    455455        OsPath modName(mods[i]);
    456456        if (InDevelopmentCopy())
    457457        {
     
    565565    SAFE_DELETE(g_GUI);
    566566
    567567    SAFE_DELETE(g_Console);
    568    
    569     // This is needed to ensure that no callbacks from the JSAPI try to use 
     568
     569    // This is needed to ensure that no callbacks from the JSAPI try to use
    570570    // the profiler when it's already destructed
    571571    g_ScriptRuntime.reset();
    572572
     
    597597    g_Renderer.SetOptionBool(CRenderer::OPT_WATERREFLECTION, g_WaterReflection);
    598598    g_Renderer.SetOptionBool(CRenderer::OPT_WATERREFRACTION, g_WaterRefraction);
    599599    g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWSONWATER, g_WaterShadows);
    600    
     600
    601601    g_Renderer.SetRenderPath(CRenderer::GetRenderPathByName(g_RenderPath));
    602602    g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWPCF, g_ShadowPCF);
    603603    g_Renderer.SetOptionBool(CRenderer::OPT_PARTICLES, g_Particles);
     
    862862    // This must come after VFS init, which sets the current directory
    863863    // (required for finding our output log files).
    864864    g_Logger = new CLogger;
    865    
     865
    866866    // Workaround until Simulation and AI use their own threads and also their own runtimes
    867867    g_ScriptRuntime = ScriptInterface::CreateRuntime(384 * 1024 * 1024);
    868868
     
    906906    // g_ConfigDB, command line args, globals
    907907    CONFIG_Init(args);
    908908
    909     // before scripting 
     909    // before scripting
    910910    // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
    911911    //if (g_JSDebuggerEnabled)
    912912    //  g_DebuggingServer = new CDebuggingServer();
     
    914914    // Optionally start profiler HTTP output automatically
    915915    // (By default it's only enabled by a hotkey, for security/performance)
    916916    bool profilerHTTPEnable = false;
    917     CFG_GET_VAL("profiler2.http.autoenable", Bool, profilerHTTPEnable);
     917    CFG_GET_VAL("profiler2.autoenable", Bool, profilerHTTPEnable);
    918918    if (profilerHTTPEnable)
    919919        g_Profiler2.EnableHTTP();
    920920
     
    950950    // Optionally start profiler GPU timings automatically
    951951    // (By default it's only enabled by a hotkey, for performance/compatibility)
    952952    bool profilerGPUEnable = false;
    953     CFG_GET_VAL("profiler2.gpu.autoenable", Bool, profilerGPUEnable);
     953    CFG_GET_VAL("profiler2.autoenable", Bool, profilerGPUEnable);
    954954    if (profilerGPUEnable)
    955955        g_Profiler2.EnableGPU();
    956956
     
    11811181                seed = seedArg.ToULong();
    11821182            }
    11831183        }
    1184        
     1184
    11851185        // Random map definition will be loaded from JSON file, so we need to parse it
    11861186        std::wstring scriptPath = L"maps/" + autoStartName.FromUTF8() + L".json";
    11871187        JS::RootedValue scriptData(cx, scriptInterface.ReadJSONFile(scriptPath).get());
     
    13061306            {
    13071307                scriptInterface.Eval("({})", &player);
    13081308            }
    1309            
     1309
    13101310            int playerID = civArgs[i].BeforeFirst(":").ToInt();
    13111311            int difficulty = civArgs[i].AfterFirst(":").ToInt();
    1312            
     1312
    13131313            scriptInterface.SetProperty(player, "AIDiff", difficulty);
    13141314            scriptInterface.SetPropertyInt(playerData, playerID-1, player);
    13151315        }
     
    13261326            {
    13271327                scriptInterface.Eval("({})", &player);
    13281328            }
    1329            
     1329
    13301330            int playerID = civArgs[i].BeforeFirst(":").ToInt();
    13311331            CStr name = civArgs[i].AfterFirst(":");
    1332            
     1332
    13331333            scriptInterface.SetProperty(player, "Civ", std::string(name));
    13341334            scriptInterface.SetPropertyInt(playerData, playerID-1, player);
    13351335        }
  • source/ps/Profiler2.cpp

     
    77 * distribute, sublicense, and/or sell copies of the Software, and to
    88 * permit persons to whom the Software is furnished to do so, subject to
    99 * the following conditions:
    10  * 
     10 *
    1111 * The above copyright notice and this permission notice shall be included
    1212 * in all copies or substantial portions of the Software.
    13  * 
     13 *
    1414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1515 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1616 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     
    157157void CProfiler2::EnableHTTP()
    158158{
    159159    ENSURE(m_Initialised);
     160    debug_DisplayMessage(L"ATTENTION",L"Starting profiler2 HTTP server");
    160161
    161162    // Ignore multiple enablings
    162163    if (m_MgContext)
     
    175176{
    176177    ENSURE(m_Initialised);
    177178    if (!m_GPU)
    178         InitialiseGPU();
     179    {
     180        debug_DisplayMessage(L"ATTENTION",L"Starting profiler2_GPU");
     181        InitialiseGPU();
     182    }
    179183}
    180184
    181185void CProfiler2::ShutdownGPU()
    182186{
     187    debug_DisplayMessage(L"ATTENTION",L"Shutting down profiler2_GPU");
    183188    SAFE_DELETE(m_GPU);
    184189}
    185190
     191void CProfiler2::ShutDownHTTP()
     192{
     193    debug_DisplayMessage(L"ATTENTION",L"Shutting down profiler2 HTTP server");
     194    if (m_MgContext)
     195    {
     196        mg_stop(m_MgContext);
     197        m_MgContext = NULL;
     198    }
     199}
     200
     201void CProfiler2::Toggle()
     202{
     203    //TODO: Maybe we can open the browser to the profiler page automatically
     204    if(m_GPU && m_MgContext)
     205    {
     206        ShutdownGPU();
     207        ShutDownHTTP();
     208    }
     209    else if(!m_GPU && !m_MgContext)
     210    {
     211        EnableGPU();
     212        EnableHTTP();
     213    }
     214}
     215
    186216void CProfiler2::Shutdown()
    187217{
    188218    ENSURE(m_Initialised);
     
    285315std::string CProfiler2::ThreadStorage::GetBuffer()
    286316{
    287317    // Called from an arbitrary thread (not the one writing to the buffer).
    288     // 
     318    //
    289319    // See comments on m_BufferPos0 etc.
    290320
    291321    shared_ptr<u8> buffer(new u8[BUFFER_SIZE], ArrayDeleter());
  • source/ps/Profiler2.h

     
    77 * distribute, sublicense, and/or sell copies of the Software, and to
    88 * permit persons to whom the Software is furnished to do so, subject to
    99 * the following conditions:
    10  * 
     10 *
    1111 * The above copyright notice and this permission notice shall be included
    1212 * in all copies or substantial portions of the Software.
    13  * 
     13 *
    1414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1515 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1616 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     
    2323/**
    2424 * @file
    2525 * New profiler (complementing the older CProfileManager)
    26  * 
     26 *
    2727 * The profiler is designed for analysing framerate fluctuations or glitches,
    2828 * and temporal relationships between threads.
    2929 * This contrasts with CProfilerManager and most external profiling tools,
    3030 * which are designed more for measuring average throughput over a number of
    3131 * frames.
    32  * 
     32 *
    3333 * To view the profiler output, press F11 to enable the HTTP output mode
    3434 * and then open source/tools/profiler2/profiler2.html in a web browser.
    35  * 
     35 *
    3636 * There is a single global CProfiler2 instance (g_Profiler2),
    3737 * providing the API used by the rest of the game.
    3838 * The game can record the entry/exit timings of a region of code
     
    4141 * Regions and events can be annotated with arbitrary string attributes,
    4242 * specified with printf-style format strings, using PROFILE2_ATTR
    4343 * (e.g. PROFILE2_ATTR("frame: %d", m_FrameNum) ).
    44  * 
     44 *
    4545 * This is designed for relatively coarse-grained profiling, or for rare events.
    4646 * Don't use it for regions that are typically less than ~0.1msecs, or that are
    4747 * called hundreds of times per frame. (The old CProfilerManager is better
    4848 * for that.)
    49  * 
     49 *
    5050 * New threads must call g_Profiler2.RegisterCurrentThread before any other
    5151 * profiler functions.
    52  * 
     52 *
    5353 * The main thread should call g_Profiler2.RecordFrameStart at the start of
    5454 * each frame.
    5555 * Other threads should call g_Profiler2.RecordSyncMarker occasionally,
    5656 * especially if it's been a long time since their last call to the profiler,
    5757 * or if they've made thousands of calls since the last sync marker.
    58  * 
     58 *
    5959 * The profiler is implemented with thread-local fixed-size ring buffers,
    6060 * which store a sequence of variable-length items indicating the time
    6161 * of the event and associated data (pointers to names, attribute strings, etc).
     
    6262 * An HTTP server provides access to the data: when requested, it will make
    6363 * a copy of a thread's buffer, then parse the items and return them in JSON
    6464 * format. The profiler2.html requests and processes and visualises this data.
    65  * 
     65 *
    6666 * The RecordSyncMarker calls are necessary to correct for time drift and to
    6767 * let the buffer parser accurately detect the start of an item in the byte stream.
    68  * 
     68 *
    6969 * This design aims to minimise the performance overhead of recording data,
    7070 * and to simplify the visualisation of the data by doing it externally in an
    7171 * environment with better UI tools (i.e. HTML) instead of within the game engine.
    72  * 
     72 *
    7373 * The initial setup of g_Profiler2 must happen in the game's main thread.
    7474 * RegisterCurrentThread and the Record functions may be called from any thread.
    7575 * The HTTP server runs its own threads, which may call the ConstructJSON functions.
     
    110110
    111111    /// An arbitrary number to help resyncing with the item stream when parsing.
    112112    static const u8 RESYNC_MAGIC[8];
    113    
     113
    114114    /**
    115115     * An item with a relative time and an ID string pointer.
    116116     */
     
    134134    public:
    135135        ThreadStorage(CProfiler2& profiler, const std::string& name);
    136136        ~ThreadStorage();
    137    
     137
    138138        void RecordSyncMarker(double t)
    139139        {
    140140            // Store the magic string followed by the absolute time
     
    163163        }
    164164
    165165        void RecordAttribute(const char* fmt, va_list argp) VPRINTF_ARGS(2);
    166        
     166
    167167        void RecordAttributePrintf(const char* fmt, ...) PRINTF_ARGS(2)
    168168        {
    169169            va_list argp;
     
    219219
    220220            m_Buffer[start] = (u8)type;
    221221            memcpy(&m_Buffer[start + 1], item, itemSize);
    222            
     222
    223223            COMPILER_FENCE; // must write m_BufferPos1 after m_Buffer
    224224            m_BufferPos1 = start + size;
    225225        }
     
    239239        // outside the range Pos1 <= x < Pos0 are safe to use. (Any in that range might
    240240        // be half-written and corrupted.) (All ranges are modulo BUFFER_SIZE.)
    241241        // Outside of Write(), these will always be equal.
    242         // 
     242        //
    243243        // TODO: does this attempt at synchronisation (plus use of COMPILER_FENCE etc)
    244244        // actually work in practice?
    245245        u32 m_BufferPos0;
     
    275275     */
    276276    void ShutdownGPU();
    277277
     278    /**
     279     * Call in main thread to shut down the profiler's HTTP server
     280     */
     281    void ShutDownHTTP();
     282
     283    /**
     284     * Call in main thread to enable/disable the profiler
     285     */
     286    void Toggle();
     287
    278288    /**
    279289     * Call in main thread to shut everything down.
    280290     * All other profiled threads should have been terminated already.
     
    387397    bool m_Initialised;
    388398
    389399    int m_FrameNumber;
    390    
     400
    391401    mg_context* m_MgContext;
    392    
     402
    393403    pthread_key_t m_TLS;
    394404
    395405    CProfiler2GPU* m_GPU;