Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4ef9e38
[aws][system] Add C++ dependencies images
mcopik May 3, 2022
2dc3894
[aws][system] Add C++ dependencies images
mcopik May 3, 2022
3dd45ef
[aws] Change name style of C++ Docker images
mcopik May 7, 2022
72b88ad
[aws] Add AWS C++ Lambda runtime as dependency
mcopik May 7, 2022
1cdcc74
[aws] Add the basic wrapper for C++
mcopik May 7, 2022
17c69fe
[aws] Add Docker build container for C++
mcopik May 7, 2022
53f81f7
[benchmarks] Add sleep benchmark implementation for C++
mcopik May 7, 2022
67560c8
[aws] Define necessary package files for C++
mcopik May 7, 2022
a9b5218
[system] Add Docker build arguments for C++ images
mcopik May 7, 2022
3c3700c
[aws] Implement correct return from C++
mcopik May 7, 2022
61bbffa
[aws] [system] First version of support for C++ benchmarks
mcopik May 7, 2022
89d29e7
[aws] Add Boost UUID in handler
mcopik May 7, 2022
5db9fc2
[aws] Support HTTP trigger for C++
mcopik May 7, 2022
c6a1a81
[aws] Minor update of C++ dependencies
mcopik May 7, 2022
dc3df69
[aws] Add key-value wrapper for C++ benchmarks
mcopik May 15, 2022
eb5d0b6
[benchmarks] Linting
mcopik May 15, 2022
2f035fc
[system] Add logging of C++ build steps
mcopik May 15, 2022
1c5d85c
[aws] Add Redis wrappers for C++
mcopik May 15, 2022
9a96d72
[aws] Move Dockerfiles to a new directory
mcopik Jun 18, 2025
b5fbb12
[dev] Linting
mcopik Jun 18, 2025
a8239a1
[aws] Rename C++ utility function and apply formatting
mcopik Jun 19, 2025
8e1f93a
[aws] Pin hiredis version
mcopik Jun 19, 2025
b7ab8e4
[aws] Fix merge error
mcopik Jun 19, 2025
068adfd
[aws] Fix various bugs for C++ benchmarks, as pointed out during review
mcopik Jun 19, 2025
ef25201
[aws] Fix generation of cloud runtime
mcopik Jun 20, 2025
3fa330f
[aws] Add architecture configuration for cpp base images. Ensure the …
HoriaMercan Jun 25, 2025
1ff7b98
Implemented 210-thumbnail benchmark in cpp.
HoriaMercan Jun 29, 2025
faf4ffd
[aws] Added docker dependencies for opencv
HoriaMercan Jun 29, 2025
bd9a88a
Delete Base64.hpp file
HoriaMercan Jul 2, 2025
85ff323
Optimize storage.cpp by using boost's bufferstream
HoriaMercan Jul 2, 2025
6ae77be
Added cpp support for graph pagerank
HoriaMercan Jul 7, 2025
6114498
Added C++ in config for Pagerank Benchmark
HoriaMercan Jul 8, 2025
330d543
Added cpp_dependencies config for building CMakeList.txt for thumbnai…
HoriaMercan Jul 8, 2025
53c3c07
Added graph-bfs benchmark in C++ AWS
HoriaMercan Jul 8, 2025
3f55a9d
Added Torch & TorchVIsion dependencies to C++. Added image-recognitio…
HoriaMercan Jul 10, 2025
5a1557d
[lint] Remove dead code
HoriaMercan Oct 13, 2025
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
2 changes: 1 addition & 1 deletion benchmarks/000.microbenchmarks/010.sleep/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"timeout": 120,
"memory": 128,
"languages": ["python", "nodejs"],
"languages": ["python", "nodejs", "cpp"],
"modules": []
}
22 changes: 22 additions & 0 deletions benchmarks/000.microbenchmarks/010.sleep/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

#include <aws/core/Aws.h>
#include <aws/core/utils/json/JsonSerializer.h>
#include <aws/lambda-runtime/runtime.h>

