Monday, February 17, 2020

Recursive Matrix and the parallel matrix multiplication using crossbeam and generic constant

This was planned project I posted before.
Basically in order to evaluate Rust's claim for zero cost abstraction and the effectiveness of parallel processing of Rust, I implemented novel Recursive Matrix and the parallel matrix multiplication.

Probably this recursive matrix multiplication would be implemented somewhere, but this is my original idea. this idea is re-interpreting matrix as matrix of its sub matrix. for instance 16X16 matrix can be interpreted as 2X2 matrix of 8X8 matrix. using this, we can reduce the size of matrix dimension.(e.g, 16 to 8 or 2). this has a good effect for large dimension matrix. often too large dimension will cause space problem also stack based array has a rather small limitation for the size of matrix. Also GPU has fixed size of matrix.(or max like 512 etc)
This reduction can be applied to the sub matrix itself recursively, we can reduce the  size of matrix under given limited size if we want.

This approach should be implemented in high level of abstraction, like Ring, Algebra, Matrix using generic trait/functions, moreover, the dimension should be part of generic parameter.

So the main idea is expressed in lift(lower) function:

pub fn lift<R: Ring, const DIM: usize, const DIM0: usize, const DIM1: usize>
(m: &ArrayMatrix::<R, DIM>)-> ArrayMatrix<ArrayMatrix<R, DIM1>, DIM0>;
   
pub fn lower<R: Ring, const DIM: usize, const DIM0: usize, const DIM1: usize>
(m: &ArrayMatrix<ArrayMatrix<R, DIM1>, DIM0>)-> ArrayMatrix::<R, DIM>;

this list function transform DIM = DIM0*DIM1 dimension matrix to DIM0 matrix of DIM1 matrix.
lower function is reverse direction.

This generic matrix is based on coeffient ring's operators. Since DIM1 matrix is ring, we can use the same generic function to implement this nested matrix.

For the parallel computation of matrix, we create cleanly separated jobs based on this nexted matrix multiplication.
For instance, 256 dimension matrix can be expressed by 2x2 matrix with 128x128 matrix.
let M = A*B, then M[i][j] = A[i][0]*B[0][j]+ A[i][1]*B[1][j], so we can create 4 jobs to calculate nested matrix entry. then these jobs are send to a channel and we can create any number of consumer threads, and they also post the result to another channel.
if there are only 4 jobs, it can only use 4 threads, so in order to maximize the CPU core usage, we should create 4x4 matrix with 64x64 matrix insted. in this case, this can use up to 16 CPU threads.

We will see such improvement for these cases although it will not be 8 time faster where we use 8 threads on 8 threads CPU.



Friday, January 31, 2020

reverse proxy in java

Several proxy server implementations are available in Java, but I found following lib is pretty useful.
https://github.com/mitre/HTTP-Proxy-Servlet

we can put the class in servlet and edit web.xml, no source code need to be changed.
using this, we can delegate pdf generation from servlet to node server.

---

