std::deque.front() выполняется 200 миллисекунд, как это возможно?

100
06 апреля 2021, 22:40

Очень странные вещи происходят

Прежде всего я использую jni android (если это важно)

У меня есть safe-thread имплементация std::deque с одно стороны в одном треде я наполняю эту очередь с другой стороны в другом треде я забираю с очереди

Я не могу понять почему метод который вытаскивает из очереди front() берет около 200 миллисекунд на выполнение?

Имплементация очереди

 #ifndef SAFE_QUEUE
#define SAFE_QUEUE
#include <queue>
#include <mutex>
#include <condition_variable>
#include "frame_manager.h"
#include <android/log.h>
#include <string>
#include <chrono>
using namespace std;
using namespace std::chrono;
namespace hello_ar
{
// A threadsafe-queue.
template<class T>
class safe_queue
{
public:
    safe_queue(std::string const &name)
    {
        m_name = name;
    }
    ~safe_queue()
    = default;
    // Add an element to the queue.
    void enqueue(T t)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push_back(t);
        m_condition.notify_one();
    }
    std::string getName()
    {
        return m_name;
    }
    int getSize()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return static_cast<int>(m_queue.size());
    }
    // Get the "front"-element.
    // If the queue is empty, wait till a element is avaiable.
    T dequeue(bool flag)
    {
        high_resolution_clock::time_point t5 = high_resolution_clock::now();
        T val;
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            while (m_queue.empty())
            {
                // release lock as long as the wait and reaquire it afterwards.
                m_condition.wait(lock);
            }
            val = m_queue.front();
            if (flag)
            {
                m_queue.pop_front();
            }
        }
        return val;
    }
    T dequeue()
    {
        return dequeue(true);
    }
    void clear()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        std::deque<std::shared_ptr<FrameManager>>().swap(m_queue);
    }
    bool empty()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_queue.empty();
    }
public:
    std::deque<T> m_queue;
    mutable std::mutex m_mutex;
    std::condition_variable m_condition;
    std::string m_name;
};
}
#endi

Наполнение очереди происходит с помощью enqueue

Как я сказал есть еще другой класс и другой метод который выполняется на другом потоке и вытаскивает из очереди, что там есть.

void VideoRender::Draw(const glm::mat4 &projection_mat, //
                       const glm::mat4 &view_mat, //
                       glm::mat4 &model_mat //
)
{
    if (!m_shaderProgram)
    {
        LOGE("shader_program is null.");
        return;
    }
    if (m_bPauseFrameLoading)
        return;
    high_resolution_clock::time_point now_time = high_resolution_clock::now();
    long long int delta_from_last_time = duration_cast<microseconds>(now_time - m_last_time).count();
    if (!m_fifo.empty() && delta_from_last_time >= util::FRAME_INTERVAL_MSEC * 1000)
    {
        m_last_time = now_time;
        high_resolution_clock::time_point t4 = high_resolution_clock::now();
        m_FrameManager = m_fifo.m_queue.front();
        long long int durationn = duration_cast<microseconds>(high_resolution_clock::now() - t4).count();
        __android_log_print(ANDROID_LOG_ERROR, "front", "front  %s::: %s", m_fifo.getName().c_str(), std::to_string(durationn).c_str());
        m_fifo.m_queue.pop_front();
        std::vector<GLfloat> const &vertices = m_FrameManager->getVertices();
        std::vector<GLfloat> const &textures = m_FrameManager->getTextures();
        std::vector<GLuint> const &indices = m_FrameManager->getIndices();
        glDeleteTextures(1, &m_textureId);
        glGenTextures(1, &m_textureId);
        glBindTexture(GL_TEXTURE_2D, m_textureId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, //
                     0, //
                     GL_RGB,  //
                     m_FrameManager->getImageWidth(), //
                     m_FrameManager->getImageHeight(), //
                     0, //
                     GL_RGB, //
                     GL_UNSIGNED_BYTE, //
                     m_FrameManager->GetImageData().data()//
        );
    }
    glUseProgram(m_shaderProgram);
    if (m_FrameManager != nullptr)
    {
        glVertexAttribPointer(static_cast<GLuint>(m_attriVertices), 3, GL_FLOAT, GL_FALSE, 0, m_FrameManager->getVertices().data());
        glEnableVertexAttribArray(static_cast<GLuint>(m_attriVertices));
        glVertexAttribPointer(static_cast<GLuint>(m_attriUvs), 2, GL_FLOAT, GL_FALSE, 0, m_FrameManager->getTextures().data());
        glEnableVertexAttribArray(static_cast<GLuint>(m_attriUvs));
        glUniform2f(m_uniform_center_xy, static_cast<GLfloat>(m_centerX), static_cast<GLfloat>(m_centerY));
        //---------------------------------------------
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, m_textureId);
        glUniform1i(m_uniformTexture, 0);
        model_mat = glm::rotate(model_mat, util::AXIS_ALIGNMENT, glm::vec3(1.F));
        model_mat = glm::rotate(model_mat, m_modelRotation, glm::vec3(0, 0, 1));
        model_mat = glm::scale(model_mat, glm::vec3(m_modelSize));
        glm::mat4 mvp_mat = projection_mat * view_mat * model_mat;
        glUniformMatrix4fv(m_uniformMvpMat, 1, GL_FALSE, glm::value_ptr(mvp_mat));
        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_FrameManager->getIndices().size()), GL_UNSIGNED_INT, m_FrameManager->getIndices().data());
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    glDisableVertexAttribArray(static_cast<GLuint>(m_attriVertices));
    glDisableVertexAttribArray(static_cast<GLuint>(m_attriUvs));
    glUseProgram(0);
    util::CheckGlError("VideoRender::Draw()");
}