#include <thread>
#include <iostream>

Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView json)
{
int sleep = json.GetInteger("sleep");

std::chrono::seconds timespan(sleep);
std::this_thread::sleep_for(timespan);

//std::string res_json = "{ \"result\": " + std::to_string(sleep) + "}";
//return aws::lambda_runtime::invocation_response::success(res_json, "application/json");
Aws::Utils::Json::JsonValue val;
val.WithObject("result", std::to_string(sleep));
return val;
}

5 changes: 3 additions & 2 deletions benchmarks/200.multimedia/210.thumbnailer/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 60,
"memory": 256,
"languages": ["python", "nodejs"],
"modules": ["storage"]
"languages": ["python", "nodejs", "cpp"],
"modules": ["storage"],
"cpp_dependencies": ["opencv", "boost"]
}
27 changes: 27 additions & 0 deletions benchmarks/200.multimedia/210.thumbnailer/cpp/function.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>

void thumbnailer(cv::Mat &in, int64_t width, int64_t height, cv::Mat &out)
{
try
{
// Calculate thumbnail size while maintaining aspect ratio
int orig_width = in.cols;
int orig_height = in.rows;

double scale_w = static_cast<double>(width) / orig_width;
double scale_h = static_cast<double>(height) / orig_height;
double scale = std::min(scale_w, scale_h); // Use smaller scale to fit within bounds

int new_width = static_cast<int>(orig_width * scale);
int new_height = static_cast<int>(orig_height * scale);

// Resize image (equivalent to PIL's thumbnail method)
cv::resize(in, out, cv::Size(new_width, new_height), cv::INTER_LINEAR);
}
catch (const cv::Exception &e)
{
std::cerr << "OpenCV error: " << e.what() << std::endl;
}
}
Comment on lines +7 to +27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Rethrow exceptions to avoid swallowing errors.

The catch block logs the error but doesn't rethrow, leaving the out parameter in an undefined state. The caller has no way to detect that the operation failed, which could lead to silent failures downstream.

Apply this diff to rethrow the exception:

   catch (const cv::Exception &e)
   {
     std::cerr << "OpenCV error: " << e.what() << std::endl;
+    throw;
   }
🤖 Prompt for AI Agents
In benchmarks/200.multimedia/210.thumbnailer/cpp/function.hpp around lines 7 to
27, the catch block logs OpenCV errors but swallows the exception leaving `out`
undefined and the caller unaware of failure; after logging the error, rethrow
the exception (use `throw;` to preserve the original exception) so the failure
propagates to the caller and they can handle it appropriately.

117 changes: 117 additions & 0 deletions benchmarks/200.multimedia/210.thumbnailer/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@

#include <aws/core/Aws.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <iostream>
#include <vector>

