From e3d208e4826f1d99886f609d77de34f3772027e7 Mon Sep 17 00:00:00 2001 From: Ian Bell <ian.bell@nist.gov> Date: Thu, 1 Jun 2023 09:33:07 -0400 Subject: [PATCH] Switch the C interface to use unsigned long long int for the index At one million indexes per second, half a million years to run out of indices --- interface/C/teqpc.cpp | 57 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/interface/C/teqpc.cpp b/interface/C/teqpc.cpp index 34b3341..515f235 100644 --- a/interface/C/teqpc.cpp +++ b/interface/C/teqpc.cpp @@ -34,14 +34,7 @@ using namespace teqp; // The max possible index is 18,446,744,073,709,551,615 std::atomic<unsigned long long int> next_index{ 0 }; -/// A function for returning a sequential index of the next -std::string get_uid(int N) { - auto s = std::to_string(next_index); - next_index++; - return std::string(N - s.size(), '0') + s; -} - -std::unordered_map<std::string, std::shared_ptr<teqp::cppinterface::AbstractModel>> library; +std::unordered_map<unsigned long long int, std::shared_ptr<teqp::cppinterface::AbstractModel>> library; void exception_handler(int& errcode, char* message_buffer, const int buffer_length) { @@ -58,18 +51,18 @@ void exception_handler(int& errcode, char* message_buffer, const int buffer_leng } } -EXPORT_CODE int CONVENTION build_model(const char* j, char* uuid, char* errmsg, int errmsg_length){ +EXPORT_CODE int CONVENTION build_model(const char* j, unsigned long long int* uuid, char* errmsg, int errmsg_length){ int errcode = 0; try{ nlohmann::json json = nlohmann::json::parse(j); - std::string uid = get_uid(32); + unsigned long long int uid = next_index++; try { library.emplace(std::make_pair(uid, cppinterface::make_model(json))); } catch (std::exception &e) { throw teqpcException(30, "Unable to load with error:" + std::string(e.what())); } - strcpy(uuid, uid.c_str()); + *uuid = uid; } catch (...) { exception_handler(errcode, errmsg, errmsg_length); @@ -77,10 +70,10 @@ EXPORT_CODE int CONVENTION build_model(const char* j, char* uuid, char* errmsg, return errcode; } -EXPORT_CODE int CONVENTION free_model(char* uuid, char* errmsg, int errmsg_length) { +EXPORT_CODE int CONVENTION free_model(const unsigned long long int uuid, char* errmsg, int errmsg_length) { int errcode = 0; try { - library.erase(std::string(uuid)); + library.erase(uuid); } catch (...) { exception_handler(errcode, errmsg, errmsg_length); @@ -88,13 +81,13 @@ EXPORT_CODE int CONVENTION free_model(char* uuid, char* errmsg, int errmsg_lengt return errcode; } -EXPORT_CODE int CONVENTION get_Arxy(const char* uuid, const int NT, const int ND, const double T, const double rho, const double* molefrac, const int Ncomp, double *val, char* errmsg, int errmsg_length) { +EXPORT_CODE int CONVENTION get_Arxy(const unsigned long long int uuid, const int NT, const int ND, const double T, const double rho, const double* molefrac, const int Ncomp, double *val, char* errmsg, int errmsg_length) { int errcode = 0; try { // Make an Eigen view of the double buffer Eigen::Map<const Eigen::ArrayXd> molefrac_(molefrac, Ncomp); // Call the function - *val = library.at(std::string(uuid))->get_Arxy(NT, ND, T, rho, molefrac_); + *val = library.at(uuid)->get_Arxy(NT, ND, T, rho, molefrac_); } catch (...) { exception_handler(errcode, errmsg, errmsg_length); @@ -112,7 +105,8 @@ EXPORT_CODE int CONVENTION get_Arxy(const char* uuid, const int NT, const int ND TEST_CASE("Use of C interface","[teqpc]") { constexpr int errmsg_length = 300; - char uuid[33] = "", uuidPR[33] = "", uuidMF[33] = "", errmsg[errmsg_length] = ""; + unsigned long long int uuid, uuidPR, uuidMF; + char errmsg[errmsg_length] = ""; double val = -1; std::valarray<double> molefrac = { 1.0 }; @@ -126,7 +120,7 @@ TEST_CASE("Use of C interface","[teqpc]") { } } )"; - build_model(j.c_str(), uuidPR, errmsg, errmsg_length); + build_model(j.c_str(), &uuidPR, errmsg, errmsg_length); { nlohmann::json jmodel = nlohmann::json::object(); jmodel["departure"] = ""; @@ -139,7 +133,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jmodel} }; std::string js = j.dump(2); - int e1 = build_model(js.c_str(), uuidMF, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuidMF, errmsg, errmsg_length); } { nlohmann::json jmodel = nlohmann::json::object(); @@ -153,7 +147,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jmodel} }; std::string js = j.dump(2); - int e1 = build_model(js.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuid, errmsg, errmsg_length); CAPTURE(errmsg); REQUIRE(e1 == 0); } @@ -171,13 +165,22 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jmodel} }; std::string js = j.dump(2); - int e1 = build_model(js.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); } + BENCHMARK("vdW1 parse string") { + std::string j = R"({"kind":"vdW1", "model":{"a":1.0, "b":2.0}})"; + return nlohmann::json::parse(j); + }; + BENCHMARK("vdW1 construct only") { + std::string j = R"({"kind":"vdW1", "model":{"a":1.0, "b":2.0}})"; + int e1 = build_model(j.c_str(), &uuid, errmsg, errmsg_length); + return e1; + }; BENCHMARK("vdW1") { std::string j = R"({"kind":"vdW1", "model":{"a":1.0, "b":2.0}})"; - int e1 = build_model(j.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(j.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 0, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); @@ -196,7 +199,7 @@ TEST_CASE("Use of C interface","[teqpc]") { } } )"; - int e1 = build_model(j.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(j.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 0, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); @@ -220,7 +223,7 @@ TEST_CASE("Use of C interface","[teqpc]") { } } )"; - int e1 = build_model(j.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(j.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 1, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); @@ -244,7 +247,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jCPA} }; std::string jstring = j.dump(); - int e1 = build_model(jstring.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(jstring.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 1, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); @@ -266,7 +269,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", model} }; std::string js = j.dump(1); - int e1 = build_model(js.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuid, errmsg, errmsg_length); CAPTURE(errmsg); CAPTURE(js); REQUIRE(e1 == 0); @@ -289,7 +292,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jmodel} }; std::string js = j.dump(2); - int e1 = build_model(js.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 1, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); @@ -311,7 +314,7 @@ TEST_CASE("Use of C interface","[teqpc]") { {"model", jmodel} }; std::string js = j.dump(2); - int e1 = build_model(js.c_str(), uuid, errmsg, errmsg_length); + int e1 = build_model(js.c_str(), &uuid, errmsg, errmsg_length); int e2 = get_Arxy(uuid, 0, 1, 300.0, 3.0e-6, &(molefrac[0]), static_cast<int>(molefrac.size()), &val, errmsg, errmsg_length); int e3 = free_model(uuid, errmsg, errmsg_length); REQUIRE(e1 == 0); -- GitLab