Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance improvement for large data #146

Merged
merged 3 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions include/inja/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,14 @@ class Renderer {
ptr = ptr_buffer;
break;
}
json::json_pointer json_ptr(ptr.data());
try {
return &m_data->at(json::json_pointer(ptr.data()));
// first try to evaluate as a loop variable
// Using contains() is faster than unsucessful at() and throwing an exception
if (m_loop_data && m_loop_data->contains(json_ptr)) {
return &m_loop_data->at(json_ptr);
}
return &m_data->at(json_ptr);
} catch (std::exception&) {
// try to evaluate as a no-argument callback
if (auto callback = m_callbacks.find_callback(bc.str, 0)) {
Expand Down Expand Up @@ -158,6 +164,7 @@ class Renderer {
};

std::vector<LoopLevel> m_loop_stack;
json* m_loop_data;
const json* m_data;

std::vector<const json*> m_tmp_args;
Expand All @@ -171,8 +178,9 @@ class Renderer {
m_loop_stack.reserve(16);
}

void render_to(std::ostream& os, const Template& tmpl, const json& data) {
void render_to(std::ostream& os, const Template& tmpl, const json& data, json* loop_data = nullptr) {
m_data = &data;
m_loop_data = loop_data;

for (size_t i = 0; i < tmpl.bytecodes.size(); ++i) {
const auto& bc = tmpl.bytecodes[i];
Expand Down Expand Up @@ -458,7 +466,7 @@ class Renderer {
break;
}
case Bytecode::Op::Include:
Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, *m_data);
Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, *m_data, m_loop_data);
break;
case Bytecode::Op::Callback: {
auto callback = m_callbacks.find_callback(bc.str, bc.args);
Expand Down Expand Up @@ -493,7 +501,9 @@ class Renderer {
LoopLevel& level = m_loop_stack.back();
level.value_name = bc.str;
level.values = std::move(m_stack.back());
level.data = (*m_data);
if (m_loop_data) {
level.data = *m_loop_data;
}
level.index = 0;
m_stack.pop_back();

Expand Down Expand Up @@ -532,8 +542,8 @@ class Renderer {
(*parent_loop_it)["parent"] = std::move(loop_copy);
}

// set "current" data to loop data
m_data = &level.data;
// set "current" loop data to this level
m_loop_data = &level.data;
update_loop_data();
break;
}
Expand All @@ -556,9 +566,9 @@ class Renderer {
m_loop_stack.pop_back();
// set "current" data to outer loop data or main data as appropriate
if (!m_loop_stack.empty()) {
m_data = &m_loop_stack.back().data;
m_loop_data = &m_loop_stack.back().data;
} else {
m_data = &data;
m_loop_data = loop_data;
}
break;
}
Expand Down
26 changes: 18 additions & 8 deletions single_include/inja/inja.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3096,8 +3096,14 @@ class Renderer {
ptr = ptr_buffer;
break;
}
json::json_pointer json_ptr(ptr.data());
try {
return &m_data->at(json::json_pointer(ptr.data()));
// first try to evaluate as a loop variable
// Using contains() is faster than unsucessful at() and throwing an exception
if (m_loop_data && m_loop_data->contains(json_ptr)) {
return &m_loop_data->at(json_ptr);
}
return &m_data->at(json_ptr);
} catch (std::exception&) {
// try to evaluate as a no-argument callback
if (auto callback = m_callbacks.find_callback(bc.str, 0)) {
Expand Down Expand Up @@ -3170,6 +3176,7 @@ class Renderer {
};

std::vector<LoopLevel> m_loop_stack;
json* m_loop_data;
const json* m_data;

std::vector<const json*> m_tmp_args;
Expand All @@ -3183,8 +3190,9 @@ class Renderer {
m_loop_stack.reserve(16);
}

void render_to(std::ostream& os, const Template& tmpl, const json& data) {
void render_to(std::ostream& os, const Template& tmpl, const json& data, json* loop_data = nullptr) {
m_data = &data;
m_loop_data = loop_data;

for (size_t i = 0; i < tmpl.bytecodes.size(); ++i) {
const auto& bc = tmpl.bytecodes[i];
Expand Down Expand Up @@ -3470,7 +3478,7 @@ class Renderer {
break;
}
case Bytecode::Op::Include:
Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, *m_data);
Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, *m_data, m_loop_data);
break;
case Bytecode::Op::Callback: {
auto callback = m_callbacks.find_callback(bc.str, bc.args);
Expand Down Expand Up @@ -3505,7 +3513,9 @@ class Renderer {
LoopLevel& level = m_loop_stack.back();
level.value_name = bc.str;
level.values = std::move(m_stack.back());
level.data = (*m_data);
if (m_loop_data) {
level.data = *m_loop_data;
}
level.index = 0;
m_stack.pop_back();

Expand Down Expand Up @@ -3544,8 +3554,8 @@ class Renderer {
(*parent_loop_it)["parent"] = std::move(loop_copy);
}

// set "current" data to loop data
m_data = &level.data;
// set "current" loop data to this level
m_loop_data = &level.data;
update_loop_data();
break;
}
Expand All @@ -3568,9 +3578,9 @@ class Renderer {
m_loop_stack.pop_back();
// set "current" data to outer loop data or main data as appropriate
if (!m_loop_stack.empty()) {
m_data = &m_loop_stack.back().data;
m_loop_data = &m_loop_stack.back().data;
} else {
m_data = &data;
m_loop_data = loop_data;
}
break;
}
Expand Down
Loading