#include "function.hpp"
#include "storage.hpp"
#include "utils.hpp"

Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView request)
{
sebs::Storage client_ = sebs::Storage::get_client();

auto bucket_obj = request.GetObject("bucket");
if (!bucket_obj.IsObject())
{
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Bucket object is not valid.");
return error;
}
auto bucket_name = bucket_obj.GetString("bucket");
auto input_key_prefix = bucket_obj.GetString("input");
auto output_key_prefix = bucket_obj.GetString("output");

auto image_name = request.GetObject("object").GetString("key");
auto width = request.GetObject("object").GetInteger("width");
auto height = request.GetObject("object").GetInteger("height");

Comment on lines +31 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate presence and types of object.key/width/height.

Avoid crashes when fields are missing or wrong types.

Apply this diff:

-  auto image_name = request.GetObject("object").GetString("key");
-  auto width = request.GetObject("object").GetInteger("width");
-  auto height = request.GetObject("object").GetInteger("height");
+  if (!request.ValueExists("object") ||
+      !request.GetObject("object").ValueExists("key") ||
+      !request.GetObject("object").ValueExists("width") ||
+      !request.GetObject("object").ValueExists("height")) {
+    Aws::Utils::Json::JsonValue error;
+    error.WithString("error", "Missing object.key/width/height.");
+    return error;
+  }
+  auto image_name = request.GetObject("object").GetString("key");
+  auto width = request.GetObject("object").GetInteger("width");
+  auto height = request.GetObject("object").GetInteger("height");
+  if (width <= 0 || height <= 0) {
+    Aws::Utils::Json::JsonValue error;
+    error.WithString("error", "Width/height must be positive.");
+    return error;
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto image_name = request.GetObject("object").GetString("key");
auto width = request.GetObject("object").GetInteger("width");
auto height = request.GetObject("object").GetInteger("height");
if (!request.ValueExists("object") ||
!request.GetObject("object").ValueExists("key") ||
!request.GetObject("object").ValueExists("width") ||
!request.GetObject("object").ValueExists("height")) {
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Missing object.key/width/height.");
return error;
}
auto image_name = request.GetObject("object").GetString("key");
auto width = request.GetObject("object").GetInteger("width");
auto height = request.GetObject("object").GetInteger("height");
if (width <= 0 || height <= 0) {
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Width/height must be positive.");
return error;
}
🤖 Prompt for AI Agents
In benchmarks/200.multimedia/210.thumbnailer/cpp/main.cpp around lines 31 to 34,
the code assumes request.GetObject("object") always contains "key", "width", and
"height" with correct types; add defensive checks to validate existence and
types before using them: verify the top-level "object" exists and is an object,
check that "key" exists and is a string, and that "width" and "height" exist and
are integers (or convertible), and if any check fails return or throw a
descriptive error (or set an error response) instead of proceeding; use the
appropriate API (HasMember/isString/isInt or equivalent) to test types and
extract values safely.

std::string body_str;
uint64_t download_time;
{
std::string input_key = input_key_prefix + "/" + image_name;
auto ans = client_.download_file(bucket_name, input_key);
body_str = std::get<0>(ans);
download_time = std::get<1>(ans);

if (body_str.empty())
{
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Failed to download object from S3: " + input_key);
return error;
}
}

std::vector<char> vectordata(body_str.begin(), body_str.end());
cv::Mat image = imdecode(cv::Mat(vectordata), 1);

// Apply the thumbnailer function and measure the computing time
cv::Mat image2;
uint64_t computing_time;
{
auto start_time = timeSinceEpochMicrosec();
thumbnailer(image, width, height, image2);
computing_time = timeSinceEpochMicrosec() - start_time;
}

std::vector<unsigned char> out_buffer;
cv::imencode(".jpg", image2, out_buffer);

// Create a unique key name for the output image
std::string key_name;
{
std::string output_key = output_key_prefix + "/" + image_name;
std::string name, extension;
if (output_key.find_last_of('.') != std::string::npos)
{
name = output_key.substr(0, output_key.find_last_of('.'));
extension = output_key.substr(output_key.find_last_of('.'));
}
else
{
name = output_key;
extension = "";
}
key_name = name + "."
+ boost::uuids::to_string(boost::uuids::random_generator()())
+ extension;
}

// Upload the resulting image to S3
// If the upload fails, return an error
Aws::String upload_data(out_buffer.begin(), out_buffer.end());

uint64_t upload_time = client_.upload_random_file(
bucket_name, key_name, true,
reinterpret_cast<char *>(out_buffer.data()), out_buffer.size());

if (upload_time == 0)
{
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Failed to upload object to S3: " + key_name);
return error;
}


Aws::Utils::Json::JsonValue val;
Aws::Utils::Json::JsonValue result;
Aws::Utils::Json::JsonValue measurements;

result.WithString("bucket", bucket_name);
result.WithString("key", key_name);
val.WithObject("result", result);

measurements.WithInteger("download_time", download_time);
measurements.WithInteger("upload_time", upload_time);
measurements.WithInteger("compute_time", computing_time);
measurements.WithInteger("download_size", vectordata.size());
measurements.WithInteger("upload_size", out_buffer.size());
val.WithObject("measurements", measurements);
return val;
}
5 changes: 3 additions & 2 deletions benchmarks/400.inference/411.image-recognition/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 60,
"memory": 512,
"languages": ["python"],
"modules": ["storage"]
"languages": ["python", "cpp"],
"modules": ["storage"],
"cpp_dependencies": ["torch", "opencv"]
}
116 changes: 116 additions & 0 deletions benchmarks/400.inference/411.image-recognition/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include <aws/core/Aws.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <iostream>
#include <vector>

