|
3 | 3 |
|
4 | 4 | #include "config.hpp" |
5 | 5 | #include "utils.hpp" |
| 6 | +#include "z3++.h" |
6 | 7 | #include <array> |
7 | 8 | #include <chrono> |
| 9 | +#include <filesystem> |
| 10 | +#include <fstream> |
8 | 11 | #include <iomanip> |
9 | 12 | #include <ratio> |
10 | 13 | #include <string> |
@@ -50,7 +53,33 @@ enum class TimeProfileKind { |
50 | 53 |
|
51 | 54 | class Profile_t { |
52 | 55 | public: |
53 | | - Profile_t() : step_count(0), cache_hit_count(0), cache_miss_count(0) {} |
| 56 | + Profile_t() : step_count(0), cache_hit_count(0), cache_miss_count(0) { |
| 57 | + // refresh the output profile directory |
| 58 | + if (PROFILE_Z3_API_CALL) { |
| 59 | + std::filesystem::path out_path(base_profile_output_path); |
| 60 | + std::error_code ec; |
| 61 | + std::filesystem::remove_all(out_path, ec); |
| 62 | + if (ec) { |
| 63 | + throw std::runtime_error("Failed to clear output directory: " + |
| 64 | + ec.message()); |
| 65 | + } |
| 66 | + std::filesystem::create_directories(out_path, ec); |
| 67 | + if (ec) { |
| 68 | + throw std::runtime_error("Failed to create output directory: " + |
| 69 | + ec.message()); |
| 70 | + } |
| 71 | + std::string record_file = |
| 72 | + base_profile_output_path + "/z3_solver_time_record.csv"; |
| 73 | + std::ofstream ofs(record_file); |
| 74 | + ofs << "Expression file,time spent (s),is_sat\n"; |
| 75 | + ofs.close(); |
| 76 | + std::filesystem::create_directories(z3_expr_output_path, ec); |
| 77 | + if (ec) { |
| 78 | + throw std::runtime_error("Failed to create z3 expr output directory: " + |
| 79 | + ec.message()); |
| 80 | + } |
| 81 | + } |
| 82 | + } |
54 | 83 |
|
55 | 84 | void cache_hit() { |
56 | 85 | if (PROFILE_CACHE) |
@@ -131,11 +160,13 @@ class Profile_t { |
131 | 160 | << std::setprecision(15) |
132 | 161 | << time_count[static_cast<std::size_t>(TimeProfileKind::INSTR)] |
133 | 162 | << std::endl; |
134 | | - std::cout << "Total time in solver (s): " << std::setprecision(15) |
135 | | - << time_count[static_cast<std::size_t>(TimeProfileKind::SOLVER_TOTAL)] |
136 | | - << std::endl; |
| 163 | + std::cout |
| 164 | + << "Total time in solver (s): " << std::setprecision(15) |
| 165 | + << time_count[static_cast<std::size_t>(TimeProfileKind::SOLVER_TOTAL)] |
| 166 | + << std::endl; |
137 | 167 | std::cout << "Total time in z3 api call (s): " << std::setprecision(15) |
138 | | - << time_count[static_cast<std::size_t>(TimeProfileKind::CALL_Z3_SOLVER)] |
| 168 | + << time_count[static_cast<std::size_t>( |
| 169 | + TimeProfileKind::CALL_Z3_SOLVER)] |
139 | 170 | << std::endl; |
140 | 171 | std::cout << "Total time in resuming from snapshot (s): " |
141 | 172 | << std::setprecision(15) |
@@ -227,7 +258,8 @@ class Profile_t { |
227 | 258 | << time_count[static_cast<std::size_t>(TimeProfileKind::INSTR)] |
228 | 259 | << ",\n"; |
229 | 260 | os << " \"total_time_solver_s\": " << std::setprecision(15) |
230 | | - << time_count[static_cast<std::size_t>(TimeProfileKind::CALL_Z3_SOLVER)] |
| 261 | + << time_count[static_cast<std::size_t>( |
| 262 | + TimeProfileKind::CALL_Z3_SOLVER)] |
231 | 263 | << ",\n"; |
232 | 264 | os << " \"total_time_resuming_from_snapshot_s\": " |
233 | 265 | << std::setprecision(15) |
@@ -256,6 +288,30 @@ class Profile_t { |
256 | 288 | os << " }\n"; |
257 | 289 | } |
258 | 290 |
|
| 291 | + void record_z3_solver_time(z3::expr expr, double time, bool is_sat) { |
| 292 | + // Write z3 expression in a file, and write the time spent in solving it and |
| 293 | + // the file path in another file |
| 294 | + if (PROFILE_Z3_API_CALL) { |
| 295 | + static int count = 0; |
| 296 | + std::string expr_file = |
| 297 | + z3_expr_output_path + "/z3_expr_" + std::to_string(count) + ".smt2"; |
| 298 | + std::error_code ec; |
| 299 | + std::ofstream ofs(expr_file); |
| 300 | + ofs << expr; |
| 301 | + ofs.close(); |
| 302 | + std::string record_file = |
| 303 | + base_profile_output_path + "/z3_solver_time_record.csv"; |
| 304 | + std::ofstream rofs(record_file, std::ios::app); |
| 305 | + rofs << expr_file << "," << std::setprecision(15) << time << "," |
| 306 | + << (is_sat ? "sat" : "unsat") << "\n"; |
| 307 | + rofs.close(); |
| 308 | + count++; |
| 309 | + } |
| 310 | + } |
| 311 | + |
| 312 | + std::string base_profile_output_path = "genwasym_profile_output"; |
| 313 | + std::string z3_expr_output_path = "genwasym_profile_output/z3_expressions"; |
| 314 | + |
259 | 315 | // record the time spent in main instruction execution, in seconds |
260 | 316 | void add_instruction_time(TimeProfileKind kind, double time) { |
261 | 317 | time_count[static_cast<std::size_t>(kind)] += time; |
@@ -283,18 +339,26 @@ static Profile_t Profile; |
283 | 339 | class ManagedTimer { |
284 | 340 | public: |
285 | 341 | ManagedTimer() = delete; |
286 | | - ManagedTimer(TimeProfileKind kind) : kind(kind) { |
| 342 | + ManagedTimer(TimeProfileKind kind) : kind(kind), time_ref(nullptr) { |
| 343 | + start = std::chrono::high_resolution_clock::now(); |
| 344 | + } |
| 345 | + ManagedTimer(TimeProfileKind kind, double &time_ref) |
| 346 | + : kind(kind), time_ref(&time_ref) { |
287 | 347 | start = std::chrono::high_resolution_clock::now(); |
288 | 348 | } |
289 | 349 | ~ManagedTimer() { |
290 | 350 | auto end = std::chrono::high_resolution_clock::now(); |
291 | 351 | std::chrono::duration<double> elapsed = end - start; |
292 | 352 | Profile.add_instruction_time(kind, elapsed.count()); |
| 353 | + if (time_ref != nullptr) { |
| 354 | + *time_ref += elapsed.count(); |
| 355 | + } |
293 | 356 | } |
294 | 357 |
|
295 | 358 | private: |
296 | 359 | TimeProfileKind kind; |
297 | 360 | std::chrono::high_resolution_clock::time_point start; |
| 361 | + double *time_ref; |
298 | 362 | }; |
299 | 363 |
|
300 | 364 | using Time = std::chrono::time_point<std::chrono::steady_clock>; |
|
0 commit comments