Skip to content
Open
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
15 changes: 6 additions & 9 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
## 2026-05-03 - [Optimize XML Parsing via Lazy Initialization]
**Learning:** In C++ codebases like Vasati that heavily rely on parsing large XML datasets (e.g., `Vakitler.xml` using `pugixml`), parsing the document repeatedly upon every instantiation of a core class (`zaman`) creates a massive performance bottleneck.
**Action:** Implemented lazy initialization (a `static bool is_loaded` flag along with making `pugi::xml_document` and `pugi::xml_node` static members) so that the XML document is loaded only once per program lifecycle. This simple change yields a roughly ~3x performance boost for object instantiation (from ~3.8s down to ~1.1s for 10000 object instantiations).
## 2026-05-08 - [XML Parsing Optimization]
**Learning:** Parsing the XML document in the constructor of `zaman` class without caching causes a significant performance bottleneck (around 40ms per 100 instantiations). Repeatedly loading the file creates high overhead.
**Action:** Used a C++11 method-local magic static and an immediately invoked lambda to cache the `cityinfo` XML node (`zaman::sehir`), reducing 100 instantiations from ~40ms to ~14ms.
## 2024-05-24 - `zaman::td_to_vakt` and String Allocation Optimization
**Learning:** In C++, frequently called formatting functions like `td_to_vakt` and `zaman::sat_turk_v_d` that use multiple `std::to_string` allocations and string concatenations (`+` or `.append()`) suffer from high memory allocation overhead, creating severe memory and CPU bottlenecks.
**Action:** Replace dynamic allocations inside highly-called utility functions with manual, fixed-size stack buffers (`char buf[]`) and direct ASCII arithmetic (`'0' + value`) to entirely bypass temporary string objects. This reduces execution time significantly in string formatting benchmarks.

## 2024-05-11 - [XML Lookup Optimization]
**Learning:** Repeatedly calling `pugi::xml_node::find_child_by_attribute` to look up prayer times by `dayofyear` is an O(N) linear search bottleneck that slows down `zaman` class instantiations.
**Action:** Replaced it with an O(1) array lookup. Since `dayofyear` acts as a sequential 0-based index (0-365), we can cache the `const char*` text of each `prayertimes` node into a static `cached_nodes[400]` array using a magic static block. This reduced instantiation time nearly by half.
## 2024-05-24 - `zaman::td_to_vakt` and String Allocation Optimization
**Learning:** In C++, frequently called formatting functions like `td_to_vakt` and `zaman::sat_turk_v_d` that use multiple `std::to_string` allocations and string concatenations (`+` or `.append()`) suffer from high memory allocation overhead, creating severe memory and CPU bottlenecks.
**Action:** Replace dynamic allocations inside highly-called utility functions with manual, fixed-size stack buffers (`char buf[]`) and direct ASCII arithmetic (`'0' + value`) to entirely bypass temporary string objects. This reduces execution time significantly in string formatting benchmarks.
44 changes: 26 additions & 18 deletions src/src-class/Zaman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,26 @@ unsigned int zaman::vakt_to_td(const std::string& vakt)

std::string zaman::td_to_vakt(unsigned int td)
{
return std::to_string(int(td / 60) % 12) + ":" + std::to_string(int(td % 60));
// ⚡ Bolt Optimizasyonu: std::to_string() yerine sabit boyutlu stack buffer kullanarak
// heap tahsisi ve string birleştirme masrafını (allocation overhead) ortadan kaldırdık.
char buf[6];
int h = int(td / 60) % 12;
int m = int(td % 60);
int pos = 0;
if (h >= 10) {
buf[pos++] = '0' + (h / 10);
buf[pos++] = '0' + (h % 10);
} else {
buf[pos++] = '0' + h;
}
buf[pos++] = ':';
if (m >= 10) {
buf[pos++] = '0' + (m / 10);
buf[pos++] = '0' + (m % 10);
} else {
buf[pos++] = '0' + m;
}
return std::string(buf, pos);
}

void zaman::vkt_h_v_d()
Expand All @@ -89,7 +108,7 @@ void zaman::vkt_h_v_d()

char buffer[5];

static const pugi::xml_node* cached_nodes = []() {
static const char** cached_nodes_text = []() {
static pugi::xml_document doc;
if (!doc.load_file("include/XML/Vakitler.xml") && !doc.load_file("vakitler.xml")) {
throw std::runtime_error("XML load failed");
Expand All @@ -99,28 +118,17 @@ void zaman::vkt_h_v_d()
throw std::runtime_error("Missing cityinfo node");
}

// ⚡ Bolt Optimizasyonu: XML düğümlerini 'dayofyear' özniteliğine göre önbelleğe alarak O(1) erişim sağla (O(N) doğrusal arama yerine)
// Her nesne örneği oluşturulduğunda O(N) doğrusal arama darboğazını ortadan kaldırır
static pugi::xml_node nodes[400];
static const char* texts[400] = {nullptr};
for (pugi::xml_node pt = node.child("prayertimes"); pt; pt = pt.next_sibling("prayertimes")) {
int day = pt.attribute("dayofyear").as_int(-1);
if (day >= 0 && day < 400) {
nodes[day] = pt;
texts[day] = pt.text().get();
}
}
return nodes;
}();

static const char* cached_nodes[400] = {nullptr};
static bool cached_nodes_init = []() {
for (pugi::xml_node pt = cached_sehir.child("prayertimes"); pt; pt = pt.next_sibling("prayertimes")) {
int day = std::atoi(pt.attribute("dayofyear").value());
if (day >= 0 && day < 400) cached_nodes[day] = pt.text().get();
}
return true;
return texts;
}();

zaman::xml_bu_gun = (zaman::h_rakam_gun_senenin >= 0 && zaman::h_rakam_gun_senenin < 400 && cached_nodes[zaman::h_rakam_gun_senenin]) ? cached_nodes[zaman::h_rakam_gun_senenin] : "";
zaman::xml_bu_gun = (zaman::h_rakam_gun_senenin >= 0 && zaman::h_rakam_gun_senenin < 400 && cached_nodes_text[zaman::h_rakam_gun_senenin]) ? cached_nodes_text[zaman::h_rakam_gun_senenin] : "";

zaman::h_aksam = zaman::xml_bu_gun.substr(50, 6);
zaman::h_istibak_nucum = zaman::xml_bu_gun.substr(56, 6);
Expand All @@ -130,7 +138,7 @@ void zaman::vkt_h_v_d()
//buradaka kodları yeniliyoruz çünkü bir sonraki gün kılacağız verileri:

int next_day = zaman::h_rakam_gun_senenin + 1;
zaman::xml_bu_gun = (next_day >= 0 && next_day < 400 && cached_nodes[next_day]) ? cached_nodes[next_day] : "";
zaman::xml_bu_gun = (next_day >= 0 && next_day < 400 && cached_nodes_text[next_day]) ? cached_nodes_text[next_day] : "";

zaman::h_imsak = zaman::xml_bu_gun.substr(0, 4) ;
zaman::h_sabah = zaman::xml_bu_gun.substr(5, 5) ;
Expand Down