void update_statistics()
{
    gTotalWorldBytes += gVLManager.getTotalBytes();
    gTotalObjectBytes += gObjectBits / 8;

    LLViewerStats& stats = LLViewerStats::instance();

    // make sure we have a valid time delta for this frame
    if (gFrameIntervalSeconds > 0.f)
    {
        if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
        {
            LLViewerStats::getInstance()->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds);
        }
        else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
        {
            LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds);
        }
        else if (gFloaterTools && gFloaterTools->getVisible())
        {
            LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
        }
    }
    stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable"));
    stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail());
    stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip"));
    stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles"));
#if 0 // 1.9.2
    LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject"));
    LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar"));
    LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment"));
#endif
    stats.setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame"));
    F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle");
    F64 network_secs = gDebugView->mFastTimerView->getTime("Network");
    stats.setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs);
    stats.setStat(LLViewerStats::ST_NETWORK_SECS, network_secs);
    stats.setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images"));
    stats.setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State"));
    stats.setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry"));

    LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
    if (cdp)
    {
        stats.mSimPingStat.addValue(cdp->getPingDelay());
        gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1);
        gSimPingCount++;
    }
    else
    {
        stats.mSimPingStat.addValue(10000);
    }

    stats.mFPSStat.addValue(1);
    F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
    stats.mLayersKBitStat.addValue(layer_bits/1024.f);
    stats.mObjectKBitStat.addValue(gObjectBits/1024.f);
    stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
    stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
    gTransferManager.resetTransferBitsIn(LLTCT_ASSET);

    if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
    {
        gTextureTimer.pause();
    }
    else
    {
        gTextureTimer.unpause();
    }

    {
        static F32 visible_avatar_frames = 0.f;
        static F32 avg_visible_avatars = 0;
        F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars;
        if (visible_avatars > 0.f)
        {
            visible_avatar_frames = 1.f;
            avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames;
        }
        stats.setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars);
    }
    LLWorld::getInstance()->updateNetStats();
    LLWorld::getInstance()->requestCacheMisses();

    // Reset all of these values.
    gVLManager.resetBitCounts();
    gObjectBits = 0;
//	gDecodedBits = 0;

    // Only update texture stats periodically so that they are less noisy
    {
        static const F32 texture_stats_freq = 0.25f;
        static LLFrameTimer texture_stats_timer;
        if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
        {
            stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f);
            stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
            stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
            gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
            LLViewerTextureList::sTextureBits = 0;
            LLViewerTextureList::sTexturePackets = 0;
            texture_stats_timer.reset();
        }
    }

    {
        static const F32 mem_stats_freq = 10.f;
        static LLFrameTimer mem_stats_timer;
        if (mem_stats_timer.getElapsedTimeF32() >= mem_stats_freq)
        {
            stats.mMallocStat.addValue(SGMemStat::getMalloc()/1024.f/1024.f);
            mem_stats_timer.reset();
        }
    }
}