Это длинный метод и на самом деле вам не нужно знать все, что здесь происходит, но я хочу обратить внимание на строку

 m_FrameManager = m_fifo.m_queue.front();

Здесь я специально сделал m_queue public чтоб убрать возможные сомнения , теперь я напрямую обращаюсь в мою имплементацию очереди от туда я напрямую беру std::deque и уже на ней вызываю front() , чтоб получить обьект

Так же сразу же этого метода есть следующая строка в которой я логирую время выполнения

__android_log_print(ANDROID_LOG_ERROR, "front", "front  %s::: %s", m_fifo.getName().c_str(), std::to_string(durationn).c_str());

И вот время выполнения

13:03:27.137  E/front: front  video_render::: 213285
13:03:27.446  E/front: front  video_render::: 276841
13:03:27.710  E/front: front  video_render::: 238782
13:03:27.936  E/front: front  video_render::: 197096
13:03:28.171  E/front: front  video_render::: 216234
13:03:28.400  E/front: front  video_render::: 208742
13:03:28.620  E/front: front  video_render::: 205443
13:03:28.869  E/front: front  video_render::: 227723
13:03:29.117  E/front: front  video_render::: 217806
13:03:29.345  E/front: front  video_render::: 207497
13:03:29.575  E/front: front  video_render::: 214358
13:03:29.806  E/front: front  video_render::: 216148
13:03:30.006  E/front: front  video_render::: 186434
13:03:30.207  E/front: front  video_render::: 188939
13:03:30.414  E/front: front  video_render::: 192210
13:03:30.620  E/front: front  video_render::: 189335
13:03:30.821  E/front: front  video_render::: 186266
13:03:31.025  E/front: front  video_render::: 186589

Так что вопрос, как такое возможно, что время выполнения стандартного метода front() 200 милисекунд?

EDIT

Тип обьекта в очереди std::shared_ptr<FrameManager>

struct FrameManager
{
private:
    std::vector<GLfloat> m_vertices;
    std::vector<GLfloat> m_textures;
    std::vector<GLuint> m_indices;
    std::vector<GLuint> m_indicess;
    std::vector<GLuint> m_indicesss;
    std::vector<GLuint> m_indicessss;
    std::vector<unsigned char> m_imageData;
    GeometryLoader m_geometryLoader;
    NativeCodec &m_nativeCodec;
    bool m_isGeometryLoaded = false;
    bool m_isTexLoaded = false;
....
}
READ ALSO
Зачем нужно пробрасывать исключения?

Зачем нужно пробрасывать исключения?

Зачем нужно пробрасывать исключения? Почему может быть нельзя из сразу обработать?

104
WebView API 28 не работает

WebView API 28 не работает

Есть WebView который подгружает локальный (хранящийся в память приложения) файл indexhtml

103
Использование разных targetNamespace для одного Wsdl

Использование разных targetNamespace для одного Wsdl

Я использую Spring-ws для написания SOAP-клиентаПри этом на сервере используются две wsdl для тестовой и продакшн сред, одинаковые по содержанию,...

102
Room Entity Annotation

Room Entity Annotation

В чем проблема? Comple error : Compilation failed; see the compiler error output for details

89