Skip to content

Commit

Permalink
Improve: fastapi_server.py to be feature-complete with respect to U…
Browse files Browse the repository at this point in the history
…Call server
  • Loading branch information
ashvardanian committed May 13, 2024
1 parent a317a27 commit 6d0aad5
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 19 deletions.
19 changes: 18 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
# UCall Examples and Benchmarks
# UCall Example & Benchmark

This folder implements a group of different servers with identical functionality, but using different RPC frameworks, including:

- FastAPI server in Python, compatible with WSGI: `fastapi_server.py`
- UCall server in Python: `ucall_server.py`
- UCall server in C++: `ucall_server.cpp`
- gRPC server in Python: `grpc_server.py`

All of them implement identical endpoints:

- `echo` - return back the payload it received for throughput benchmarks
- `validate_session` - lightweight operation on two integers, returning a boolean, to benchmark the request latency on tiny tasks
- `create_user` - more complex operation on flat dictionary input with strings and integers
- `validate_user_identity` - that validates arguments, raises exceptions, and returns complex nested objects
- `set` & `get` - key-value store operations, similar to Redis
- `resize` - batch-capable image processing operation for Base64-encoded images
- `dot_product` - batch-capable matrix vector-vector multiplication operation

## Echo and Summation

Expand Down
39 changes: 24 additions & 15 deletions examples/bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,27 @@ class Stats:
requests_failure: int = 0
mean_latency_secs: float = 0
total_secs: float = 0
last_failure: str = ''
last_failure: str = ""

@property
def success_rate(self) -> float:
return (self.requests_correct * 1.0 / self.requests) if self.requests else 1.0

def __repr__(self) -> str:
bandwidth = self.requests / \
self.total_secs if self.total_secs > 0 else 0.0
result = f'''
bandwidth = self.requests / self.total_secs if self.total_secs > 0 else 0.0
result = f"""
- Took: {self.total_secs:.1f} CPU seconds
- Total exchanges: {self.requests:,}
- Success rate: {self.success_rate:.3%}
- Mean latency: {self.mean_latency_secs * 1e6:.1f} microseconds
- Mean bandwidth: {bandwidth:.1f} requests/s
'''
"""
return I(result)


def bench_serial(
callable, *,
callable,
*,
requests_count: int = 100_000,
seconds: float = 10,
progress: bool = False,
Expand Down Expand Up @@ -90,19 +90,21 @@ def bench_parallel(
callable=callable,
seconds=seconds,
requests_count=requests_count,
progress=progress)
progress=progress,
)

requests_correct = Value('i', 0)
requests_incorrect = Value('i', 0)
requests = Value('i', 0)
mean_latency_secs = Value('f', 0)
requests_correct = Value("i", 0)
requests_incorrect = Value("i", 0)
requests = Value("i", 0)
mean_latency_secs = Value("f", 0)

def run():
stats = bench_serial(
callable=callable,
seconds=seconds,
requests_count=requests_count,
progress=False)
progress=False,
)
requests_correct.value += stats.requests_correct
requests_incorrect.value += stats.requests_incorrect
requests.value += stats.requests
Expand All @@ -129,9 +131,16 @@ def run():
)


def main(class_name: str, *, threads: int = 1, requests: int = 100_000, seconds: float = 10, progress: bool = False):
def main(
class_name: str,
*,
threads: int = 1,
requests: int = 100_000,
seconds: float = 10,
progress: bool = False,
):
script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(f'{script_dir}/login')
sys.path.append(f"{script_dir}/login")
class_ = locate(class_name)
stats = bench_parallel(
callable=class_(),
Expand All @@ -143,5 +152,5 @@ def main(class_name: str, *, threads: int = 1, requests: int = 100_000, seconds:
print(stats)


if __name__ == '__main__':
if __name__ == "__main__":
fire.Fire(main)
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ async def create_user(age: int, name: str, avatar: str, bio: str):

@app.post("/validate_user_identity")
async def validate_user_identity(
user_id: int, name: str, age: float, access_token: str
user_id: int,
name: str,
age: float,
access_token: str,
):
if age < 18:
raise HTTPException(status_code=400, detail=f"{name} must be older than 18")
Expand Down
3 changes: 1 addition & 2 deletions examples/login/jsonrpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"os"
"time"
"bytes"
"flag"
"flag"
)

var(
Expand Down Expand Up @@ -79,7 +79,6 @@ func main() {
_, err = conn.Write([]byte(req))
}
if err != nil {
//fmt.Printf("Write Error: %v\n", err)
break
}

Expand Down

0 comments on commit 6d0aad5

Please sign in to comment.