Here's an example excerpt of a web.xml file to communicate to a Solr server:
<servlet>
    <servlet-name>solr</servlet-name>
    <servlet-class>org.mitre.dsmiley.httpproxy.ProxyServlet</servlet-class>
    <init-param>
      <param-name>targetUri</param-name>
      <param-value>http://solrserver:8983/solr</param-value>
    </init-param>
    <init-param>
      <param-name>log</param-name>
      <param-value>true</param-value>
    </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>solr</servlet-name>
  <url-pattern>/solr/*</url-pattern>
</servlet-mapping>
--

we may further combin(or replace) this with rust's proxy based on tokio and headless chrome to generate pdf.

Puppeteer on Rust

Puppeteer  is a powerful tool to control web application at server side using headless chromium.
This is mainly used for automated testing, but one of the useful feature is generating pdf from html.

One of the  main problem of generating PDF from html on client side browser is that the layout may change when the browser is updated(Actually I only considering Chrome/chromium).

So if the PDF generation is done at server side, we can fix the specific version of chromium at server side, but client can update the browser without loosing correct layout of pdf.

This Puppeteer  can be installed by 'npm i puppeteer'
Following is the sample code for support httpserver to convert html into pdf.
This service takes parameters, and generate html string from them and create pdf from the generated html string, so no file system is used for html and pdf.(efficient)


const http = require('http');

http.createServer((request, response) => {
    //console.log('request.url: '+request.url)
    //console.log('request.method: '+request.method)
    if (request.method === 'POST' && request.url === '/nodejs/template-pdf-gen') {
      var ctx = null;
      request.on('data', (chunk) => {
        ctx = JSON.parse(chunk);
      }).on('end', async () => {
        const browser = await puppeteer.launch({ headless: true }) 
        const page = await browser.newPage();  
        var url = 'file://'+ctx.webRootPath.replace(/\\/g, '/');
        var html = generate_html(ctx);

        await page.goto(url);
        await page.setContent(html);

        var pdf = await page.pdf({
          format: 'A4',
          margin: {
                top: "20px",
                left: "20px",
                right: "20px",
                bottom: "20px"
          }   
        });
        await browser.close();        
        response.end(pdf);
      });
    } else {
      response.statusCode = 404;
      response.end();
    }
  }).listen(8989);



There are a few trick in the above code.
1) in order to process link element in the HTML file which refer to the  local file, we need to use page.goto(url), before calling page.setContent(html)

2) the root web location must be provided from client.(we may hard code this, but if it is in a war file, we cannot hard code the folder location statically).

3) in case of Java servlet, there is a method getServletContext().getRealPath("/") which provide this info. webRootPath in the above code has this value.

----

It we are only interested in generating pdf, there is way to use RUST library to do the same job.
 https://github.com/atroche/rust-headless-chrome

there are another similar tool but not restricted to chrome:https://github.com/jonhoo/fantoccini

Saturday, January 18, 2020

reverse proxy server in rust

There are several reverse proxy server.
Following crate seems easy to use.

https://docs.rs/hyper-reverse-proxy/0.4.0/hyper_reverse_proxy/

sozu is difficult to build in windows, and a bit old (2018).

if we use this, existing server app running in Glassfish can be moved to Rust based server without affecting the client side application. For instance, db related server side code can be migrated to Rust base server.

extern crate hyper;
extern crate futures;

use hyper::server::conn::AddrStream;
use hyper::{Body, Request, Server};
use hyper::service::{service_fn, make_service_fn};
use futures::future::{Future};

fn main() {

    // This is our socket address...
    let addr = ([127, 0, 0, 1], 13900).into();

    // A `Service` is needed for every connection.
    let make_svc = make_service_fn(|socket: &amp;AddrStream| {
        let remote_addr = socket.remote_addr();
        service_fn(move |req: Request<body>| { // returns BoxFut
            println!("path: {}, ip: {}", req.uri().path(), remote_addr.ip());
            return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:8080", req)
        })
    });

    let server = Server::bind(&amp;addr)
        .serve(make_svc)
        .map_err(|e| eprintln!("server error: {}", e));

    println!("Running server on {:?}", addr);

    // Run this server for... forever!
    hyper::rt::run(server);
}






Wednesday, January 15, 2020

Parallel matrix computation in Rust

Parallel matrix computation is an interesting topic to test how much the zero cost abstraction is achieved in Rust.
Also if it can increase the performance, it is practically useful.

These should be used for Magnus expansion.

I will write such code later.


Multi threaded HTTP server using crossbeam

The Rust book has a section on multi threaded HTTP server, and I found the corresponding implementation on github.
https://github.com/richardknox/rust-webserver

This was actually published 2 years ago.
While the code is pretty neat, but it is intersting to implement this with crossbeam so that it can directly apply SPMC channel. basically this is typical situation for load balance server.

In fact, the straight forward modification did not work.
it seems better to use hyper.

there is an interesting github, that is quite close to my goal. but it is not using crossbeam.
So it would be better to use this for multi threaded http server imple with crossbeam.

https://github.com/hyperium/hyper/issues/1358

https://gist.github.com/klausi/93b57d3abe2c5bc4975b0b9921f2a3c2


Go program may be useful:
 https://github.com/dc0d/tcpserver/blob/master/tcpserver.go

------

After trying to combine crossbeam and tokio, I found this is not simple.
In particular the latest approach of Tokio rely on async, and async and thread seems not easy to coexist.
Once process function includes async code, all code must be async.
And thread's parameter closure should not be async, and the free variable are not permitted because of the lifetime of variable.
 there have been some discussion over mpsc channel against mpmc like approach, and if we use these Tokio, hyper library, we may not have to use mpmc at least for http related application.
since it already supports multi threaded handlers.

Anyway I will investigate hyper now. (hyper uses tokio)

https://tokio.rs/

https://hyper.rs/

https://github.com/hyperium/hyper


Tuesday, January 14, 2020

Why no traits for collections in Rust?

I tried to write a generic function which converts a list to a receiver channel.
Originally I wrote this function taking Vec, but I wanted to change to Collection type which is sort of 'super' type of Vec, but there is no such type in Rust.

There are interesting research in this direction in Rust.


https://www.reddit.com/r/rust/comments/83q25s/why_no_traits_for_collections_in_rust/

Why no traits for collections in Rust?

In Java, there are interfaces such as Collection and Map that are used to identify generic collections--e.g. ArrayList and HashSet implement Collection, and HashMap and TreeMap implement Map.
I'd like having this capability in Rust as well, in case I'm designing a library and want the user to be able to decide which implementation of a collection they'd like to use. However, I noticed Rust doesn't have traits to represent a generic collection. I was wondering if this was an intentional design decision and what the reasoning was.


http://smallcultfollowing.com/babysteps/blog/2016/11/02/associated-type-constructors-part-1-basic-concepts-and-introduction/


https://github.com/rust-lang/rfcs/pull/1598

Recursive Matrix and the parallel matrix multiplication using crossbeam and generic constant

This was planned project I posted before. Basically in order to evaluate Rust's claim for zero cost abstraction and the effectiveness o...