Thursday, October 29, 2015

File I/O Performance comparision between Java 1.7.x and Python 2.7.x

Although I have been a Java developer for over a decade now, but I would try to be as neutral as possible. The idea is to compare the basic operations and capabilities of various languages viz. Python and Java.

The Operation: following is the list of operations performed in the languages

Here is the hardware of the machine on which both the languages were tested:

CPU: 4 core CPU. Intel 64 bit
Memory: 8GB RAM. Processes were running at 128MB
Disk: 40 GB. More than 80% free.
OS: Redhat v 6.5.0.1.el6.x86_64






Although the above test might not dictate the use case in your organization, however it might give you a lead to make decision. Please feel free to comment if you wish to discuss further :) .

Monday, February 23, 2015

An HTTP request duplicator using node.js

A lot of times we feel the need to duplicate a request to multiple servers or ports maybe because the source is one or maybe because we want different actions to be taken on the same request. I had a similar problem where I had multiple servers which were used by different teams and all the teams were expecting a particular request on their VMs. However the problem was that the source of request was single. Thus, there was no option but to develop something to accomplish the above task.

Writing something from scratch in Java/.NET would give me flexibility but would take a lot of time to develop. Then I came across duplicator open source project which I modified to enable it to duplicate the same request to multiple targets.

The source code is hosted at https://github.com/ameyakhasgiwala/multi-duplicator and the single script file can be downloaded or forked if required. I am also pasting the script here for readability

The script can be configured with parameters.
-p: the port on which the script will listen for requests
-f: single -f parameter specifying the VM:port to which the request should be forwarded.
-d: multiple -d parameters specifying the VM:port to which the request should be duplicated.

node /usr/local/bin/multi-duplicator -p 8102 -f server1.myorg:9876 -d server2.otherorg:1234 -d server3.org3:3456



#!/usr/bin/env node
// vim: set ft=javascript:

var cluster = require('cluster')
var colors = require('colors')
var log = console.log.bind(console, '[Cluster]'.blue)

if (cluster.isMaster) {

  var opts = require('optimist')
      .usage('Usage: $0 [-hv] -p port -f host:port [-d host:port] [-r int]')
      .options('h',
        { alias: 'help'
        , describe: 'show usage information'
        })
      .options('v',
        { alias: 'version'
        , describe: 'show version information'
        })
      .options('p',
        { alias: 'port'
        , describe: 'port to listen on, defaults to PORT'
        , 'default': process.env['PORT']
        })
      .options('f',
        { alias: 'forward'
        , describe: 'host to forward to'
        })
      .options('d',
        { alias: 'duplicate'
        , describe: 'host to duplicate to'
        })
      .options('r',
        { alias: 'rate'
        , describe: 'rate to sample traffic'
        , 'default': 1
        })
      .check(function(argv){
        if (argv.h) throw ''

        if (argv.v) {
          console.log(duplicator.version)
          process.exit()
        }

        if (!argv.p) throw 'You must specify a port, either via the -p option or' +
          'in the PORT environment variable'

        if (!argv.f) throw 'You must specify a host to forward to with -f option'
      })
    , argv = opts.argv

  function serverInfo() {
    log("Listening on port:", argv.p)
    if (argv.f) log("Forwarding to:", argv.f)
    if (argv.d) log("Duplicating to:", argv.d)
    if (argv.r) log("Sample rate:", argv.r)
    log(Array.isArray(argv.d))
  }

  var workers = {}
  function spawn(argv) {
    var worker = cluster.fork()
    workers[worker.pid] = worker
    worker.send(argv)
    return worker
  }

  var count = require('os').cpus().length
  for (var i = 0; i < count; i++) {
    spawn(argv)
  }

  serverInfo()

  cluster.on('exit', function(worker) {
    log('worker ' + worker.pid + ' died. spawning a new process...')
    delete workers[worker.pid]
    spawn(argv)
  })

} else {

  var duplicator = require('../')
  log = console.log.bind(console, '[Worker]'.green)
  process.on('message', function(argv) {
    log('worker started with pid', process.pid)

    var server = duplicator(function(client, forward, duplicate) {
      if (argv.f) forward(argv.f)
      if (argv.d) {
        if (Array.isArray(argv.d)) {
          argv.d.forEach (function(dup) {
            log("duplicating request to", dup)
            duplicate(dup, argv.r)
          })
        }
        else {
          duplicate(argv.d, argv.r)
        }
      }
    })
    server.listen(argv.p)
  })
}