Merge pull request #7838 from zzmp/refactor/script-sleep

Use sleep_until for ScriptEngine
This commit is contained in:
Brad Hefta-Gaub 2016-05-09 15:58:22 -07:00
commit 0de721e8f4
3 changed files with 35 additions and 10 deletions

View file

@ -386,8 +386,7 @@ void Agent::sendAvatarBillboardPacket() {
void Agent::processAgentAvatarAndAudio(float deltaTime) { void Agent::processAgentAvatarAndAudio(float deltaTime) {
if (!_scriptEngine->isFinished() && _isAvatar) { if (!_scriptEngine->isFinished() && _isAvatar) {
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>(); auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE) const int SCRIPT_AUDIO_BUFFER_SAMPLES = AudioConstants::SAMPLE_RATE / SCRIPT_FPS + 0.5;
/ (1000 * 1000)) + 0.5);
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO); QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);

View file

@ -9,6 +9,9 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <chrono>
#include <thread>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop> #include <QtCore/QEventLoop>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
@ -706,9 +709,15 @@ void ScriptEngine::run() {
QScriptValue result = evaluate(_scriptContents, _fileNameString); QScriptValue result = evaluate(_scriptContents, _fileNameString);
QElapsedTimer startTime; #ifdef _WIN32
startTime.start(); // VS13 does not sleep_until unless it uses the system_clock, see:
// https://www.reddit.com/r/cpp_questions/comments/3o71ic/sleep_until_not_working_with_a_time_pointsteady/
using clock = std::chrono::system_clock;
#else
using clock = std::chrono::high_resolution_clock;
#endif
clock::time_point startTime = clock::now();
int thisFrame = 0; int thisFrame = 0;
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -716,12 +725,29 @@ void ScriptEngine::run() {
qint64 lastUpdate = usecTimestampNow(); qint64 lastUpdate = usecTimestampNow();
// TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine
while (!_isFinished) { while (!_isFinished) {
int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec // Throttle to SCRIPT_FPS
if (usecToSleep > 0) { const std::chrono::microseconds FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
usleep(usecToSleep); clock::time_point sleepTime(startTime + thisFrame++ * FRAME_DURATION);
} std::this_thread::sleep_until(sleepTime);
#ifdef SCRIPT_DELAY_DEBUG
{
auto now = clock::now();
uint64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(now - startTime).count();
if (seconds > 0) { // avoid division by zero and time travel
uint64_t fps = thisFrame / seconds;
// Overreporting artificially reduces the reported rate
if (thisFrame % SCRIPT_FPS == 0) {
qCDebug(scriptengine) <<
"Frame:" << thisFrame <<
"Slept (us):" << std::chrono::duration_cast<std::chrono::microseconds>(now - sleepTime).count() <<
"FPS:" << fps;
}
}
}
#endif
if (_isFinished) { if (_isFinished) {
break; break;
} }

View file

@ -39,9 +39,9 @@
#include "ScriptUUID.h" #include "ScriptUUID.h"
#include "Vec3.h" #include "Vec3.h"
const QString NO_SCRIPT(""); static const QString NO_SCRIPT("");
const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0f / 60.0f) * 1000 * 1000) + 0.5f); static const int SCRIPT_FPS = 60;
class CallbackData { class CallbackData {
public: public: