mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Adding initial toy_example that shows why reflection is almost frictionless to use.
This commit is contained in:
+21
@@ -49,6 +49,27 @@ objs
|
||||
|
||||
# C++ ignore from https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore
|
||||
|
||||
# CMake build artifacts
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
simdjson-config*.cmake
|
||||
simdjson-props.cmake
|
||||
simdjson.pc
|
||||
|
||||
# Build directories
|
||||
deps/
|
||||
examples/build_*/
|
||||
examples/*_demo
|
||||
examples/*_benchmark
|
||||
|
||||
# Temporary files
|
||||
examples/CMakeLists_demo.txt
|
||||
examples/simple_http.h
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
# 🛠️ Build Instructions for simdjson One-Liner Demo
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### For Both Examples
|
||||
- **cpr library** (for HTTP requests) - See [INSTALL_CPR.md](INSTALL_CPR.md) for installation
|
||||
- **curl library** (cpr dependency) - Usually pre-installed on most systems
|
||||
- **simdjson library** - Included in this repository
|
||||
|
||||
### For Legacy Example (github_legacy.cpp)
|
||||
- Any C++20 compatible compiler (GCC 10+, Clang 10+, MSVC 2019+)
|
||||
|
||||
### For Modern Example (github_modern.cpp)
|
||||
- Bloomberg Clang fork with C++26 reflection support
|
||||
- Get it from: https://github.com/bloomberg/clang-p2996
|
||||
|
||||
## 🔨 Compilation Commands
|
||||
|
||||
### Quick Setup (Recommended)
|
||||
|
||||
1. **Build cpr from source** (if not installed system-wide):
|
||||
```bash
|
||||
# From the examples directory
|
||||
mkdir -p ../deps && cd ../deps
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr && git checkout 1.10.5
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCPR_USE_SYSTEM_CURL=ON -DBUILD_SHARED_LIBS=OFF -DCPR_ENABLE_SSL=OFF
|
||||
make -j4
|
||||
cd ../../../examples
|
||||
```
|
||||
|
||||
2. **Compile the examples**:
|
||||
```bash
|
||||
# Legacy approach (any C++20 compiler)
|
||||
clang++ -std=c++20 \
|
||||
-I../deps/cpr/include \
|
||||
-I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. \
|
||||
github_legacy.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a \
|
||||
-lcurl -pthread \
|
||||
-o github_legacy_demo
|
||||
|
||||
# Modern approach (Bloomberg clang with reflection)
|
||||
clang++ -std=c++26 -freflection \
|
||||
-DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../deps/cpr/include \
|
||||
-I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. \
|
||||
github_modern.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a \
|
||||
-lcurl -pthread \
|
||||
-o github_modern_demo
|
||||
```
|
||||
|
||||
### Using System-Installed cpr
|
||||
|
||||
If cpr is installed system-wide (see [INSTALL_CPR.md](INSTALL_CPR.md)):
|
||||
|
||||
```bash
|
||||
# Legacy approach
|
||||
clang++ -std=c++20 \
|
||||
-I../include -I.. \
|
||||
github_legacy.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_legacy_demo
|
||||
|
||||
# Modern approach
|
||||
clang++ -std=c++26 -freflection \
|
||||
-DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../include -I.. \
|
||||
github_modern.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_modern_demo
|
||||
```
|
||||
|
||||
### Using simdjson Single Header
|
||||
|
||||
```bash
|
||||
# Legacy approach
|
||||
clang++ -std=c++20 \
|
||||
-I../singleheader \
|
||||
github_legacy.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_legacy_demo
|
||||
|
||||
# Modern approach
|
||||
clang++ -std=c++26 -freflection \
|
||||
-DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../singleheader -I../include \
|
||||
github_modern.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_modern_demo
|
||||
```
|
||||
|
||||
### Using CMake (Recommended)
|
||||
|
||||
```bash
|
||||
# Create build directory
|
||||
mkdir build && cd build
|
||||
|
||||
# Configure with CMake
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCMAKE_CXX_STANDARD=26 \
|
||||
-DCMAKE_CXX_FLAGS="-freflection -DSIMDJSON_STATIC_REFLECTION=1"
|
||||
|
||||
# Build both examples
|
||||
make github_legacy github_modern
|
||||
```
|
||||
|
||||
### Quick Build with simdjson Single Header
|
||||
|
||||
```bash
|
||||
# Legacy approach
|
||||
clang++ -std=c++20 \
|
||||
-I../singleheader \
|
||||
github_legacy.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_legacy_demo
|
||||
|
||||
# Modern approach
|
||||
clang++ -std=c++26 -freflection \
|
||||
-DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../singleheader \
|
||||
github_modern.cpp \
|
||||
../singleheader/simdjson.cpp \
|
||||
-lcpr -lcurl \
|
||||
-o github_modern_demo
|
||||
```
|
||||
|
||||
## 🏃 Running the Examples
|
||||
|
||||
```bash
|
||||
# Run legacy version
|
||||
./github_legacy_demo
|
||||
|
||||
# Run modern version
|
||||
./github_modern_demo
|
||||
```
|
||||
|
||||
## 🎯 Platform-Specific Notes
|
||||
|
||||
### Linux (x86_64)
|
||||
```bash
|
||||
-DSIMDJSON_IMPLEMENTATION_HASWELL=1
|
||||
```
|
||||
|
||||
### Linux (ARM64)
|
||||
```bash
|
||||
-DSIMDJSON_IMPLEMENTATION_ARM64=1
|
||||
```
|
||||
|
||||
### macOS (Apple Silicon)
|
||||
```bash
|
||||
-DSIMDJSON_IMPLEMENTATION_ARM64=1
|
||||
```
|
||||
|
||||
### macOS (Intel)
|
||||
```bash
|
||||
-DSIMDJSON_IMPLEMENTATION_HASWELL=1
|
||||
```
|
||||
|
||||
### Windows (MSVC)
|
||||
```cmd
|
||||
cl /std:c++20 /I..\include /I.. github_legacy.cpp /Fe:github_legacy_demo.exe
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### "reflection feature not available"
|
||||
- Ensure you're using the Bloomberg clang fork
|
||||
- Check version: `clang++ --version` should show bloomberg/clang-p2996
|
||||
|
||||
### "SIMDJSON_STATIC_REFLECTION not working"
|
||||
- Make sure to define it before including headers:
|
||||
```cpp
|
||||
#define SIMDJSON_STATIC_REFLECTION 1
|
||||
#include <simdjson.h>
|
||||
```
|
||||
|
||||
### Linking errors
|
||||
- Use single-header approach for simplicity
|
||||
- Or ensure simdjson library is properly built and linked
|
||||
|
||||
### Performance issues
|
||||
- Add optimization flags: `-O3 -march=native`
|
||||
- Enable LTO: `-flto`
|
||||
|
||||
## 📦 Creating a Portable Demo
|
||||
|
||||
For conferences, prepare the demo environment:
|
||||
|
||||
```bash
|
||||
# Install cpr library (if not available)
|
||||
# Ubuntu/Debian:
|
||||
sudo apt-get install libcpr-dev
|
||||
|
||||
# macOS:
|
||||
brew install cpr
|
||||
|
||||
# Or build from source:
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr && mkdir build && cd build
|
||||
cmake .. && make && sudo make install
|
||||
|
||||
# Create demo directory
|
||||
mkdir simdjson_oneliner_demo
|
||||
cd simdjson_oneliner_demo
|
||||
|
||||
# Copy necessary files
|
||||
cp path/to/github_legacy.cpp .
|
||||
cp path/to/github_modern.cpp .
|
||||
cp -r path/to/simdjson/include .
|
||||
cp -r path/to/simdjson/singleheader .
|
||||
|
||||
# Create build script
|
||||
cat > build_demo.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
echo "🔨 Building Legacy Example..."
|
||||
clang++ -std=c++20 -O3 -I./include -I. \
|
||||
github_legacy.cpp -lcpr -lcurl -o legacy_demo
|
||||
|
||||
echo "🔨 Building Modern Example (C++26)..."
|
||||
clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 -O3 \
|
||||
-I./include -I. github_modern.cpp -lcpr -lcurl -o modern_demo
|
||||
|
||||
echo "✅ Build complete!"
|
||||
echo "Run: ./legacy_demo or ./modern_demo"
|
||||
EOF
|
||||
|
||||
chmod +x build_demo.sh
|
||||
```
|
||||
|
||||
## 🎪 Conference Checklist
|
||||
|
||||
- [ ] Bloomberg clang installed on demo machine
|
||||
- [ ] Both examples compile cleanly
|
||||
- [ ] Internet connection for live API calls (or use standalone)
|
||||
- [ ] Backup: pre-recorded video of compilation and execution
|
||||
- [ ] Slides with code snippets
|
||||
- [ ] QR code for GitHub repo
|
||||
|
||||
## 🔗 Quick Links
|
||||
|
||||
- simdjson: https://github.com/simdjson/simdjson
|
||||
- Bloomberg Clang: https://github.com/bloomberg/clang-p2996
|
||||
- P2996 Reflection Proposal: https://wg21.link/p2996
|
||||
- Talk Resources: [Your GitHub repo with examples]
|
||||
@@ -1 +1,23 @@
|
||||
add_subdirectory(quickstart)
|
||||
|
||||
# Add simdjson one-liner demo examples
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/github_legacy.cpp AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/github_modern.cpp)
|
||||
# FetchContent to download cpr
|
||||
include(FetchContent)
|
||||
set(CPR_ENABLE_SSL OFF CACHE BOOL "")
|
||||
FetchContent_Declare(
|
||||
cpr
|
||||
GIT_REPOSITORY https://github.com/libcpr/cpr.git
|
||||
GIT_TAG 1.10.5
|
||||
)
|
||||
FetchContent_MakeAvailable(cpr)
|
||||
|
||||
# Build the examples
|
||||
add_executable(github_legacy github_legacy.cpp)
|
||||
target_link_libraries(github_legacy simdjson cpr::cpr)
|
||||
|
||||
add_executable(github_modern github_modern.cpp)
|
||||
target_link_libraries(github_modern simdjson cpr::cpr)
|
||||
target_compile_options(github_modern PRIVATE -std=c++26 -freflection)
|
||||
target_compile_definitions(github_modern PRIVATE SIMDJSON_STATIC_REFLECTION=1)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
# 🚀 From Boilerplate to One-Liner: The simdjson Revolution
|
||||
|
||||
## Conference Talk: JSON Parsing in Modern C++
|
||||
|
||||
### 📋 Talk Abstract
|
||||
Discover how simdjson's new API combined with C++26 reflection transforms JSON parsing from a tedious, error-prone task into a single line of code. This talk showcases the dramatic evolution from manual parsing to automatic struct deserialization.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Key Talking Points
|
||||
|
||||
### 1. **The Problem** (2 minutes)
|
||||
- JSON is everywhere: APIs, configs, data exchange
|
||||
- C++ historically makes JSON parsing verbose
|
||||
- Show other languages: `user = json.loads(data)` in Python
|
||||
- "Why can't C++ be this simple?"
|
||||
|
||||
### 2. **The Legacy Approach** (5 minutes)
|
||||
- Live demo: `github_legacy.cpp`
|
||||
- Walk through the boilerplate:
|
||||
```cpp
|
||||
// 😓 Manual field extraction
|
||||
user.login = std::string(doc["login"].get_string().value());
|
||||
user.id = doc["id"].get_int64().value();
|
||||
|
||||
// 😰 Handle optional fields
|
||||
auto company_result = doc["company"];
|
||||
if (!company_result.is_null()) {
|
||||
user.company = std::string(company_result.get_string().value());
|
||||
}
|
||||
```
|
||||
- Count the lines: ~30 lines just for parsing!
|
||||
- Error-prone: typos, missing fields, type mismatches
|
||||
|
||||
### 3. **The Magic Moment** (3 minutes)
|
||||
- "What if I told you it could be just ONE line?"
|
||||
- Show `github_modern.cpp`
|
||||
- The magic line:
|
||||
```cpp
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(json_data));
|
||||
```
|
||||
- Audience reaction: 🤯
|
||||
|
||||
### 4. **How It Works** (5 minutes)
|
||||
- C++26 static reflection
|
||||
- Compile-time struct introspection
|
||||
- simdjson generates parsing code automatically
|
||||
- Zero runtime overhead - it's all compile-time!
|
||||
|
||||
### 5. **Live Demo** (5 minutes)
|
||||
- Compile both examples
|
||||
- Run them side-by-side
|
||||
- Show identical output
|
||||
- Highlight the code difference
|
||||
- Add a new field to the struct - watch it "just work"
|
||||
|
||||
### 6. **Deserialization Performance** (3 minutes)
|
||||
- "But is deserialization fast?"
|
||||
- Live benchmark demonstration
|
||||
- Both approaches achieve ~2.7 GB/s deserialization speed on real GitHub API data
|
||||
- Reflection adds ZERO runtime overhead to deserialization
|
||||
- "You get simplicity WITHOUT sacrificing speed!"
|
||||
- Note: We're measuring JSON → struct deserialization performance
|
||||
- Note: Performance scales with larger documents (up to 3+ GB/s)
|
||||
|
||||
### 7. **The Future is Now** (2 minutes)
|
||||
- Bloomberg clang fork available today
|
||||
- C++26 coming soon
|
||||
- Start preparing your codebases
|
||||
- simdjson ready for the future
|
||||
|
||||
---
|
||||
|
||||
## 💻 Live Coding Demo Script
|
||||
|
||||
### Setup
|
||||
```bash
|
||||
# Show the two files
|
||||
ls -la github_*.cpp
|
||||
|
||||
# Show line count difference
|
||||
wc -l github_legacy.cpp github_modern.cpp
|
||||
```
|
||||
|
||||
### Demo 1: The Pain of Legacy
|
||||
```bash
|
||||
# Open github_legacy.cpp in editor
|
||||
# Highlight the parse_github_user function
|
||||
# Point out each manual field extraction
|
||||
# "Look at all this code just to parse 7 fields!"
|
||||
```
|
||||
|
||||
### Demo 2: The Modern Magic
|
||||
```bash
|
||||
# Open github_modern.cpp
|
||||
# Show the struct - "Just a plain struct!"
|
||||
# Show the one-liner
|
||||
# "That's it. That's the entire parsing code."
|
||||
```
|
||||
|
||||
### Demo 3: Compilation and Execution
|
||||
|
||||
**Option 1: Use the demo script (Recommended)**
|
||||
```bash
|
||||
# The script handles everything - building cpr, compiling, and running
|
||||
./conference_demo.sh
|
||||
```
|
||||
|
||||
**Option 2: Manual compilation**
|
||||
```bash
|
||||
# Build cpr first (one-time setup)
|
||||
mkdir -p ../deps && cd ../deps
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr && git checkout 1.10.5
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCPR_USE_SYSTEM_CURL=ON \
|
||||
-DBUILD_SHARED_LIBS=OFF -DCPR_ENABLE_SSL=OFF
|
||||
make -j4
|
||||
cd ../../../examples
|
||||
|
||||
# Compile legacy
|
||||
clang++ -std=c++20 \
|
||||
-I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_legacy.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o legacy_demo
|
||||
|
||||
# Compile modern (with reflection)
|
||||
clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_modern.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o modern_demo
|
||||
|
||||
# Run both - they fetch real GitHub data!
|
||||
./legacy_demo
|
||||
./modern_demo
|
||||
```
|
||||
|
||||
### Demo 4: Adding a New Field (Crowd Pleaser!)
|
||||
```cpp
|
||||
// Add to struct in both files:
|
||||
std::string twitter_username;
|
||||
|
||||
// Legacy: Must add parsing code
|
||||
else if (key == "twitter_username")
|
||||
user.twitter_username = field.value().get_string().value();
|
||||
|
||||
// Modern: Nothing to add! It just works!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎤 Speaker Notes
|
||||
|
||||
### Opening Hook
|
||||
"How many of you have written JSON parsing code in C++? Keep your hands up if you enjoyed it... Yeah, I thought so."
|
||||
|
||||
### Transition to Modern
|
||||
"But what if I told you that in 2024, with simdjson and C++26, parsing JSON can be as simple as Python?"
|
||||
|
||||
### After showing the one-liner
|
||||
"No, this isn't pseudocode. This is real, working C++ code. Let me prove it to you."
|
||||
|
||||
### Addressing Skeptics
|
||||
- "It's not magic, it's metaprogramming"
|
||||
- "No runtime cost - it's all compile-time"
|
||||
- "Yes, it handles errors properly"
|
||||
- "Yes, it's production-ready"
|
||||
|
||||
### Closing
|
||||
"The future of C++ is here. It's fast, it's simple, and it's beautiful. Stop writing boilerplate. Start writing the code that matters."
|
||||
|
||||
---
|
||||
|
||||
## 📊 Slide Suggestions
|
||||
|
||||
### Slide 1: Title
|
||||
**From 50 Lines to 1: The simdjson Revolution**
|
||||
*Your Name - Conference 2024*
|
||||
|
||||
### Slide 2: The Problem
|
||||
```python
|
||||
# Python
|
||||
user = json.loads(data)
|
||||
|
||||
# JavaScript
|
||||
const user = JSON.parse(data);
|
||||
|
||||
# C++ ???
|
||||
// 😭 50+ lines of boilerplate
|
||||
```
|
||||
|
||||
### Slide 3: The Solution
|
||||
```cpp
|
||||
// C++26 with simdjson
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(data));
|
||||
```
|
||||
|
||||
### Slide 4: Performance Graph
|
||||
- Bar chart showing simdjson vs other parsers
|
||||
- "Fast AND Simple"
|
||||
|
||||
### Slide 5: Timeline
|
||||
- 2018: simdjson introduced (fast but verbose)
|
||||
- 2024: New API design
|
||||
- 2024: C++26 reflection support
|
||||
- Future: It's here!
|
||||
|
||||
### Slide 6: Call to Action
|
||||
- Try it today: github.com/simdjson/simdjson
|
||||
- Bloomberg clang: github.com/bloomberg/clang-p2996
|
||||
- Join the revolution!
|
||||
|
||||
---
|
||||
|
||||
## 🔥 Audience Engagement
|
||||
|
||||
### Interactive Elements
|
||||
1. **Live Poll**: "How many lines of code for parsing JSON?"
|
||||
2. **Challenge**: "Spot the bug in this manual parsing code"
|
||||
3. **Q&A Focus**: Performance, error handling, compatibility
|
||||
|
||||
### Memorable Moments
|
||||
- The reveal of the one-liner
|
||||
- Live compilation with reflection
|
||||
- Adding a field without changing parsing code
|
||||
- Performance numbers
|
||||
|
||||
### Takeaway Message
|
||||
"C++ doesn't have to be painful. With modern tools and modern standards, C++ can be as elegant as any language - and faster than all of them."
|
||||
@@ -0,0 +1,72 @@
|
||||
# Installing CPR Library
|
||||
|
||||
The examples require the CPR library for making HTTP requests to the GitHub API.
|
||||
|
||||
## Option 1: Install via Package Manager (Recommended)
|
||||
|
||||
### Ubuntu/Debian
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install libcpr-dev
|
||||
```
|
||||
|
||||
### macOS (Homebrew)
|
||||
```bash
|
||||
brew install cpr
|
||||
```
|
||||
|
||||
### Arch Linux
|
||||
```bash
|
||||
sudo pacman -S cpr
|
||||
```
|
||||
|
||||
## Option 2: Build from Source
|
||||
|
||||
```bash
|
||||
# Clone cpr
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr
|
||||
|
||||
# Build and install
|
||||
mkdir build && cd build
|
||||
cmake .. -DCPR_USE_SYSTEM_CURL=ON
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Option 3: Using vcpkg
|
||||
|
||||
```bash
|
||||
vcpkg install cpr
|
||||
```
|
||||
|
||||
## Option 4: Using Conan
|
||||
|
||||
```bash
|
||||
conan install cpr/1.10.5@
|
||||
```
|
||||
|
||||
## Compilation
|
||||
|
||||
Once cpr is installed, compile the examples:
|
||||
|
||||
```bash
|
||||
# Legacy example
|
||||
clang++ -std=c++20 -I../include -I.. github_legacy.cpp -lcpr -lcurl -o github_legacy_demo
|
||||
|
||||
# Modern example (requires Bloomberg clang)
|
||||
clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../include -I.. github_modern.cpp -lcpr -lcurl -o github_modern_demo
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you get "cpr/cpr.h not found", check:
|
||||
- `pkg-config --cflags --libs cpr`
|
||||
- Add include path: `-I/usr/local/include`
|
||||
- Add library path: `-L/usr/local/lib`
|
||||
|
||||
For SSL issues, ensure OpenSSL is installed:
|
||||
- Ubuntu/Debian: `sudo apt-get install libssl-dev`
|
||||
- macOS: `brew install openssl`
|
||||
- Link OpenSSL: `-lssl -lcrypto`
|
||||
@@ -0,0 +1,74 @@
|
||||
# 🚀 simdjson One-Liner Demo: From Boilerplate to Magic
|
||||
|
||||
This demo showcases the dramatic simplification of JSON parsing in C++ using simdjson's new API combined with C++26 reflection.
|
||||
|
||||
## Files
|
||||
|
||||
- `github_legacy.cpp` - Traditional manual JSON parsing approach (~30 lines of parsing code)
|
||||
- `github_modern.cpp` - Modern C++26 reflection approach (1 line of parsing code!)
|
||||
- `CONFERENCE_TALK.md` - Complete conference presentation guide
|
||||
- `BUILD_INSTRUCTIONS.md` - Detailed compilation instructions
|
||||
- `conference_demo.sh` - Interactive demo script for presentations
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Bloomberg clang for C++26: https://github.com/bloomberg/clang-p2996
|
||||
- curl library (usually pre-installed)
|
||||
- cpr library (built automatically by demo script)
|
||||
|
||||
### Easy Demo
|
||||
```bash
|
||||
# Just run the demo script - it handles everything!
|
||||
./conference_demo.sh
|
||||
```
|
||||
|
||||
The script will:
|
||||
1. Build cpr if needed
|
||||
2. Compile both examples
|
||||
3. Run interactive presentation
|
||||
|
||||
### Manual Compilation
|
||||
|
||||
If you want to compile manually:
|
||||
|
||||
```bash
|
||||
# Build cpr first (if not installed)
|
||||
mkdir -p ../deps && cd ../deps
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr && git checkout 1.10.5
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCPR_USE_SYSTEM_CURL=ON -DBUILD_SHARED_LIBS=OFF -DCPR_ENABLE_SSL=OFF
|
||||
make -j4
|
||||
cd ../../../examples
|
||||
|
||||
# Compile examples
|
||||
# Legacy
|
||||
clang++ -std=c++20 -I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_legacy.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o legacy_demo
|
||||
|
||||
# Modern
|
||||
clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_modern.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o modern_demo
|
||||
```
|
||||
|
||||
## The Magic ✨
|
||||
|
||||
**Before (Legacy):**
|
||||
```cpp
|
||||
// 30+ lines of manual parsing...
|
||||
user.login = std::string(doc["login"].get_string().value());
|
||||
user.id = doc["id"].get_int64().value();
|
||||
// ... etc for each field
|
||||
```
|
||||
|
||||
**After (Modern):**
|
||||
```cpp
|
||||
// Just ONE line!
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(response.text));
|
||||
```
|
||||
|
||||
Both examples fetch real data from GitHub API to demonstrate real-world usage!
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
#!/bin/bash
|
||||
# Conference Demo Script - simdjson One-Liner Magic
|
||||
# Run this during your talk for a smooth demo experience
|
||||
|
||||
# Check if cpr is built
|
||||
if [ ! -f "../deps/cpr/build/lib/libcpr.a" ]; then
|
||||
echo "⚠️ CPR library not found. Building it first..."
|
||||
echo ""
|
||||
if [ ! -d "../deps/cpr" ]; then
|
||||
mkdir -p ../deps
|
||||
cd ../deps
|
||||
git clone https://github.com/libcpr/cpr.git
|
||||
cd cpr && git checkout 1.10.5
|
||||
cd ../..
|
||||
fi
|
||||
cd ../deps/cpr
|
||||
mkdir -p build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCPR_USE_SYSTEM_CURL=ON -DBUILD_SHARED_LIBS=OFF -DCPR_ENABLE_SSL=OFF
|
||||
make -j4
|
||||
cd ../../../examples
|
||||
echo "✅ CPR built successfully!"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
clear
|
||||
echo "🚀 simdjson: From Boilerplate to One-Liner"
|
||||
echo "==========================================="
|
||||
echo ""
|
||||
echo "Press Enter to continue..."
|
||||
read
|
||||
|
||||
# Show the legacy approach
|
||||
echo "📚 First, let's look at the LEGACY approach..."
|
||||
echo ""
|
||||
echo "Opening github_legacy.cpp..."
|
||||
sleep 1
|
||||
echo ""
|
||||
echo "Key points:"
|
||||
echo " • Manual parse_github_user() function"
|
||||
echo " • Extract each field individually"
|
||||
echo " • Handle optional fields explicitly"
|
||||
echo " • ~30 lines of parsing code"
|
||||
echo ""
|
||||
echo "Press Enter to see the code..."
|
||||
read
|
||||
|
||||
# Display key parts of legacy code
|
||||
cat github_legacy.cpp | grep -A 20 "parse_github_user" | head -25
|
||||
|
||||
echo ""
|
||||
echo "😓 That's a lot of boilerplate!"
|
||||
echo ""
|
||||
echo "Press Enter to compile and run..."
|
||||
read
|
||||
|
||||
# Compile legacy
|
||||
echo "🔨 Compiling legacy version..."
|
||||
echo "Command: clang++ -std=c++20 -I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes -I../include -I.. github_legacy.cpp ../singleheader/simdjson.cpp ../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o legacy_demo"
|
||||
clang++ -std=c++20 -I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes -I../include -I.. github_legacy.cpp ../singleheader/simdjson.cpp ../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o legacy_demo
|
||||
echo "✅ Compiled!"
|
||||
echo ""
|
||||
echo "🏃 Running legacy demo (fetching real GitHub data)..."
|
||||
echo ""
|
||||
./legacy_demo
|
||||
|
||||
echo ""
|
||||
echo "Press Enter to see the MODERN approach..."
|
||||
read
|
||||
|
||||
clear
|
||||
echo "✨ Now, let's look at the MODERN approach with C++26 reflection..."
|
||||
echo ""
|
||||
echo "Opening github_modern.cpp..."
|
||||
sleep 1
|
||||
echo ""
|
||||
echo "Key points:"
|
||||
echo " • Just declare your struct"
|
||||
echo " • ONE line of parsing code"
|
||||
echo " • C++26 reflection handles everything"
|
||||
echo " • No manual field extraction!"
|
||||
echo ""
|
||||
echo "Press Enter to see the magic..."
|
||||
read
|
||||
|
||||
# Show the struct and the one-liner
|
||||
echo "The struct (just a plain struct!):"
|
||||
echo ""
|
||||
cat github_modern.cpp | grep -A 10 "struct GitHubUser" | head -12
|
||||
echo ""
|
||||
echo "The parsing code (ONE LINE!):"
|
||||
echo ""
|
||||
echo " GitHubUser user = simdjson::from(simdjson::padded_string(response.text));"
|
||||
echo ""
|
||||
echo "🤯 That's it! That's all the parsing code!"
|
||||
echo ""
|
||||
echo "Press Enter to compile with C++26 reflection..."
|
||||
read
|
||||
|
||||
# Compile modern
|
||||
echo "🔨 Compiling modern version with Bloomberg clang..."
|
||||
echo "Command: clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 -I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes -I../include -I.. github_modern.cpp ../singleheader/simdjson.cpp ../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o modern_demo"
|
||||
clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 -I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes -I../include -I.. github_modern.cpp ../singleheader/simdjson.cpp ../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o modern_demo
|
||||
echo "✅ Compiled!"
|
||||
echo ""
|
||||
echo "🏃 Running modern demo (fetching real GitHub data)..."
|
||||
echo ""
|
||||
./modern_demo
|
||||
|
||||
echo ""
|
||||
echo "Press Enter to see side-by-side comparison..."
|
||||
read
|
||||
|
||||
clear
|
||||
echo "📊 SIDE-BY-SIDE COMPARISON"
|
||||
echo "========================="
|
||||
echo ""
|
||||
echo "Legacy Approach: Modern Approach (C++26):"
|
||||
echo "---------------- ------------------------"
|
||||
echo "❌ 30+ lines of parsing code ✅ 1 line of parsing code"
|
||||
echo "❌ Manual field extraction ✅ Automatic with reflection"
|
||||
echo "❌ Error-prone ✅ Type-safe"
|
||||
echo "❌ Hard to maintain ✅ Just update the struct"
|
||||
echo "❌ Boilerplate for each type ✅ Works for any struct"
|
||||
echo ""
|
||||
echo ""
|
||||
echo "Press Enter to run PERFORMANCE BENCHMARKS..."
|
||||
read
|
||||
|
||||
clear
|
||||
echo "⚡ DESERIALIZATION PERFORMANCE BENCHMARKS"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Let's measure the actual JSON → struct deserialization speed..."
|
||||
echo ""
|
||||
|
||||
# Compile benchmarks if not exist
|
||||
if [ ! -f "./legacy_benchmark" ] || [ ! -f "./modern_benchmark" ]; then
|
||||
echo "🔨 Compiling benchmark versions..."
|
||||
|
||||
clang++ -std=c++20 -O3 -march=native \
|
||||
-I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_legacy_benchmark.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o legacy_benchmark 2>/dev/null
|
||||
|
||||
clang++ -std=c++26 -freflection -O3 -march=native \
|
||||
-DSIMDJSON_STATIC_REFLECTION=1 \
|
||||
-I../deps/cpr/include -I../deps/cpr/build/cpr_generated_includes \
|
||||
-I../include -I.. github_modern_benchmark.cpp ../singleheader/simdjson.cpp \
|
||||
../deps/cpr/build/lib/libcpr.a -lcurl -pthread -o modern_benchmark 2>/dev/null
|
||||
fi
|
||||
|
||||
echo "🏃 Running legacy benchmark..."
|
||||
echo ""
|
||||
./legacy_benchmark
|
||||
|
||||
echo ""
|
||||
echo "Press Enter to run modern benchmark..."
|
||||
read
|
||||
|
||||
echo "🏃 Running modern benchmark..."
|
||||
echo ""
|
||||
./modern_benchmark
|
||||
|
||||
echo ""
|
||||
echo "🎉 The future of C++ is here!"
|
||||
echo ""
|
||||
echo "Questions?"
|
||||
@@ -0,0 +1,83 @@
|
||||
// Legacy approach - manual JSON parsing with simdjson
|
||||
#include <simdjson.h>
|
||||
#include <cpr/cpr.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
struct GitHubUser {
|
||||
std::string login;
|
||||
int64_t id;
|
||||
std::string name;
|
||||
std::optional<std::string> company;
|
||||
std::optional<std::string> location;
|
||||
int64_t public_repos;
|
||||
int64_t followers;
|
||||
};
|
||||
|
||||
// Legacy approach - manual parsing with lots of boilerplate
|
||||
GitHubUser parse_github_user(const std::string& json_str) {
|
||||
GitHubUser user;
|
||||
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::padded_string json(json_str);
|
||||
simdjson::ondemand::document doc = parser.iterate(json);
|
||||
|
||||
// Manual field extraction with error checking
|
||||
user.login = std::string(doc["login"].get_string().value());
|
||||
user.id = doc["id"].get_int64().value();
|
||||
user.name = std::string(doc["name"].get_string().value());
|
||||
|
||||
// Handle optional fields
|
||||
auto company_result = doc["company"];
|
||||
if (!company_result.is_null()) {
|
||||
user.company = std::string(company_result.get_string().value());
|
||||
}
|
||||
|
||||
auto location_result = doc["location"];
|
||||
if (!location_result.is_null()) {
|
||||
user.location = std::string(location_result.get_string().value());
|
||||
}
|
||||
|
||||
user.public_repos = doc["public_repos"].get_int64().value();
|
||||
user.followers = doc["followers"].get_int64().value();
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "📚 Legacy Approach - Manual JSON Parsing\n";
|
||||
std::cout << "========================================\n\n";
|
||||
|
||||
// Fetch data from GitHub API
|
||||
auto response = cpr::Get(
|
||||
cpr::Url{"https://api.github.com/users/lemire"},
|
||||
cpr::Header{{"User-Agent", "simdjson-legacy-demo"}}
|
||||
);
|
||||
|
||||
if (response.status_code != 200) {
|
||||
std::cerr << "❌ Failed to fetch data: HTTP " << response.status_code << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
// 😓 The old way - manual parsing with lots of code
|
||||
GitHubUser user = parse_github_user(response.text);
|
||||
|
||||
// Display results
|
||||
std::cout << "GitHub User: " << user.name << " (@" << user.login << ")\n";
|
||||
std::cout << "ID: " << user.id << "\n";
|
||||
if (user.company) std::cout << "Company: " << *user.company << "\n";
|
||||
if (user.location) std::cout << "Location: " << *user.location << "\n";
|
||||
std::cout << "Public Repos: " << user.public_repos << "\n";
|
||||
std::cout << "Followers: " << user.followers << "\n";
|
||||
|
||||
std::cout << "\n⚠️ Notice all the manual parsing code required!\n";
|
||||
|
||||
} catch (const simdjson::simdjson_error& e) {
|
||||
std::cerr << "❌ Parsing error: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
// Legacy approach with performance measurement
|
||||
#include <simdjson.h>
|
||||
#include <cpr/cpr.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
struct GitHubUser {
|
||||
std::string login;
|
||||
int64_t id;
|
||||
std::string name;
|
||||
std::optional<std::string> company;
|
||||
std::optional<std::string> location;
|
||||
int64_t public_repos;
|
||||
int64_t followers;
|
||||
};
|
||||
|
||||
// Manual parsing function (the old way)
|
||||
GitHubUser parse_github_user(const std::string& json_str) {
|
||||
GitHubUser user;
|
||||
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::padded_string json(json_str);
|
||||
simdjson::ondemand::document doc = parser.iterate(json);
|
||||
|
||||
// Manual field extraction with error checking
|
||||
user.login = std::string(doc["login"].get_string().value());
|
||||
user.id = doc["id"].get_int64().value();
|
||||
user.name = std::string(doc["name"].get_string().value());
|
||||
|
||||
// Handle optional fields
|
||||
auto company_result = doc["company"];
|
||||
if (!company_result.is_null()) {
|
||||
user.company = std::string(company_result.get_string().value());
|
||||
}
|
||||
|
||||
auto location_result = doc["location"];
|
||||
if (!location_result.is_null()) {
|
||||
user.location = std::string(location_result.get_string().value());
|
||||
}
|
||||
|
||||
user.public_repos = doc["public_repos"].get_int64().value();
|
||||
user.followers = doc["followers"].get_int64().value();
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
// Manual serialization function (the old way)
|
||||
std::string serialize_github_user(const GitHubUser& user) {
|
||||
std::ostringstream json;
|
||||
json << "{";
|
||||
json << "\"login\":\"" << user.login << "\",";
|
||||
json << "\"id\":" << user.id << ",";
|
||||
json << "\"name\":\"" << user.name << "\",";
|
||||
|
||||
if (user.company.has_value()) {
|
||||
json << "\"company\":\"" << *user.company << "\",";
|
||||
} else {
|
||||
json << "\"company\":null,";
|
||||
}
|
||||
|
||||
if (user.location.has_value()) {
|
||||
json << "\"location\":\"" << *user.location << "\",";
|
||||
} else {
|
||||
json << "\"location\":null,";
|
||||
}
|
||||
|
||||
json << "\"public_repos\":" << user.public_repos << ",";
|
||||
json << "\"followers\":" << user.followers;
|
||||
json << "}";
|
||||
|
||||
return json.str();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "📚 Legacy Approach - Deserialization Performance Benchmark\n";
|
||||
std::cout << "=========================================================\n\n";
|
||||
|
||||
// Fetch data from GitHub API
|
||||
auto response = cpr::Get(
|
||||
cpr::Url{"https://api.github.com/users/lemire"},
|
||||
cpr::Header{{"User-Agent", "simdjson-benchmark"}}
|
||||
);
|
||||
|
||||
if (response.status_code != 200) {
|
||||
std::cerr << "❌ Failed to fetch data: HTTP " << response.status_code << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Warm up
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto user = parse_github_user(response.text);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
const int iterations = 10000;
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
auto user = parse_github_user(response.text);
|
||||
// Prevent optimization
|
||||
if (i == 0) {
|
||||
std::cout << "Parsing: " << user.name << " (@" << user.login << ")\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
|
||||
// Calculate performance metrics
|
||||
double time_per_parse = duration.count() / static_cast<double>(iterations);
|
||||
double bytes_per_parse = response.text.size();
|
||||
double gb_per_second = (bytes_per_parse * iterations) / (duration.count() * 1000.0);
|
||||
|
||||
std::cout << "📊 Deserialization Performance Results:\n";
|
||||
std::cout << " • JSON size: " << bytes_per_parse << " bytes\n";
|
||||
std::cout << " • Iterations: " << iterations << "\n";
|
||||
std::cout << " • Total time: " << duration.count() / 1000.0 << " ms\n";
|
||||
std::cout << " • Time per deserialization: " << std::fixed << std::setprecision(2) << time_per_parse << " μs\n";
|
||||
std::cout << " • Deserialization speed: " << std::fixed << std::setprecision(2) << gb_per_second << " GB/s\n";
|
||||
|
||||
// Now benchmark serialization
|
||||
std::cout << "\n📝 Serialization Performance Benchmark\n";
|
||||
std::cout << "=====================================\n\n";
|
||||
|
||||
// Parse once to get a user object
|
||||
auto user = parse_github_user(response.text);
|
||||
|
||||
// Warm up serialization
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto json_str = serialize_github_user(user);
|
||||
}
|
||||
|
||||
// Benchmark serialization
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
auto json_str = serialize_github_user(user);
|
||||
// Prevent optimization
|
||||
if (i == 0) {
|
||||
std::cout << "Serialized JSON size: " << json_str.length() << " bytes\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
|
||||
// Calculate serialization performance metrics
|
||||
time_per_parse = duration.count() / static_cast<double>(iterations);
|
||||
double serialized_size = serialize_github_user(user).length();
|
||||
gb_per_second = (serialized_size * iterations) / (duration.count() * 1000.0);
|
||||
|
||||
std::cout << "📊 Serialization Performance Results:\n";
|
||||
std::cout << " • JSON size: " << serialized_size << " bytes\n";
|
||||
std::cout << " • Iterations: " << iterations << "\n";
|
||||
std::cout << " • Total time: " << duration.count() / 1000.0 << " ms\n";
|
||||
std::cout << " • Time per serialization: " << std::fixed << std::setprecision(2) << time_per_parse << " μs\n";
|
||||
std::cout << " • Serialization speed: " << std::fixed << std::setprecision(2) << gb_per_second << " GB/s\n";
|
||||
std::cout << "\n⚠️ Note: Manual serialization with string concatenation\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Modern approach - C++26 reflection with simdjson
|
||||
// Compile with Bloomberg clang fork:
|
||||
// clang++ -std=c++26 -freflection -DSIMDJSON_STATIC_REFLECTION=1 ...
|
||||
#include <simdjson.h>
|
||||
#include <simdjson/convert.h>
|
||||
#include <cpr/cpr.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
// 🎯 JUST DECLARE YOUR STRUCT - THAT'S IT!
|
||||
// No serialization code needed with C++26 reflection
|
||||
struct GitHubUser {
|
||||
std::string login;
|
||||
int64_t id;
|
||||
std::string name;
|
||||
std::optional<std::string> company;
|
||||
std::optional<std::string> location;
|
||||
int64_t public_repos;
|
||||
int64_t followers;
|
||||
};
|
||||
// NO BOILERPLATE CODE NEEDED! 🎉
|
||||
|
||||
int main() {
|
||||
std::cout << "✨ Modern Approach - C++26 Reflection\n";
|
||||
std::cout << "=====================================\n\n";
|
||||
|
||||
// Fetch data from GitHub API
|
||||
auto response = cpr::Get(
|
||||
cpr::Url{"https://api.github.com/users/lemire"},
|
||||
cpr::Header{{"User-Agent", "simdjson-modern-demo"}}
|
||||
);
|
||||
|
||||
if (response.status_code != 200) {
|
||||
std::cerr << "❌ Failed to fetch data: HTTP " << response.status_code << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
// ✨ THE MAGIC - Just one line, no boilerplate!
|
||||
// C++26 reflection handles everything automatically
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(response.text));
|
||||
|
||||
// Display results
|
||||
std::cout << "GitHub User: " << user.name << " (@" << user.login << ")\n";
|
||||
std::cout << "ID: " << user.id << "\n";
|
||||
if (user.company) std::cout << "Company: " << *user.company << "\n";
|
||||
if (user.location) std::cout << "Location: " << *user.location << "\n";
|
||||
std::cout << "Public Repos: " << user.public_repos << "\n";
|
||||
std::cout << "Followers: " << user.followers << "\n";
|
||||
|
||||
std::cout << "\n🚀 That's it! No manual parsing code needed!\n";
|
||||
std::cout << " C++26 reflection generates everything automatically.\n";
|
||||
|
||||
} catch (const simdjson::simdjson_error& e) {
|
||||
std::cerr << "❌ Parsing error: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Modern approach with performance measurement - C++26 reflection
|
||||
#include <simdjson.h>
|
||||
#include <simdjson/convert.h>
|
||||
#include <cpr/cpr.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
// Just declare your struct - reflection handles the rest!
|
||||
struct GitHubUser {
|
||||
std::string login;
|
||||
int64_t id;
|
||||
std::string name;
|
||||
std::optional<std::string> company;
|
||||
std::optional<std::string> location;
|
||||
int64_t public_repos;
|
||||
int64_t followers;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << "✨ Modern Approach - Deserialization Performance Benchmark (C++26)\n";
|
||||
std::cout << "================================================================\n\n";
|
||||
|
||||
// Fetch data from GitHub API
|
||||
auto response = cpr::Get(
|
||||
cpr::Url{"https://api.github.com/users/lemire"},
|
||||
cpr::Header{{"User-Agent", "simdjson-benchmark"}}
|
||||
);
|
||||
|
||||
if (response.status_code != 200) {
|
||||
std::cerr << "❌ Failed to fetch data: HTTP " << response.status_code << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Warm up
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(response.text));
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
const int iterations = 10000;
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
GitHubUser user = simdjson::from(simdjson::padded_string(response.text));
|
||||
// Prevent optimization
|
||||
if (i == 0) {
|
||||
std::cout << "Parsing: " << user.name << " (@" << user.login << ")\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
|
||||
// Calculate performance metrics
|
||||
double time_per_parse = duration.count() / static_cast<double>(iterations);
|
||||
double bytes_per_parse = response.text.size();
|
||||
double gb_per_second = (bytes_per_parse * iterations) / (duration.count() * 1000.0);
|
||||
|
||||
std::cout << "📊 Deserialization Performance Results:\n";
|
||||
std::cout << " • JSON size: " << bytes_per_parse << " bytes\n";
|
||||
std::cout << " • Iterations: " << iterations << "\n";
|
||||
std::cout << " • Total time: " << duration.count() / 1000.0 << " ms\n";
|
||||
std::cout << " • Time per deserialization: " << std::fixed << std::setprecision(2) << time_per_parse << " μs\n";
|
||||
std::cout << " • Deserialization speed: " << std::fixed << std::setprecision(2) << gb_per_second << " GB/s\n";
|
||||
|
||||
std::cout << "\n🚀 Same performance, just ONE line of deserialization code!\n";
|
||||
|
||||
// Serialization note
|
||||
std::cout << "\n📝 Serialization with Reflection\n";
|
||||
std::cout << "================================\n\n";
|
||||
std::cout << "⚠️ NOTE: simdjson doesn't yet support reflection-based serialization.\n";
|
||||
std::cout << " The `simdjson::to` function is not yet implemented.\n";
|
||||
std::cout << " This is a future enhancement that would provide:\n";
|
||||
std::cout << " • One-line serialization: simdjson::to<std::string>(user)\n";
|
||||
std::cout << " • Automatic JSON generation from C++ structs\n";
|
||||
std::cout << " • No manual string building required\n";
|
||||
std::cout << "\n";
|
||||
std::cout << " For now, serialization still requires manual implementation,\n";
|
||||
std::cout << " but deserialization is fully automated with reflection! 🎉\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user