Browse Source

Rust: hyper on tokio-proto/service (#2619)

Refresh for hyper benchmark based on tokio-proto and tokio-service.
serde-derive is used for json serialization as that's what people
will do in real app.
Max Gortman 8 years ago
parent
commit
09a729dd39

+ 8 - 6
frameworks/Rust/hyper/Cargo.toml

@@ -1,16 +1,18 @@
 [package]
 name = "hello"
-version = "0.2.0"
+version = "0.3.0"
 authors = ["Steve Klabnik <[email protected]>", "Alexander Polyakov <[email protected]>"]
 
 [dependencies]
-net2 = "0.2"
 futures = "0.1"
-pretty_env_logger = "0.1"
-log = "0.3.6"
-tokio-core = "0.1"
+tokio-proto = "0.1"
+tokio-service = "0.1"
 num_cpus = "1.2"
+serde = "0.9"
+serde_json = "0.9"
+serde_derive = "0.9"
+mime = "0.2"
 
 [dependencies.hyper]
 git = "https://github.com/hyperium/hyper/"
-rev = "39a53fcd3364634125dafcf4d7a1d191241a7ff0"
+rev = "43cf9aefe8f9147a0f08aa0f9d609d275549fd7c"

+ 1 - 0
frameworks/Rust/hyper/benchmark_config.json

@@ -3,6 +3,7 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
+      "json_url": "/json",
       "plaintext_url": "/plaintext", 
       "port": 8080,
       "approach": "Realistic",

+ 1 - 1
frameworks/Rust/hyper/setup.sh

@@ -4,4 +4,4 @@ fw_depends postgresql rust
 
 cargo clean
 cargo build --release
-cargo run --release &
+./target/release/hello &

+ 39 - 43
frameworks/Rust/hyper/src/main.rs

@@ -1,23 +1,29 @@
 extern crate futures;
+extern crate tokio_proto;
+extern crate tokio_service;
 extern crate hyper;
-extern crate pretty_env_logger;
 #[macro_use]
-extern crate log;
-extern crate net2;
-extern crate tokio_core;
+extern crate serde_derive;
+extern crate serde_json;
 extern crate num_cpus;
+#[macro_use]
+extern crate mime;
 
-use hyper::{Get, StatusCode};
-use hyper::header::{ContentLength, ContentType};
-use hyper::server::{Server, Service, Request, Response};
-
-use net2::TcpBuilder;
-use net2::unix::UnixTcpBuilderExt;
-use tokio_core::net::TcpListener;
+use tokio_proto::TcpServer;
+use futures::future;
+use hyper::Method::Get;
+use hyper::header::{ContentLength, ContentType, Server};
+use hyper::status::StatusCode::NotFound;
+use hyper::server::{Http, Service, Request, Response};
+use std::net::SocketAddr;
 
 static HELLOWORLD: &'static [u8] = b"Hello, world!";
 
-#[derive(Clone, Copy)]
+#[derive(Serialize)]
+struct JsonResponse<'a> {
+    message: &'a str,
+}
+
 struct TechEmpower;
 
 impl Service for TechEmpower {
@@ -27,44 +33,34 @@ impl Service for TechEmpower {
     type Future = ::futures::Finished<Response, hyper::Error>;
 
     fn call(&self, req: Request) -> Self::Future {
-        ::futures::finished(match (req.method(), req.path()) {
+        let response = match (req.method(), req.path()) {
             (&Get, "/plaintext") => {
-                use hyper::mime::{Mime,TopLevel,SubLevel,Attr,Value};
                 Response::new()
                     .with_header(ContentLength(HELLOWORLD.len() as u64))
-                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])))
+                    .with_header(ContentType(mime!(Text / Plain)))
                     .with_body(HELLOWORLD)
-	    },
-            _ => {
+            }
+            (&Get, "/json") => {
+                let rep = JsonResponse { message: "Hello, world!" };
+                let rep_body = serde_json::to_vec(&rep).unwrap();
                 Response::new()
-                    .with_status(StatusCode::NotFound)
+                    .with_header(ContentLength(rep_body.len() as u64))
+                    .with_header(ContentType(mime!(Application / Json)))
+                    .with_body(rep_body)
             }
-        })
+            _ => Response::new().with_status(NotFound),
+        };
+        future::ok(response.with_header(Server("Hyper".to_string())))
     }
 }
 
-
 fn main() {
-    use std::net::SocketAddr;
-    pretty_env_logger::init().unwrap();
-    let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
-    let mut threads = vec![];
-    for i in 0..num_cpus::get_physical() {
-        use std::thread;
-        let i = i;
-        let handle = thread::spawn(move|| {
-            let (listening, server) = Server::standalone(|tokio| {
-		    let listener = TcpBuilder::new_v4()?.reuse_port(true)?.bind(addr)?.listen(10000)?;
-		    let addr = try!(listener.local_addr());
-		    let listener = try!(TcpListener::from_listener(listener, &addr, tokio));
-		    Server::new(listener.incoming(), addr).handle(|| Ok(TechEmpower), tokio)
-	    }).unwrap();
-            println!("Listening {} on http://{}", i, listening);
-            server.run();
-        });
-        threads.push(handle);
-    }
-    for t in threads {
-        t.join().unwrap();
-    }
-}
+    let addr: SocketAddr = "0.0.0.0:8080".parse().unwrap();
+    let mut srv = TcpServer::new(Http::new(), addr);
+    println!("Listening on http://{} using {} threads",
+             addr,
+             num_cpus::get());
+
+    srv.threads(num_cpus::get());
+    srv.serve(move || Ok(TechEmpower))
+}

+ 1 - 1
toolset/setup/linux/languages/rust.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-RUST_VERSION="1.13.0"
+RUST_VERSION="1.16.0"
 
 fw_installed rust && return 0