mirror of
https://github.com/ivanch/tcc.git
synced 2025-09-15 09:05:21 +00:00
Compare commits
12 Commits
ac8bff31f2
...
main
Author | SHA1 | Date | |
---|---|---|---|
274fe5252a | |||
e547ae41d4 | |||
a920b36386 | |||
ed9942d56e | |||
00db2190b5 | |||
877c7a0dc3 | |||
acfd94f6ff | |||
9ef644702b | |||
95a85be35d | |||
1eb02db473 | |||
96ecf8de16 | |||
e8ae8935f2 |
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "Spring"]
|
||||
path = Spring
|
||||
url = git@github.com:horakhy/springtcc.git
|
||||
[submodule "Express"]
|
||||
path = Express
|
||||
url = git@github.com:horakhy/tcc-express.git
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
|
||||
</project>
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/tcc.iml" filepath="$PROJECT_DIR$/.idea/tcc.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
8
.idea/tcc.iml
generated
8
.idea/tcc.iml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@@ -15,18 +15,6 @@ namespace TCC.Controllers
|
||||
this.ImageService = imageService;
|
||||
}
|
||||
|
||||
[HttpGet("load-small-image")]
|
||||
public async Task<IActionResult> GetSimpleImage()
|
||||
{
|
||||
return File(ImageService.GetSimpleImage(), "image/png");
|
||||
}
|
||||
|
||||
[HttpGet("load-big-image")]
|
||||
public async Task<IActionResult> GetBigImage()
|
||||
{
|
||||
return File(ImageService.GetBigImage(), "image/png");
|
||||
}
|
||||
|
||||
[HttpPost("save-big-image")]
|
||||
public async Task<IActionResult> SaveBigImage()
|
||||
{
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ProtoBuf;
|
||||
using System.IO;
|
||||
using tcc_app.Models;
|
||||
|
||||
namespace TCC.Controllers
|
||||
{
|
||||
@@ -24,25 +23,25 @@ namespace TCC.Controllers
|
||||
return Ok(sum);
|
||||
}
|
||||
|
||||
[HttpGet("json")]
|
||||
public async Task<IActionResult> GetJsonResponse()
|
||||
[HttpPost("json")]
|
||||
public async Task<IActionResult> PostJson([FromBody] PersonJson person)
|
||||
{
|
||||
return Ok(new { message = "Hello World!" });
|
||||
return Ok(person);
|
||||
}
|
||||
|
||||
[HttpPost("protobuf")]
|
||||
public async Task<IActionResult> PostProtobuf()
|
||||
{
|
||||
HelloWorld cliente;
|
||||
PersonProto person;
|
||||
byte[] response;
|
||||
using (var stream = Request.BodyReader.AsStream())
|
||||
{
|
||||
cliente = ProtoBuf.Serializer.Deserialize<HelloWorld>(stream);
|
||||
person = ProtoBuf.Serializer.Deserialize<PersonProto>(stream);
|
||||
}
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
ProtoBuf.Serializer.Serialize(stream, cliente);
|
||||
ProtoBuf.Serializer.Serialize(stream, person);
|
||||
response = stream.ToArray();
|
||||
}
|
||||
|
||||
@@ -51,11 +50,4 @@ namespace TCC.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[ProtoContract()]
|
||||
public class HelloWorld
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,10 +12,10 @@ RUN dotnet restore
|
||||
RUN dotnet build -c Release -o out
|
||||
|
||||
RUN cd out && \
|
||||
wget https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/81Bkht5C/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/nAndfAjK/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/RzXwJG7o/nginx.html && \
|
||||
wget https://files.ivanch.me/api/public/dl/ch3NV0P8/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/jNlXYMLR/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/QdKvaeQI/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/YD4vmSsO/nginx.html && \
|
||||
rm -rf runtimes && \
|
||||
mkdir -p ./static && \
|
||||
mv small-image.png ./static && \
|
||||
|
12
ASP.NET/Models/PersonJson.cs
Normal file
12
ASP.NET/Models/PersonJson.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace tcc_app.Models
|
||||
{
|
||||
public class PersonJson
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
public List<string> Friends { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
}
|
||||
|
||||
}
|
24
ASP.NET/Models/PersonProto.cs
Normal file
24
ASP.NET/Models/PersonProto.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using ProtoBuf;
|
||||
|
||||
namespace tcc_app.Models
|
||||
{
|
||||
[ProtoContract()]
|
||||
public class PersonProto
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[ProtoMember(2)]
|
||||
public int Age { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public List<string> Friends { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public string Email { get; set; }
|
||||
|
||||
[ProtoMember(5)]
|
||||
public string Phone { get; set; }
|
||||
}
|
||||
|
||||
}
|
@@ -10,15 +10,5 @@
|
||||
fileStream.CopyToAsync(file);
|
||||
file.Close();
|
||||
}
|
||||
|
||||
public byte[] GetSimpleImage()
|
||||
{
|
||||
return File.ReadAllBytes("static/small-image.png");
|
||||
}
|
||||
|
||||
public byte[] GetBigImage()
|
||||
{
|
||||
return File.ReadAllBytes("static/big-image.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,23 +1,22 @@
|
||||
FROM rust:latest
|
||||
FROM rust:1.77-buster as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN cargo build --release
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
WORKDIR /app
|
||||
|
||||
RUN RUN apt-get update && apt-get -y install wget && \
|
||||
wget https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/81Bkht5C/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/nAndfAjK/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/RzXwJG7o/nginx.html
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN cargo build --release && \
|
||||
cp ./target/release/ActixAPI . && \
|
||||
RUN apt-get update && apt-get -y install wget && \
|
||||
wget https://files.ivanch.me/api/public/dl/ch3NV0P8/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/jNlXYMLR/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/QdKvaeQI/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/YD4vmSsO/nginx.html && \
|
||||
mkdir -p ./static && \
|
||||
mv small-image.png ./static && \
|
||||
mv big-image.png ./static && \
|
||||
mv video.mp4 ./static && \
|
||||
mv nginx.html ./static && \
|
||||
ldconfig /usr/local/lib
|
||||
mv nginx.html ./static
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
COPY --from=builder /app/target/release/ActixAPI .
|
||||
|
||||
ENTRYPOINT ["./ActixAPI"]
|
||||
CMD ["./ActixAPI"]
|
@@ -1,14 +1,31 @@
|
||||
use qstring::QString;
|
||||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, HttpRequest, Result};
|
||||
use actix_files::NamedFile;
|
||||
// use actix_protobuf::{ProtoBuf, ProtoBufResponseBuilder as _};
|
||||
use actix_protobuf::*;
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Message)]
|
||||
pub struct HelloWorld {
|
||||
pub struct PersonProtobuf {
|
||||
#[prost(string, tag = "1")]
|
||||
pub message: String
|
||||
pub name: String,
|
||||
#[prost(int32, tag = "2")]
|
||||
pub age: i32,
|
||||
#[prost(string, repeated, tag = "3")]
|
||||
pub friends: Vec<String>,
|
||||
#[prost(string, tag = "4")]
|
||||
pub email: String,
|
||||
#[prost(string, tag = "5")]
|
||||
pub phone: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct PersonJson {
|
||||
pub name: String,
|
||||
pub age: i32,
|
||||
pub friends: Vec<String>,
|
||||
pub email: String,
|
||||
pub phone: String,
|
||||
}
|
||||
|
||||
#[get("/status/ok")]
|
||||
@@ -37,43 +54,20 @@ async fn simulation_harmonic_progression(req: HttpRequest) -> impl Responder {
|
||||
HttpResponse::Ok().body(format!("{}", sum))
|
||||
}
|
||||
|
||||
#[get("/simulation/json")]
|
||||
async fn simulation_json() -> impl Responder {
|
||||
let body = serde_json::json!({
|
||||
"message": "Hello World!"
|
||||
});
|
||||
|
||||
HttpResponse::Ok()
|
||||
.json(body)
|
||||
#[post("/simulation/json")]
|
||||
async fn simulation_json(msg: web::Json<PersonJson>) -> impl Responder {
|
||||
HttpResponse::Ok().json(web::Json(msg))
|
||||
}
|
||||
|
||||
#[post("/simulation/protobuf")]
|
||||
async fn simulation_protobuf(msg: ProtoBuf<HelloWorld>) -> impl Responder {
|
||||
println!("model: {:?}", msg.0);
|
||||
|
||||
async fn simulation_protobuf(msg: ProtoBuf<PersonProtobuf>) -> impl Responder {
|
||||
HttpResponse::Ok().protobuf(msg.0)
|
||||
}
|
||||
|
||||
#[get("/image/load-small-image")]
|
||||
async fn load_small_image() -> Result<NamedFile> {
|
||||
let real_path = "static/small-image.png";
|
||||
|
||||
Ok(NamedFile::open(real_path)?)
|
||||
}
|
||||
|
||||
#[get("/image/load-big-image")]
|
||||
async fn load_big_image() -> Result<NamedFile> {
|
||||
let real_path = "static/big-image.png";
|
||||
|
||||
Ok(NamedFile::open(real_path)?)
|
||||
}
|
||||
|
||||
#[post("/image/save-big-image")]
|
||||
async fn save_big_image(image_data: web::Bytes) -> Result<HttpResponse> {
|
||||
// Write bytes to file
|
||||
std::fs::write("image.png", &image_data).unwrap();
|
||||
|
||||
// Return the blurred image bytes
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body("{\"status\": 200}"))
|
||||
@@ -87,8 +81,6 @@ async fn main() -> std::io::Result<()> {
|
||||
App::new()
|
||||
.route("/static/{filename:.*}", web::get().to(static_serve))
|
||||
.service(hello)
|
||||
.service(load_small_image)
|
||||
.service(load_big_image)
|
||||
.service(save_big_image)
|
||||
.service(simulation_harmonic_progression)
|
||||
.service(simulation_json)
|
||||
|
1
Express
Submodule
1
Express
Submodule
Submodule Express added at 930a322dfa
@@ -6,12 +6,17 @@ ENV PYTHONUNBUFFERED=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y imagemagick && apt-get install -y wget && ls
|
||||
RUN apt-get update && \
|
||||
apt-get install -y wget unzip && \
|
||||
wget https://github.com/protocolbuffers/protobuf/releases/download/v25.0/protoc-25.0-linux-x86_64.zip && \
|
||||
unzip protoc-25.0-linux-x86_64.zip && \
|
||||
mv bin/protoc /usr/local/bin/ && \
|
||||
rm -rf protoc-25.0-linux-x86_64.zip bin include readme.txt
|
||||
|
||||
RUN wget https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/81Bkht5C/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/nAndfAjK/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/RzXwJG7o/nginx.html && \
|
||||
RUN wget https://files.ivanch.me/api/public/dl/ch3NV0P8/small-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/jNlXYMLR/big-image.png && \
|
||||
wget https://files.ivanch.me/api/public/dl/QdKvaeQI/video.mp4 && \
|
||||
wget https://files.ivanch.me/api/public/dl/YD4vmSsO/nginx.html && \
|
||||
rm -rf runtimes && \
|
||||
mkdir -p ./static && \
|
||||
mv small-image.png ./static && \
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
@@ -5,36 +5,6 @@ from flask import request, Response, Blueprint, jsonify, send_file
|
||||
image_blueprint = Blueprint('image_blueprint', __name__)
|
||||
image_service = ImageService()
|
||||
|
||||
@image_blueprint.route('/image/blur', methods=['POST'])
|
||||
def blur_image():
|
||||
radius = int(request.args.get('radius'))
|
||||
image = request.get_data()
|
||||
|
||||
if radius and image:
|
||||
return send_file(io.BytesIO(image_service.box_blur_image(image, radius)),
|
||||
mimetype='image/png',
|
||||
as_attachment=True,
|
||||
download_name='blurred_image.png')
|
||||
|
||||
return "Bad request", 400
|
||||
|
||||
|
||||
@image_blueprint.route('/image/load-small-image', methods=['GET'])
|
||||
def get_simple_image():
|
||||
return send_file(io.BytesIO(image_service.get_simple_image()),
|
||||
mimetype='image/png',
|
||||
as_attachment=True,
|
||||
download_name='small-image.png')
|
||||
|
||||
|
||||
@image_blueprint.route('/image/load-big-image', methods=['GET'])
|
||||
def get_big_image():
|
||||
return send_file(io.BytesIO(image_service.get_big_image()),
|
||||
mimetype='image/png',
|
||||
as_attachment=True,
|
||||
download_name='big-image.png')
|
||||
|
||||
|
||||
@image_blueprint.route('/image/save-big-image', methods=['POST'])
|
||||
def save_image():
|
||||
image_service.save_image(request.get_data())
|
||||
|
@@ -1,4 +1,5 @@
|
||||
from flask import request, Blueprint, jsonify
|
||||
import person_pb2
|
||||
|
||||
simulation_blueprint = Blueprint('simulation_blueprint', __name__)
|
||||
|
||||
@@ -25,6 +26,16 @@ def return_ok():
|
||||
|
||||
return str(sum), 200
|
||||
|
||||
@simulation_blueprint.route('/simulation/json', methods=['GET'])
|
||||
@simulation_blueprint.route('/simulation/json', methods=['POST'])
|
||||
def return_helloworld():
|
||||
return simulation_controller.return_helloworld(), 200
|
||||
data = request.json
|
||||
return data, 200
|
||||
|
||||
@simulation_blueprint.route('/simulation/protobuf', methods=['POST'])
|
||||
def return_protobuf():
|
||||
bytes_data = request.data
|
||||
|
||||
helloworld = person_pb2.Person()
|
||||
helloworld.ParseFromString(bytes_data)
|
||||
|
||||
return helloworld.SerializeToString(), 200
|
||||
|
@@ -4,4 +4,4 @@ status_blueprint = Blueprint('status_blueprint', __name__)
|
||||
|
||||
@status_blueprint.route('/status/ok', methods=['GET'])
|
||||
def return_ok():
|
||||
return 200
|
||||
return '', 200
|
||||
|
9
FlaskAPI/person.proto
Normal file
9
FlaskAPI/person.proto
Normal file
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message Person {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
repeated string friends = 3;
|
||||
string email = 4;
|
||||
string phone = 5;
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: helloworld.proto
|
||||
# source: person.proto
|
||||
# Protobuf Python Version: 4.25.0
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
@@ -14,13 +14,13 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\"\x18\n\x05MyObj\x12\x0f\n\x07message\x18\x01 \x01(\tb\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cperson.proto\"R\n\x06Person\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03\x61ge\x18\x02 \x01(\x05\x12\x0f\n\x07\x66riends\x18\x03 \x03(\t\x12\r\n\x05\x65mail\x18\x04 \x01(\t\x12\r\n\x05phone\x18\x05 \x01(\tb\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'person_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
_globals['_MYOBJ']._serialized_start=20
|
||||
_globals['_MYOBJ']._serialized_end=44
|
||||
_globals['_PERSON']._serialized_start=16
|
||||
_globals['_PERSON']._serialized_end=98
|
||||
# @@protoc_insertion_point(module_scope)
|
@@ -1,3 +1,3 @@
|
||||
Flask>=1.0
|
||||
gunicorn>=19.9.0
|
||||
Wand
|
||||
Flask==3.0
|
||||
gunicorn==19.9.0
|
||||
protobuf==4.25.0
|
@@ -1,49 +1,7 @@
|
||||
from wand.image import Image, Color
|
||||
|
||||
def box_blur_image_separable(image, radius_x, radius_y):
|
||||
width, height = image.width, image.height
|
||||
kernel_x_size = 2 * radius_x + 1
|
||||
kernel_y_size = 2 * radius_y + 1
|
||||
kernel_area = kernel_x_size * kernel_y_size
|
||||
|
||||
blurred_image = image.clone()
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
r_total, g_total, b_total = 0, 0, 0
|
||||
|
||||
for offset_y in range(-radius_y, radius_y + 1):
|
||||
for offset_x in range(-radius_x, radius_x + 1):
|
||||
new_x = x + offset_x
|
||||
new_y = y + offset_y
|
||||
|
||||
if 0 <= new_x < width and 0 <= new_y < height:
|
||||
pixel = image[new_x, new_y]
|
||||
r_total += pixel.red_int8
|
||||
g_total += pixel.green_int8
|
||||
b_total += pixel.blue_int8
|
||||
|
||||
r_avg = int(r_total / kernel_area)
|
||||
g_avg = int(g_total / kernel_area)
|
||||
b_avg = int(b_total / kernel_area)
|
||||
|
||||
blurred_image[x, y] = Color(f'rgb({r_avg},{g_avg},{b_avg})')
|
||||
|
||||
return blurred_image
|
||||
|
||||
class ImageService:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def box_blur_image(self, img, radius):
|
||||
with Image(blob=img) as image:
|
||||
image.gaussian_blur(radius, radius)
|
||||
return image.make_blob()
|
||||
|
||||
# blurred_image = box_blur_image_separable(image, radius, 0)
|
||||
# blurred_image = box_blur_image_separable(blurred_image, 0, radius)
|
||||
# return blurred_image.make_blob()
|
||||
|
||||
def get_simple_image(self):
|
||||
with open("./static/small-image.png", "rb") as file:
|
||||
return file.read()
|
||||
|
1
Spring
Submodule
1
Spring
Submodule
Submodule Spring added at 1c28f5c8e3
@@ -40,7 +40,7 @@ services:
|
||||
tcc-express:
|
||||
image: tcc:express
|
||||
container_name: tcc-express
|
||||
build: ./tcc-express
|
||||
build: ./Express
|
||||
restart: always
|
||||
ports:
|
||||
- "9084:5000"
|
||||
@@ -52,7 +52,7 @@ services:
|
||||
tcc-spring:
|
||||
image: tcc:spring
|
||||
container_name: tcc-spring
|
||||
build: ./springtcc
|
||||
build: ./Spring
|
||||
restart: always
|
||||
ports:
|
||||
- "9085:8080"
|
||||
|
@@ -1,7 +1,22 @@
|
||||
import helloworld_pb2
|
||||
import json
|
||||
import person_pb2
|
||||
|
||||
helloworld = helloworld_pb2.MyObj()
|
||||
helloworld.message = "Hello World!"
|
||||
person_proto = person_pb2.Person()
|
||||
person_proto.name = "John Doe"
|
||||
person_proto.age = 30
|
||||
person_proto.friends.extend(["Jane Doe", "John Smith"])
|
||||
person_proto.email = "john.doe@email.com"
|
||||
person_proto.phone = "123-456-7890"
|
||||
person_proto = person_proto.SerializeToString()
|
||||
|
||||
person_json = {
|
||||
"name": "John Doe",
|
||||
"age": 30,
|
||||
"friends": ["Jane Doe", "John Smith"],
|
||||
"email": "john.doe@email.com",
|
||||
"phone": "123-456-7890"
|
||||
}
|
||||
person_json = json.dumps(person_json)
|
||||
|
||||
FRAMEWORKS = [
|
||||
('Actix', 'tcc-actix', 'orange'),
|
||||
@@ -19,17 +34,14 @@ ENDPOINTS = {
|
||||
'Spring': 'http://localhost:9085',
|
||||
}
|
||||
|
||||
AVG_RUNS = 5
|
||||
helloworld_pb2
|
||||
AVG_RUNS = 30
|
||||
|
||||
API_REQUESTS = [
|
||||
('/status/ok', 'GET', range(0, 30_000, 5000), None),
|
||||
# ('/simulation/harmonic-progression?n=100000', 'GET', range(0, 30_000, 5000), None),
|
||||
# ('/simulation/json', 'GET', range(0, 30_000, 5000), None),
|
||||
# ('/image/save-big-image', 'POST', range(0, 500, 50), open('big-image.png', 'rb').read()),
|
||||
# ('/image/load-small-image', 'GET', range(0, 30_000, 5000), None),
|
||||
# ('/static/small-image.png', 'GET', range(0, 30_000, 5000), None),
|
||||
# ('/image/load-big-image', 'GET', range(0, 500, 50), None),
|
||||
# ('/static/big-image.png', 'GET', range(0, 500, 50), None),
|
||||
# ('/static/nginx.html', 'GET', range(0, 30_000, 5000), None),
|
||||
('/simulation/protobuf', 'POST', range(0, 30_000, 5000), helloworld.SerializeToString()),
|
||||
('/simulation/harmonic-progression?n=100000', 'GET', range(0, 30_000, 5000), None),
|
||||
('/simulation/json', 'POST', range(0, 30_000, 5000), (person_json, "application/json")),
|
||||
('/simulation/protobuf', 'POST', range(0, 30_000, 5000), (person_proto, "application/protobuf")),
|
||||
('/image/save-big-image', 'POST', range(0, 500, 50), (open('big-image.png', 'rb').read(), "image/png")),
|
||||
('/static/small-image.png', 'GET', range(0, 30_000, 5000), None),
|
||||
('/static/big-image.png', 'GET', range(0, 500, 50), None),
|
||||
]
|
||||
|
@@ -10,19 +10,20 @@ FRAMEWORKS = [f for f, _, _ in FRAMEWORKS]
|
||||
def setBoxColors(bp):
|
||||
for i, box in enumerate(bp['boxes']):
|
||||
box.set(color=FRAMEWORKS_COLORS[i])
|
||||
for i, median in enumerate(bp['medians']):
|
||||
# median.set(color=FRAMEWORKS_COLORS[i])
|
||||
median.set(color='white')
|
||||
|
||||
box.set(facecolor=FRAMEWORKS_COLORS[i])
|
||||
for i in range(len(FRAMEWORKS)):
|
||||
bp['whiskers'][i*2].set(color=FRAMEWORKS_COLORS[i])
|
||||
bp['whiskers'][i*2 + 1].set(color=FRAMEWORKS_COLORS[i])
|
||||
for i in range(len(FRAMEWORKS)):
|
||||
bp['caps'][i*2].set(color=FRAMEWORKS_COLORS[i])
|
||||
bp['caps'][i*2 + 1].set(color=FRAMEWORKS_COLORS[i])
|
||||
for i, median in enumerate(bp['medians']):
|
||||
median.set(color='white')
|
||||
|
||||
|
||||
def plot_graph(x_data, y_data, title, x_label, y_label, filename, y_lim = None):
|
||||
print(filename)
|
||||
|
||||
old_x_data = x_data
|
||||
old_y_data = y_data
|
||||
|
||||
@@ -39,40 +40,20 @@ def plot_graph(x_data, y_data, title, x_label, y_label, filename, y_lim = None):
|
||||
for f in range(len(FRAMEWORKS)):
|
||||
y_data[-1][f].append(old_y_data[f][i])
|
||||
|
||||
fig = figure()
|
||||
ax = axes()
|
||||
fig, axes = plt.subplots(ncols=len(x_data), sharey=True)
|
||||
|
||||
all_positions = []
|
||||
|
||||
print(filename)
|
||||
# print(y_data)
|
||||
for j in range(len(x_data)):
|
||||
positions = [len(FRAMEWORKS)*j + i + 2*j for i in range(len(FRAMEWORKS))]
|
||||
|
||||
bp = boxplot(y_data[j], positions = positions, widths = 0.6, showfliers=False,
|
||||
patch_artist=True)
|
||||
all_positions.append(positions)
|
||||
for ax, j in zip(axes, [i for i in range(len(x_data))]):
|
||||
bp = ax.boxplot(y_data[j], showfliers=False, patch_artist=True, positions=[i for i in range(len(FRAMEWORKS))])
|
||||
ax.set(xlabel=x_data[j], xticklabels=['' for _ in range(len(FRAMEWORKS))])
|
||||
ax.margins(0.05)
|
||||
setBoxColors(bp)
|
||||
if j % 2 == 1:
|
||||
ax.set_facecolor('#f2f2f2')
|
||||
|
||||
for i in range(len(FRAMEWORKS)):
|
||||
medians = []
|
||||
for j in range(len(x_data)):
|
||||
medians.append(np.median(y_data[j][i]))
|
||||
|
||||
positions = [all_positions[x][i] for x in range(len(x_data))]
|
||||
plt.plot(positions, medians, color=FRAMEWORKS_COLORS[i], marker='.', linestyle='--', linewidth=0.3)
|
||||
|
||||
avg_positions = []
|
||||
for positions in all_positions:
|
||||
avg = np.average(positions)
|
||||
avg_positions.append(avg)
|
||||
|
||||
ax.set_xticks(avg_positions)
|
||||
ax.set_xticklabels([str(x) for x in x_data])
|
||||
|
||||
plt.title(title)
|
||||
plt.xlabel(x_label)
|
||||
plt.ylabel(y_label)
|
||||
# set title
|
||||
fig.suptitle(title)
|
||||
fig.supxlabel(x_label)
|
||||
fig.supylabel(y_label)
|
||||
|
||||
if y_lim:
|
||||
plt.ylim(y_lim)
|
||||
@@ -85,6 +66,7 @@ def plot_graph(x_data, y_data, title, x_label, y_label, filename, y_lim = None):
|
||||
plt.legend()
|
||||
|
||||
plt.tight_layout()
|
||||
fig.subplots_adjust(hspace=0, wspace=0)
|
||||
plt.savefig(f'{filename}.png')
|
||||
|
||||
plt.clf()
|
||||
|
@@ -1,5 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message MyObj {
|
||||
string message = 1;
|
||||
}
|
@@ -15,8 +15,8 @@ def download_file(url):
|
||||
|
||||
def init():
|
||||
if not os.path.exists('small-image.png'):
|
||||
download_file('https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png')
|
||||
download_file('https://files.ivanch.me/api/public/dl/ch3NV0P8/small-image.png')
|
||||
if not os.path.exists('big-image.png'):
|
||||
download_file('https://files.ivanch.me/api/public/dl/iFuXSNhw/big-image.png')
|
||||
download_file('https://files.ivanch.me/api/public/dl/jNlXYMLR/big-image.png')
|
||||
|
||||
init()
|
9
scripts/person.proto
Normal file
9
scripts/person.proto
Normal file
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message Person {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
repeated string friends = 3;
|
||||
string email = 4;
|
||||
string phone = 5;
|
||||
}
|
26
scripts/person_pb2.py
Normal file
26
scripts/person_pb2.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: person.proto
|
||||
# Protobuf Python Version: 4.25.0
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cperson.proto\"R\n\x06Person\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03\x61ge\x18\x02 \x01(\x05\x12\x0f\n\x07\x66riends\x18\x03 \x03(\t\x12\r\n\x05\x65mail\x18\x04 \x01(\t\x12\r\n\x05phone\x18\x05 \x01(\tb\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'person_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
_globals['_PERSON']._serialized_start=16
|
||||
_globals['_PERSON']._serialized_end=98
|
||||
# @@protoc_insertion_point(module_scope)
|
31
scripts/protobuftest.py
Normal file
31
scripts/protobuftest.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import person_pb2
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
async def fetch(session):
|
||||
obj = get_object()
|
||||
# async with session.post('http://172.25.96.1:9090/simulation/protobuf', data=obj.SerializeToString(),
|
||||
async with session.post('http://127.0.0.1:5000/simulation/protobuf', data=obj.SerializeToString(),
|
||||
headers={"content-type": "application/protobuf"}) as resp:
|
||||
print(resp.status)
|
||||
data = await resp.read()
|
||||
receiveObj = person_pb2.Person()
|
||||
receiveObj.ParseFromString(data)
|
||||
print(receiveObj)
|
||||
|
||||
async def go(loop):
|
||||
async with aiohttp.ClientSession(loop=loop) as session:
|
||||
await fetch(session)
|
||||
|
||||
def get_object():
|
||||
obj = person_pb2.Person()
|
||||
obj.name = "John Doe"
|
||||
obj.age = 30
|
||||
obj.friends.extend(["Jane Doe", "John Smith"])
|
||||
obj.email = "john.doe@email.com"
|
||||
obj.phone = "123-456-7890"
|
||||
return obj
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(go(loop))
|
||||
loop.close()
|
4
scripts/requirements.txt
Normal file
4
scripts/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
protobuf>=4.25.0
|
||||
matplotlib
|
||||
numpy
|
||||
docker
|
@@ -14,7 +14,7 @@ FRAMEWORK_NAME = ""
|
||||
CONTAINER_NAME = ""
|
||||
URL_BASE = 'http://localhost:9090'
|
||||
|
||||
def send_request(url, method = 'GET', payload = None):
|
||||
def send_request(url, method = 'GET', data = None):
|
||||
success = False
|
||||
responses = {
|
||||
2: 0, # OK
|
||||
@@ -27,7 +27,9 @@ def send_request(url, method = 'GET', payload = None):
|
||||
if method == 'GET':
|
||||
response = requests.get(url)
|
||||
elif method == 'POST':
|
||||
response = requests.post(url, data=payload, headers={'Content-Type': 'image/png'})
|
||||
payload = data[0]
|
||||
content_type = data[1]
|
||||
response = requests.post(url, data=payload, headers={'Content-Type': content_type})
|
||||
except:
|
||||
continue
|
||||
success = response.status_code == 200
|
||||
@@ -74,8 +76,6 @@ def run_tests(endpoint, method, num_requests, metadata):
|
||||
start_time = time.time()
|
||||
|
||||
futures = []
|
||||
#with requests.Session() as session:
|
||||
# futures = [executor.submit(send_request, session, url) for _ in range(num_request)]
|
||||
|
||||
half = floor(num_request/2)
|
||||
for i in range(num_request):
|
||||
@@ -102,7 +102,7 @@ def run_tests(endpoint, method, num_requests, metadata):
|
||||
record(files[0], num_request, f"{num_request/elapsed_time:.2f}")
|
||||
record_resource(files[1], num_request, cpu, ram)
|
||||
|
||||
time.sleep(3)
|
||||
time.sleep(30)
|
||||
|
||||
def get_resource_usage():
|
||||
if CONTAINER_NAME == "": return 0, 0
|
||||
|
Submodule tcc-express deleted from 504b59278f
Reference in New Issue
Block a user