| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
cuJSON is the world's fastest JSON parser, running entirely on your GPU. Forget the old idea that GPUs can't handle complex data parsing—cuJSON proves them wrong. It's built from the ground up to be super parallel, making quick work of everything from validating your data to figuring out its structure.
The result? cuJSON absolutely flies, leaving other top-tier CPU and even existing GPU parsers in the dust. If you're dealing with tons of JSON data, cuJSON is designed to eliminate that bottleneck and speed things up dramatically.
JSON (JavaScript Object Notation) data is widely used in modern computing, yet its parsing performance can be a major bottleneck. Conventional wisdom suggests that GPUs are ill-suited for parsing due to the branch-heavy nature of parsing algorithms. This work challenges that notion by presenting cuJSON, a novel JSON parser built on a redesigned parsing algorithm, specifically tailored for GPU architectures with minimal branching and maximal parallelism.
cuJSON offloads all three key phases of JSON parsing to the GPU: (i) UTF validation, (ii) JSON tokenization, and (iii) nesting structure recognition. Each phase is powered by a highly parallel algorithm optimized for GPUs, effectively leveraging intrinsic GPU functions and high-performance CUDA libraries for acceleration. To maximize the parsing speed, the output of cuJSON is also specially designed in a non-conventional way. Finally, cuJSON is able to break key dependencies in the parsing process, making it possible to accelerate the parsing of a single large JSON file effectively. Evaluation shows that cuJSON not only outperforms highly optimized CPU-based parsers like simdjson and Pison but also surpasses existing GPU-based parsers like cuDF and GPJSON, in terms of both functionality and performance.
This repository contains the official source code for the cuJSON paper. All figures and benchmark results presented in the publication can be fully reproduced using the code provided here.
Ashkan Vedadi Gargary, Soroosh Safari Loaliyan, and Zhijia Zhao. 2025. CuJSON: A Highly Parallel JSON Parser for GPUs. In Proceedings of the 31st ACM International Conference on Architectural Support for Programming Languages and Operating Systems, Volume 1 (ASPLOS '26). Association for Computing Machinery, New York, NY, USA, 85–100. https://doi.org/10.1145/3760250.3762222
For detailed instructions on how to replicate the experimental results and figures from the paper, specially for research purposes and comparison, please refer to the paper_reproduced/ directory.
Additionally, all the scripts are available at paper_reproduced/scripts/readme.md.
Two sample datasets are included in the dataset folder. Large datasets (used in performance evaluation) can be downloaded from https://drive.google.com/drive/folders/1PkDEy0zWOkVREfL7VuINI-m9wJe45P2Q?usp=sharing and placed into the dataset folder. Each dataset comes with two formats:
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
Follow these steps to compile and run the cuJSON examples:
git clone https://github.com/ashkanvg/cuJSON cd cuJSON
nvcc -O3 -std=c++17 -arch=sm_80 main.cu -o cujson_standard.out./cujson_standard.out ./dataset/twitter_sample_large_record.jsonFollow these steps to compile and run the cuJSON examples:
git clone https://github.com/ashkanvg/cuJSON cd cuJSON
Compile main_jsonlines.cu to split the input into four chunks:
nvcc -O3 -std=c++17 -arch=sm_80 main_jsonlines.cu -o cujson_jsonlines_count.outCompile main_jsonlines_chunksize.cu to limit chunks to 256 MiB expressed in bytes:
nvcc -O3 -std=c++17 -arch=sm_80 main_jsonlines_chunksize.cu -o cujson_jsonlines_chunksize_bytes.outCompile main_jsonlines_chunksize_MB.cu to specify the same limit in megabytes:
nvcc -O3 -std=c++17 -arch=sm_80 main_jsonlines_chunksize_MB.cu -o cujson_jsonlines_chunksize_mb.out./cujson_jsonlines_count.out ./dataset/twitter_sample_small_records.json
./cujson_jsonlines_chunksize_bytes.out ./dataset/twitter_sample_small_records.json
./cujson_jsonlines_chunksize_mb.out ./dataset/twitter_sample_small_records.jsonThis section guides you on how to incorporate and utilize the cuJSON library within your own C++/CUDA projects for both standard JSON and JSON Lines parsing.
To integrate cuJSON, you'll generally follow these steps:
Include the cuJSON Source: Copy the entire cujson/ directory from this repository into your project's source tree. Ensure your build system (e.g., nvcc compilation) is configured to compile these files and include their headers.
Include the Main Header: In your source files where you intend to use cuJSON, include its primary header:
#include "cujson/cujson.h"
#include "cujson/cujsonlines.h"
std::string filePath = "./dataset/twitter_sample_large_record.json";
cuJSONInput input = loadJSON(filePath);a. Split based on the number of chunks:
size_t chunkCount = 4;
std::string filePath = "./dataset/twitter_sample_small_records.json";
cuJSONLinesInput input = loadJSONLines_chunkCount(filePath, chunkCount);b. Split based on the maximum chunk size in bytes:
std::string filePath = "./dataset/twitter_sample_small_records.json";
size_t maxChunkSizeBytes = 256 * 1024 * 1024;
cuJSONLinesInput input = loadJSONLines_chunkSizeBytes(filePath, maxChunkSizeBytes);c. Split based on the maximum chunk size in megabytes:
std::string filePath = "./dataset/twitter_sample_small_records.json";
size_t maxChunkSizeMegaBytes = 256;
cuJSONLinesInput input = loadJSONLines_chunkSizeMegaBytes(filePath, maxChunkSizeMegaBytes);cuJSONResult parsed_array = parse_standard_json(input);
cuJSONResult parsed_array = parse_json_lines(input);
| API Method | Description |
|---|---|
| cuJSONInput loadJSON(const std::string& filePath) | Loads a Standard JSON file into a cuJSONInput structure. |
| cuJSONLinesInput loadJSONLines_chunkCount(const std::string& filePath, size_t chunkCount) | Loads a JSON Lines file and splits it into chunkCount chunks. |
| cuJSONLinesInput loadJSONLines_chunkSizeBytes(const std::string& filePath, size_t chunkSizeBytes) | Loads a JSON Lines file and splits it into chunks based on a maximum chunk size (in bytes). |
| cuJSONLinesInput loadJSONLines_chunkSizeMegaBytes(const std::string& filePath, size_t chunkSizeMegaBytes) | Loads a JSON Lines file and splits it into chunks based on a maximum chunk size (in megabytes). |
| cuJSONResult parse_standard_json(cuJSONInput input) | Parses a Standard JSON file after it has been loaded into a cuJSONInput structure. |
| cuJSONResult parse_json_lines(cuJSONLinesInput input) | Parses a JSON Lines file after it has been loaded into a cuJSONLinesInput structure. |
These are the primary data structures for interacting with the cuJSON parser:
struct cuJSONInput {
uint8_t* data; // Pointer to the raw JSON data buffer
size_t size; // The total size (in bytes) of the JSON data in the buffer.
};
struct cuJSONLinesInput {
uint8_t* data; // pointer to the data buffer
size_t chunkCount; // number of chunks in the parser
size_t size; // size of the input data
std::vector<uint8_t*> chunks; // vector of pointers to each chunk
std::vector<size_t> chunksSize; // vector of size to each chunk
};
struct cuJSONResult {
uint8_t* inputJSON; // Raw JSON pointer metadata
int chunkCount; // Number of parsed chunks
int bufferSize; // Parser/iterator buffer metadata
std::vector<int> resultSizes; // Structural result size for each chunk
std::vector<int> resultSizesPrefix; // Prefix sums of per-chunk result sizes
int32_t* structural; // Byte positions of JSON structural characters
int32_t* pair_pos; // Matching closing index for each opening structure
int depth; // Maximum nesting-depth metadata
int totalResultSize; // Combined structural output size
int fileSize; // Structural result span, including boundary entries
};
After parsing, use cuJSONIterator for Standard JSON or cuJSONLinesIterator for JSON Lines. Both iterators use the precomputed pair_pos and structural arrays to skip nested structures and navigate to keys or array elements efficiently.
The iterator classes share the core navigation methods, with two additional helpers available only for JSON Lines.
cuJSONIterator standardIterator(&parsed_array, filePath.c_str());
cuJSONLinesIterator linesIterator(&parsed_array, filePath.c_str());| API Method | Availability | Description |
|---|---|---|
| int gotoKey(std::string key) | Both | Moves to the value associated with key in the current object. |
| int gotoArrayIndex(int index) | Both | Moves to an element in the current array. |
| int increamentIndex(int index) | Both | Advances by index positions in the structural array. This spelling is part of the current public API. |
| int gotoNextSibling(int index) | JSON Lines | Moves to another element in the current array. |
| bool checkKeyValue(std::string key, std::string value) | JSON Lines | Tests whether the current object contains the key-value pair. |
| std::string getKey() | Both | Returns the key at the current iterator position. |
| std::string getValue() | Both | Returns the value at the current iterator position. |
| void reset() | Both | Resets the iterator to the first structural entry. |
| void freeJson() | Both | Releases the iterator and parsed-result allocations. |
For the bundled Standard JSON sample, enter the synthetic root and then the first array element before selecting lang:
standardIterator.gotoArrayIndex(0);
standardIterator.gotoArrayIndex(0);
standardIterator.gotoKey("lang");
std::string value = standardIterator.getValue();For the bundled JSON Lines sample, select the first record and then its top-level lang field:
linesIterator.gotoArrayIndex(0);
linesIterator.gotoKey("lang");
std::string value = linesIterator.getValue();standardIterator.freeJson();
// or
linesIterator.freeJson();For a variety of usage examples, please refer to the files located in the paper_reproduced/query_example/ directory.
| Back | FazBrowse Home | New Git URL |