#include "utils.hpp"
#include "storage.hpp"

#include <torch/torch.h>
#include <torch/script.h>

#include <torchvision/vision.h>
#include <torchvision/models/resnet.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>


#define kIMAGE_SIZE 224
#define kCHANNELS 3
#define kTOP_K 3


bool load_image(cv::Mat &image)
{

if (image.empty() || !image.data)
{
return false;
}
cv::cvtColor(image, image, cv::COLOR_BGR2RGB);

int w = image.size().width, h = image.size().height;
cv::Size scale((int)256 * ((float)w) / h, 256);
cv::resize(image, image, scale);
w = image.size().width, h = image.size().height;
image = image(cv::Range(16, 240), cv::Range(80, 304));
image.convertTo(image, CV_32FC3, 1.0f / 255.0f);

Comment on lines +37 to +43
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Unsafe fixed ROI crop; center-crop robustly after resizing the shorter side.

Current indices can go out of bounds (e.g., width 256). Replace with size-aware crop.

-    int w = image.size().width, h = image.size().height;
-    cv::Size scale((int)256 * ((float)w) / h, 256);
-    cv::resize(image, image, scale);
-    w = image.size().width, h = image.size().height;
-    image = image(cv::Range(16, 240), cv::Range(80, 304));
-    image.convertTo(image, CV_32FC3, 1.0f / 255.0f);
+    int w = image.cols, h = image.rows;
+    int short_side = std::min(w, h);
+    cv::Size scaled(
+        static_cast<int>(std::round(w * 256.0 / short_side)),
+        static_cast<int>(std::round(h * 256.0 / short_side)));
+    cv::resize(image, image, scaled);
+    w = image.cols; h = image.rows;
+    int x = std::max(0, std::min((w - kIMAGE_SIZE) / 2, w - kIMAGE_SIZE));
+    int y = std::max(0, std::min((h - kIMAGE_SIZE) / 2, h - kIMAGE_SIZE));
+    image = image(cv::Rect(x, y, kIMAGE_SIZE, kIMAGE_SIZE));
+    image.convertTo(image, CV_32FC3, 1.0f / 255.0f);

Committable suggestion skipped: line range outside the PR's diff.

return true;
}

int recognition(cv::Mat &image)
{

static bool initialized = false;
static torch::jit::script::Module module;
if (!initialized)
{
try
{
std::cout << "Initialize ResNet50 model" << std::endl;
module = torch::jit::load("./resnet50.pt");
}
catch (const c10::Error &e)
{
std::cerr << "error loading the model\n";
return -1;
}
initialized = true;
}

if (load_image(image))
{

auto input_tensor = torch::from_blob(
image.data, {1, kIMAGE_SIZE, kIMAGE_SIZE, kCHANNELS});
input_tensor = input_tensor.permute({0, 3, 1, 2});

input_tensor[0][0] = input_tensor[0][0].sub_(0.485).div_(0.229);
input_tensor[0][1] = input_tensor[0][1].sub_(0.456).div_(0.224);
input_tensor[0][2] = input_tensor[0][2].sub_(0.406).div_(0.225);

torch::Tensor out_tensor = module.forward({input_tensor}).toTensor();
auto results = out_tensor.sort(-1, true);
auto softmaxs = std::get<0>(results)[0].softmax(0);
auto indexs = std::get<1>(results)[0];

std::cout << indexs[0].item<int>() << " " << softmaxs[0].item<double>() << std::endl;
return indexs[0].item<int>();


}

return -1;
}

Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView request)
{
sebs::Storage client_ = sebs::Storage::get_client();

auto bucket_obj = request.GetObject("bucket");
if (!bucket_obj.IsObject())
{
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Bucket object is not valid.");
return error;
}

auto bucket_name = bucket_obj.GetString("bucket");
auto input_prefix = bucket_obj.GetString("input");
auto model_prefix = bucket_obj.GetString("model");
auto key = request.GetObject("object").GetString("input");
auto model_key = request.GetObject("object").GetString("model");

Comment on lines +96 to +109
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate request schema before GetString() calls.

Guard against missing keys to prevent exceptions.

-    auto bucket_obj = request.GetObject("bucket");
-    if (!bucket_obj.IsObject())
+    if (!request.ValueExists("bucket") || !request.GetObject("bucket").IsObject())
     {
         Aws::Utils::Json::JsonValue error;
         error.WithString("error", "Bucket object is not valid.");
         return error;
     }
-
-    auto bucket_name = bucket_obj.GetString("bucket");
-    auto input_prefix = bucket_obj.GetString("input");
-    auto model_prefix = bucket_obj.GetString("model");
-    auto key = request.GetObject("object").GetString("input");
-    auto model_key = request.GetObject("object").GetString("model");
+    auto bucket_obj = request.GetObject("bucket");
+    if (!bucket_obj.ValueExists("bucket") || !bucket_obj.ValueExists("input") || !bucket_obj.ValueExists("model")
+        || !request.ValueExists("object")
+        || !request.GetObject("object").ValueExists("input")
+        || !request.GetObject("object").ValueExists("model")) {
+        Aws::Utils::Json::JsonValue error;
+        error.WithString("error", "Missing required keys: bucket.bucket/input/model and object.input/model.");
+        return error;
+    }
+    auto bucket_name = bucket_obj.GetString("bucket");
+    auto input_prefix = bucket_obj.GetString("input");
+    auto model_prefix = bucket_obj.GetString("model");
+    auto key = request.GetObject("object").GetString("input");
+    auto model_key = request.GetObject("object").GetString("model");
🤖 Prompt for AI Agents
In benchmarks/400.inference/411.image-recognition/cpp/main.cpp around lines 96
to 109, the code calls GetString() on JSON members without checking they exist
or are strings; add guards that verify bucket_obj has the keys "bucket",
"input", and "model" and that request.GetObject("object") has "input" and
"model", and confirm each member IsString()/HasMember() (or equivalent) before
calling GetString(); if any check fails, build and return an
Aws::Utils::Json::JsonValue error with a clear message indicating which key is
missing or of the wrong type.


Aws::Utils::Json::JsonValue val;
Aws::Utils::Json::JsonValue result;
Aws::Utils::Json::JsonValue measurements;

return val;
}
5 changes: 3 additions & 2 deletions benchmarks/500.scientific/501.graph-pagerank/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 120,
"memory": 512,
"languages": ["python"],
"modules": []
"languages": ["python", "cpp"],
"modules": [],
"cpp_dependencies": ["igraph"]
}
56 changes: 56 additions & 0 deletions benchmarks/500.scientific/501.graph-pagerank/cpp/function.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

#include <igraph.h>

#include <cfloat>

#include "utils.hpp"

igraph_real_t graph_pagerank
(int size, uint64_t seed, uint64_t &graph_generation_time_ms, uint64_t &compute_pr_time_ms)
{
igraph_t graph;
igraph_vector_t pagerank;
igraph_real_t value;

igraph_rng_seed(igraph_rng_default(), seed);
{
uint64_t start_time = timeSinceEpochMicrosec();
igraph_barabasi_game(
/* graph= */ &graph,
/* n= */ size,
/* power= */ 1,
/* m= */ 10,
/* outseq= */ NULL,
Comment on lines +17 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Boundary checks for Barabási–Albert parameters.

m=10 requires size > 10; for smaller graphs igraph may error. Guard inputs or scale m.

Apply this diff:

-  igraph_rng_seed(igraph_rng_default(), seed);
+  igraph_rng_seed(igraph_rng_default(), seed);
   {
     uint64_t start_time = timeSinceEpochMicrosec();
-    igraph_barabasi_game(
+    int m = size > 1 ? std::min(10, size - 1) : 1;
+    igraph_barabasi_game(
       /* graph=    */ &graph,
       /* n=        */ size,
       /* power=    */ 1,
-      /* m=        */ 10,
+      /* m=        */ m,

Also applies to: 29-35

🤖 Prompt for AI Agents
In benchmarks/500.scientific/501.graph-pagerank/cpp/function.hpp around lines
17-23 (and similarly at 29-35), the call uses m=10 unconditionally which will
fail when size <= 10; compute a safe m before calling igraph_barabasi_game
(e.g., cap m to size-1 and ensure it is at least 1: m = (size > 1) ? min(10,
(int)size - 1) : 1), then pass that m to igraph_barabasi_game; apply the same
defensive m calculation to the second occurrence at lines 29-35.

/* outpref= */ 0,
/* A= */ 1.0,
/* directed= */ 0,
/* algo= */ IGRAPH_BARABASI_PSUMTREE_MULTIPLE,
Comment on lines +26 to +27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Directedness mismatch: graph is undirected, PageRank called as directed.

You create an undirected graph (directed=0) but call igraph_pagerank with IGRAPH_DIRECTED. Use IGRAPH_UNDIRECTED or generate a directed graph consistently.

Apply this diff to keep it undirected:

-      /* directed= */ 0,
+      /* directed= */ 0,
@@
-                    igraph_vss_all(), IGRAPH_DIRECTED,
+                    igraph_vss_all(), IGRAPH_UNDIRECTED,

Also applies to: 36-40

🤖 Prompt for AI Agents
In benchmarks/500.scientific/501.graph-pagerank/cpp/function.hpp around lines
26-27 (and similarly lines 36-40), the graph is constructed as undirected
(directed=0) but PageRank is being invoked with IGRAPH_DIRECTED; change the
PageRank call to use IGRAPH_UNDIRECTED (or construct the graph with directed=1)
so the directedness is consistent—update the enum/flag passed to igraph_pagerank
to IGRAPH_UNDIRECTED in both places to match the graph construction.

/* start_from= */ 0
);
graph_generation_time_ms = (timeSinceEpochMicrosec() - start_time);
}

igraph_vector_init(&pagerank, 0);
{
uint64_t start_time = timeSinceEpochMicrosec();
igraph_pagerank(&graph, IGRAPH_PAGERANK_ALGO_PRPACK,
&pagerank, &value,
igraph_vss_all(), IGRAPH_DIRECTED,
/* damping */ 0.85, /* weights */ NULL,
NULL /* not needed with PRPACK method */);
compute_pr_time_ms = (timeSinceEpochMicrosec() - start_time);
}
/* Check that the eigenvalue is 1, as expected. */
if (fabs(value - 1.0) > 32*DBL_EPSILON) {
fprintf(stderr, "PageRank failed to converge.\n");
return 1;
}
Comment on lines +44 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Early return leaks resources (graph and pagerank vector).

On convergence failure you return without destroying pagerank and graph.

Apply this minimal fix:

   if (fabs(value - 1.0) > 32*DBL_EPSILON) {
       fprintf(stderr, "PageRank failed to converge.\n");
-      return 1;
+      igraph_vector_destroy(&pagerank);
+      igraph_destroy(&graph);
+      return 1;
   }

Also applies to: 51-54

🤖 Prompt for AI Agents
In benchmarks/500.scientific/501.graph-pagerank/cpp/function.hpp around lines
44-47 (and similarly for lines 51-54), the early return on convergence failure
leaks the pagerank vector and graph; before returning make sure to release both
resources by invoking the same cleanup used on the success path (e.g.,
delete/free the pagerank array and call the graph destroy/free function or
destructor used elsewhere in the file), then log the error and return the
failure code.


igraph_real_t result = VECTOR(pagerank)[0];

igraph_vector_destroy(&pagerank);
igraph_destroy(&graph);

return result;
}

Loading