Pay in Local Currency While You Are Travelling. It Is Cheaper

Should you pay in local or home currency while travelling?

Short answer. Pay in local currency. For example, I have a credit card from the US and I’m going to be in Hong Kong for my vacation. I should pay in Hong Kong dollar.

Long answer. There’s something about DCC that you have to pay a small fee for the customer to see the amount in home currency in the receipt. Here’s an example.

If I had paid in US dollar, I would have paid \$0.81 more. It doesn’t seem like a lot but it definitely adds up. I checked my credit card transaction and it showed \$19.33. It’s also good if you can get the card that’s free foreign transaction fee.

Feb 25th, 2017

Reservoir Sampling of Size 1

Feb 20th, 2017

OSX Convert Raw DNG to JPG

Problem

I like shooting raw and I’m still doing it. However, there’s a time when I had to Airdrop jpeg to my phone and I didn’t want to go into the trouble of import all the photos to Lightroom and export them again. So I turned to Google and here’s what I found.

I’m lazy and I do most things in my terminal. Here’s the way you can do the same if you want to just quickly convert raw images to jpg.

Solution

  1. You need dcraw which you can use brew to install
1
brew install dcraw
  1. You need cjpeg which is from libjpeg so most likely you will have that already. Otherwise you can install by following these steps from here

  2. Go into your raw photos folder and run this command

1
for i in *; do dcraw -c "$i" | cjpeg -quality 100 -optimize -progressive > $(echo $(basename "$i" ".crw").jpg); done

This command will loop through all the files inside the folder and run dcraw command for each file then pipe it through cjpeg and same to the original name with jpg extension.

I didn’t really check the quality as I just wanted to quickly post on Twitter.

Reference

  1. http://www.mutaku.com/wp/index.php/2011/02/cook-your-raw-photos-into-jpeg-with-linux/
Feb 20th, 2017

Python-request Connection Aborted and Broken Pipe Error

Ever wondered why your long running python script just bombs out mid-way?

If you have seen this error

1
ConnectionError: ('Connection aborted.', error(32, 'Broken pipe'))

It might be that the script takes longer than expected and SSL got cut off before it has the chance to finish the request. This is what I do and it seems to be working. In your ~/.ssh/config add this to your configuration.

1
2
3
Host *
    ServerAliveInterval 300
    ServerAliveCountMax 2

What this does is it’s going to send a NULL packet to the other side every 300 seconds and give up after 2 tries.

Hope this helps everyone.

Reference: - How to keep alive ssh session

Dec 24th, 2016

A Must Item While Travelling in Japan

What is this item?

Short answer is. A pocket Wifi. Or some sort of a way for you to have Internet at your finger tip.

Why this article?

I don’t usually write anything when I’m travelling, but I think this is quiet a different experience I have from other countries I have been to.

I have been to more than 30 countries and I did not experience language barrier as much as I experienced in Japan. Granted, I speak Mandarin so I don’t have a problem in China. I got by easily even in Russia and country like Turkey.

If you’re one of those want-to-unplug travellers, then this article is not for you. If I go hiking, usually I would not care about connectedness. I want to just go out and experience the nature. But for this trip, I visited mostly big cities and I wanted to get as much information I need especially Tokyo.

Japan has one of the most complex train systems in the world. In Tokyo, you have two companies for Subway and multiple train operators. City Mapper helps a lot with the subways but it still lacks information about other train systems to get you to other parts of the city. Uber and Taxi in Toyko are very expensive in my opinion. I used Google Maps all the time and it saved me time and money.

Subway stations in Tokyo is enormous if you get off wrong exit you might have to walk at least 10-15 minutes to get to your destination. Google Maps has very clear indication of where to exit closest to your destination.

I used Google Translate to communicate with one shop assistant because we wanted to get our shoes fixed and he didn’t speak a single English word. So, we handed the phone for him to speak and Google Translate to translate to English for us. It helped tremendously!

If your phone operator has affordable roaming option like T-Mobile in the US then you’re all set.

How to get one of those Pocket Wifis

I researched quite a bit and I chose this http://www.globaladvancedcomm.com/. It’s really easy.

I ordered online two days before my departure and it only costed me $140 for the whole 15 days in Japan. I shared the wifi with 2 other friends. You can choose for them to deliver the wifi to your hotel. When I arrived to the hotel it was waiting for me at the reception.

This is what you get in the envelop.

This is the return envelop that you need to drop in a mailbox

Mailbox at Haneda airport to return the wifi.

During the whole trip, there wasn’t even one occasion where the wifi didn’t work. I got the connection the whole time and the battery lasted for at least from 9am to 7pm. If you have a power bank it can easily last until the end of the day. If you have more devices, I believe you will need to choose the premium one with faster speed.

Dec 5th, 2016

Game of Life for Dummies

Game of life

It’s a game invented by the British mathematician John Horton Conway and the game goes like this.

1
2
3
4
5
6
7

Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):

Any live cell with fewer than two live neighbors dies, as if caused by under-population.
Any live cell with two or three live neighbors lives on to the next generation.
Any live cell with more than three live neighbors dies, as if by over-population..
Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.

Most people know this game because you might be asked during any technical interview to design Game of Life on a whiteboard. But for me, when I first learn how to program I was asked to code Game of Life and it was actually kinda fun. Especially, if you do it in TDD.

Why this post then?

I know there’s a lot of posts out there solving Game of Life in any possible known computer languages, but I feel like all of them are too hard to understand or use advanced library like numpy to solve the problem which makes it really hard to understand for me. Also, if I would like to understand how to solve the problem and if I can’t explain this simply that means I don’t understand at all.

Algorithm

The simplest algorithm goes like this.

  1. Count all the live cells around 8x8 matrix of a cell.
  2. Determine if the next state, the cell lives or dies based on the rules.

So, if you can count all the live cells around a cell, you’re pretty much there.

Naive approach

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Solution(object):
    def gameOfLife(self, board):
        """
        :type board: List[List[int]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        m = len(board)
        n = len(board[0]) if m else 0

        temp_board = [[0] * n for i in range(m)]

        def count_cell(i, j):
          """
          :type i: Column row
          :type j: Column column
          Count all the cells around the cell[i][j]
          """

          list_of_tuples = [(i-1, j-1), (i-1, j), (i-1, j+1),
              (i, j-1), (i, j), (i, j+1),
              (i+1, j-1), (i+1, j), (i+1, j+1)]

          count = 0
          for l in list_of_tuples:
            x, y = l
            if x >= 0 and y >= 0 and x < m and y < n:
              if x is not i or y is not j:
                if board[x][y] == 1:
                  count += 1

          return count

        for i in range(m):
          for j in range(n):
            count = count_cell(i, j)
            temp_board[i][j] = count

        for i in range(m):
          for j in range(n):
            cell = board[i][j]
            count = temp_board[i][j]
            if cell == 1:
              if count < 2:
                board[i][j] = 0
              elif count is 3 or count is 2:
                board[i][j] = 1
              elif count > 3:
                board[i][j] = 0
            else:
              if count == 3:
                board[i][j] = 1

board = [[0,0,0,0,0],
    [0,0,1,0,0],
    [0,0,1,0,0],
    [0,0,1,0,0],
    [0,0,0,0,0]]

Solution().gameOfLife(board)
print(board)

The naive approach is really simple and stupid. There’s a method to count all the cells and put that to a temp board so it can be used to determined the next cycle of the game.

The complexity would be O(m * n) but the space would be O(m * n) as well

First refactor

The first refactoring would be to just loop through the surrounding cell with the check for boundaries.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Solution(object):
    def gameOfLife(self, board):
        """
        :type board: List[List[int]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        m = len(board)
        n = len(board[0]) if m else 0

        temp_board = [[0] * n for i in range(m)]

        def count_cell(i, j):
          """
          :type i: Column row
          :type j: Column column
          Count all the cells around the cell[i][j]
          """
          lives = 0

          for I in range(max(i-1, 0), min(i+2, m)):
            for J in range(max(j-1, 0), min(j+2, n)):
              if I is not i or J is not j:
                lives += board[I][J]
          return lives

        for i in range(m):
          for j in range(n):
            count = count_cell(i, j)
            temp_board[i][j] = count

        for i in range(m):
          for j in range(n):
            cell = board[i][j]
            count = temp_board[i][j]
            if cell == 1:
              if count < 2:
                board[i][j] = 0
              elif count is 3 or count is 2:
                board[i][j] = 1
              elif count > 3:
                board[i][j] = 0
            else:
              if count == 3:
                board[i][j] = 1

board = [[0,0,0,0,0],
    [0,0,1,0,0],
    [0,0,1,0,0],
    [0,0,1,0,0],
    [0,0,0,0,0]]

Solution().gameOfLife(board)
print(board)

It’s a bit better don’t you think?

Second refactor

Now the first two approaches, we have to have a temp board to calculate the next state. Let’s see if we can do better than that by manipulating the board in-place instead of having a temp board.

Someone on the leetcode discussion suggested bit manipulation to store the state of the cell which I think it’s a brilliant idea. However, I feel like there’s not much explanation so I’m going to try to explain it here.

The problem with the second approach is that we have to have a temp board to store the number of surrounding cells so that we can flip it after the whole board has been counted. The problem with this approach is space complexity if the board is really large we need to double the size of memory to store the state of the board.

For example:

1
2
3
4
5
  2nd   1st
0 0 (dead, dead)
0 1 (dead, live)
1 0 (live, dead)
1 1 (live, live)

We have this board

1
2
3
[[0, 0, 0],
 [0, 1, 0],
 [1, 0, 0]]

If we look at the coordinate (1,1) the cell is live and only has 1 surrounding living cell which according to the rule the cell dies because of under-population in the next state. So we can represent that cell as 0 1. The right-most bit represent the first state and the left-most bit represent the next state. So in the case, the cell has value 1 which after we shift it to the right with cell[i][j] >>= 1. It’s going to be 0 which means the cell dies in the next state.

So to refactor the code we will get something like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"""
This is because we only care about live cell that's going to live on to the next state
And the dead cell that's going to come alive
"""

# If the cell is live and the surrounding cells count is either two or three, the cell lives on to the next state
if board[i][j] == 1 and count >= 2 and count <= 3:
    board[i][j] = 3
# If the cell is dead and the surrounding cells count is exactly three, the cell lives on to the next state
if board[i][j] == 0 and count == 3:
    board[i][j] = 2

# Then we flip to the next state
for i in range(m):
    for j in range(n):
        board[i][j] >>= 1

To sum up we will get the code which looks something like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
m = len(board)
n = len(board[0]) if m else 0

temp_board = [[0] * n for i in range(m)]

def count_cell(i, j):
    lives = 0
    for I in range(max(i - 1, 0), min(i + 2, m)):
        for J in range(max(j - 1, 0), min(j + 2, n)):
            if I is not i or J is not j:
                lives += board[I][J] & 1
    return lives

for i in range(m):
  for j in range(n):
    count = count_cell(i, j)
    if board[i][j] == 1 and count >= 2 and count <= 3:
        board[i][j] = 3
    if board[i][j] == 0 and count == 3:
        board[i][j] = 2

for i in range(m):
    for j in range(n):
        board[i][j] >>= 1

You might notice about this line.

1
lives += board[I][J] & 1

This is because we want to just loop through the board once and if we change the number of the current cell to be ready for the next state, the later cell will get the wrong count. To & 1 means we just want to get the current state of the cell whether it’s dead or alive regardless of the total count of the surrounding cells.

Nov 11th, 2016

What Is Going on Under Your JavaScript Code

Disclaimer

I’m no expert in this field nor having a PhD in Compiler. This is just my pure curiosity and I hope to share of what I’ve discovered so people can continue their curiosity.

Why I’m interested in this.

I was asked once during my technical interview, “What happen when you execute fs.readFileSync(‘’)”. What he meant was that how JavaScript code interacts with the machine under the hood. At the time, I thought I just wrote that code and there you go I got the content of the file.

I couldn’t answer and I didn’t get the job. I just recently became a JavaScript developer because of my interest in front-end and back-end in the same time. Knowing JavaScript allows me to get the best of both worlds. However, the only thing I know about JavaScript is that it’s something to do with V8 and I had no idea what’s going on under the hood. So, I took the time to really understand how JavaScript works and the history behind it. So, I started with the task a computer does best; executing commands or how does a computer execute a command.

How does computer works?

One of the best movies for me is “The Core” where “Rat” had to hack the Internet to control the flow of information. The hacker claims that he only knew one language, “zeros and ones”. At the time, I understood that it’s something to do with binary number, and I thought that it’s just hollywood talk and these people didn’t know what they were talking. I have to write print('Hello'); to print Hello on my console, it has nothing to do with zeros or ones.

So, I started digging and I found this.

Basically, when we execute a piece of code, the compiler compiles the code to a set of instructions which is Assembly. Then, we have an assembler to translate the instructions to their numerical equivalents. For example,

1
ADD esp, 8

is translated in x86 architecture like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Raw Hex (zero bytes in bold):

83C408

String Literal:

"\x83\xC4\x08"

Array Literal:

{ 0x83, 0xC4, 0x08 }

Disassembly:
0:  83 c4 08                add    esp,0x8

Notice the HEX code 83C408 which you can translate to binary number later for the computer to understand.

You can use this online assembler to play with it.

How does JavaScript engine (v8) work?

In a nutshell, V8 translates JavaScript code to machine code with JIT (Just-In-Time) compiler.

There are four main stages of how the code passes through V8.

  1. JavaScript - Your code

  2. Hydrogen - Intermediate code

  3. Lithium - Machine specific code

  4. Machine Code - This is what your computer understand.

In this post we’re going to see the assembly code which is the machine specific code.

Show me the code

Enough talking. Now show me the code you say. Let’s say you have a simple function to add two numbers together like this.

1
2
3
function add(a, b) {
  return a + b;
}

To view the machine code in Assembly you need to install V8. First you need to install depot-tools. Once you install depot-tools you can run Follow this instruction.

Note: The documentation of how to install V8 is subject to change. So, please refer to link.

In order to get V8 you need to run. You will also need Python 2

1
2
fetch v8
cd v8

The script will take sometime to finish. It will fetch V8 source code. Then you need to build all the dependencies by running.

1
gclient sync

Now you need to install D8. The next step is going to take a long time. So, get yourself a nice cup of coffee.

1
make x64.release objectprint=on disassembler=on

Once everything is in place, you’re ready to see how your code is communicating with your CPU.

You can do this to get the assembly code

1
2
cd out/x64.release
./d8 --print-code ~/Downloads/add.js

This is what you’re likely going to see.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
--- Raw source ---
function add(a,b) {
  return a+b;
}


--- Code ---
source_position = 0
kind = FUNCTION
compiler = full-codegen
Instructions (size = 140)
0x27f3928043e0     0  55             push rbp
0x27f3928043e1     1  4889e5         REX.W movq rbp,rsp
0x27f3928043e4     4  56             push rsi
0x27f3928043e5     5  57             push rdi
0x27f3928043e6     6  488b4f2f       REX.W movq rcx,[rdi+0x2f]
0x27f3928043ea    10  488b490f       REX.W movq rcx,[rcx+0xf]
0x27f3928043ee    14  83411b01       addl [rcx+0x1b],0x1
0x27f3928043f2    18  49ba81bb8a39e52a0000 REX.W movq r10,0x2ae5398abb81    ;; object: 0x2ae5398abb81 <FixedArray[2]>
0x27f3928043fc    28  4152           push r10
0x27f3928043fe    30  6a00           push 0x0
0x27f392804400    32  488b45f0       REX.W movq rax,[rbp-0x10]
0x27f392804404    36  488b402f       REX.W movq rax,[rax+0x2f]
0x27f392804408    40  488b400f       REX.W movq rax,[rax+0xf]
0x27f39280440c    44  50             push rax
0x27f39280440d    45  b803000000     movl rax,0x3
0x27f392804412    50  48bb80753e1001000000 REX.W movq rbx,0x1103e7580
0x27f39280441c    60  e81fffefff     call 0x27f392704340     ;; code: STUB, CEntryStub, minor: 8
0x27f392804421    65  493ba5200c0000 REX.W cmpq rsp,[r13+0xc20]
0x27f392804428    72  7305           jnc 79  (0x27f39280442f)
0x27f39280442a    74  e811e6f4ff     call StackCheck  (0x27f392752a40)    ;; code: BUILTIN
0x27f39280442f    79  498b45a0       REX.W movq rax,[r13-0x60]
0x27f392804433    83  48bba9ba8a39e52a0000 REX.W movq rbx,0x2ae5398abaa9    ;; object: 0x2ae5398abaa9 Cell for 6144
0x27f39280443d    93  83430bd1       addl [rbx+0xb],0xd1
0x27f392804441    97  791f           jns 130  (0x27f392804462)
0x27f392804443    99  50             push rax
0x27f392804444   100  e877e5f4ff     call InterruptCheck  (0x27f3927529c0)    ;; code: BUILTIN
0x27f392804449   105  58             pop rax
0x27f39280444a   106  48bba9ba8a39e52a0000 REX.W movq rbx,0x2ae5398abaa9    ;; object: 0x2ae5398abaa9 Cell for 6144
0x27f392804454   116  49ba0000000000180000 REX.W movq r10,0x180000000000
0x27f39280445e   126  4c895307       REX.W movq [rbx+0x7],r10
0x27f392804462   130  c9             leavel
0x27f392804463   131  c20800         ret 0x8
0x27f392804466   134  6690           nop

Source positions:
 pc offset  position
         0         0
       130        35  statement

Deoptimization Output Data (deopt points = 0)

Back edges (size = 0)
ast_id  pc_offset  loop_depth

0x2ae5398abbb9: [TypeFeedbackInfo]
 - ic_total_count: 0, ic_with_type_info_count: 0, ic_generic_count: 0

RelocInfo (size = 6)
0x27f3928043f4  embedded object  (0x2ae5398abb81 <FixedArray[2]>)
0x27f39280441d  code target (STUB)  (0x27f392704340)
0x27f39280442b  code target (BUILTIN)  (0x27f392752a40)
0x27f392804435  embedded object  (0x2ae5398abaa9 Cell for 6144)
0x27f392804445  code target (BUILTIN)  (0x27f3927529c0)
0x27f39280444c  embedded object  (0x2ae5398abaa9 Cell for 6144)

--- End code ---

~~Now, in theory you can grab the hex code and run that in C and you should be able to get the same result. I haven’t tried it please let me know if it works or not.~~ It wouldn’t work because the generated code has fixed memory address from when the program was executed.

What I learn from this post is how is my JavaScript code executed in my computer and the next time I got asked, I will be able to answer that interview question. Sometimes, it’s nicer to be asked a question like this than how to revert a binary tree on a whiteboard. Don’t you think?

More info

  1. V8 Cheatsheet

  2. What does V8 do with that loop

  3. Comparing C to machine language (video)

  4. A closer look at crankshaft v8s optimizing compiler

Oct 4th, 2016

How to Change Your Habit One Task at a Time

Are you struggling to get anything done?

Now we have this amazing tool that could change your life… I present to you Habitica. If you click now you will get this tool for free. Does that sound like a Direct TV ad?.

I’d like to write down my experience of how I use Habitica to change my bad habit one task at a time. I was introduced to this tool when I was visiting my friend Scott Muc in Berlin. We were chatting about time management and productivity. He introduced me to Cofitivity as well, which is also another great tool to increase your productivity. I guess I don’t have to tell you about pomodoro. After 4 months later, I’ve changed some of my bad habits. One of which is making my bed. It might sounds easy but I make my own bed everyday and even while I’m travelling.

How?

Habitica is built around Gamification. If you don’t know what Gamification is, think about badges or number of likes or favourites. People love badges and people are crazy about likes. I was once crazy about checking in all the time to earn different badged on Foursquare or give a really detailed reviews just to earn reputation. It is fun and addicting.

Also if you play video game, you must remember countless of hours you spent on killing monsters to earn XP or rare items. That’s the core idea of Habitica. It keeps your motivating and you won’t get bored easily. I say easily because eventually you will find Habitica too easy. They have a reset button where you can reset your character class or if you’re too overwhelmed by all the habits and dailies.

Habitica combines the fun of RPG (Role Playing Games) and Gamification. Instead of fighting monsters, you’re fighting with your own habits. After you get something done, you earn XP and gold so you can level up your character or buy cool weapons to show off with your friends.

So how do I use Habitica.

Personally, I don’t use Habitica for any of my work tasks. I use Wunderlist instead. If you’re like me my work tasks tend to be really long and sometime I lose track of what needs to be done if I enter every task to Habitica. I use Habitica for anything that I want to make myself doing it or I want to change my bad habit. For example, I have a negative task every time I eat something unhealthy, like cookies or sweet. Every time I eat a cookie I have to click that - button and I’d lose my health. Or I would create a task to check my plane ticket for my next vacation.

Another example of how I changed my habit is making my bed. I created a task to make my bed every morning. It might sound too simple but it really did change my habit. Now I make my bed everyday without even knowing it. I wake up every morning, make my bed and click the checkbox. I earn XP and I feel good about it.

Another example would be that I could finish my Coursera course that I have always wanted to do for a long time. I used to sign up to all the classes on Coursera and I ended up not passing even the first week. Now I can force myself to finish the course week by week. If I don’t do it in time, my character dies, loses all the golds and one rare item.

Now if you have been playing for quite sometime, your tasks or habits can get really long which you have to scroll up and down. One thing I do is to group tasks together in checklist. For example, if I want to finish a book, I list out all the chapters then I check it off chapter by chapter. This helps you keep track of what else needs to be done.

You can also set the difficulty of the task. For example, making my bed is easy but learning a chapter on Coursera is hard. I would get more XP on my Coursera task.

Discipline is really important in Habitica. You can create as many tasks as you like and keep clicking it until you level up which no one will stop you. Eventually the game will be too easy and you will get bored and you won’t change anything. This also means that if you do negative tasks you have to click that - button. There’s no shame on binge eating on your cheat day. Habitica has reward system where you can create a reward for yourself which you have to use your golds.

Challenge accepted!

Habitica has a social aspect that can keep you motivated. You can form a party with your friend and fight the big boss or you can accept a challenge from the community to make your game harder and more engaging. For example, I recently signed up for a Spanish class and I joined the Spanish Duolingo challenge (Now I’m 50% done). Challenges have pre-populated tasks and dallies for you already. You just have to tick them off when you finished the task. If you’re discipline enough you might get diamonds from the owner of the challenge as a reward. This way, you will have other like-minded people to discuss or to encourage each other.

It’s open source

This is the best thing about Habitica. It’s open source. You can fork the repository on Github and create your own version or help the community to make the application better. It’s all open source including iOS and Android.

Let’s change your bad habit one task at a time! Come and say hi to me on Habitica or let me know how you use Habitica to change your habit.

All after I finished this post I get to tick it off my list!

Mar 2nd, 2016

Gatling Cluster

Performance matters

I think we can all agree that performance is one of the most important things in any application. That’s why we have performance or load testing. There’s a lot of tools out there we can choose from. But for this tutorial I pick Gatling.

Now it’s easy to say I want to generate 1,000,000 requests and hit the machine as hard as possible. In reality, your machine won’t be able to do that due to OS or Network Card limitations. The most common thing is ulimit

Gatling has a way to scale out the test scenario to different machines but there’s not enough documentation on the website.

Credit goes to nimrodtech for creating the script but I adapted a bit so if anybody wants to grab this please feel free.

My version assumes that you’re using EC2 instance and the directory structures are different between the host and local.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#Assuming same user name for all hosts
USER_NAME='ubuntu'

#Remote hosts list
HOSTS=( IP_ADDRESSES )
PEM_FILE=~/.ssh/your_pem.pem

#You should change all of this values to suit your structure
CURRENT_DIRECTORY=$(pwd)
GATLING_LOCAL_HOME=$CURRENT_DIRECTORY/performance/gatling
GATLING_REMOTE_HOME=/home/ubuntu/gatling

GATLING_LOCAL_SIMULATIONS_DIR=$GATLING_LOCAL_HOME/user-files/simulations/
GATLING_REMOTE_SIMULATIONS_DIR=$GATLING_REMOTE_HOME/user-files/simulations/

GATLING_LOCAL_RUNNER=$GATLING_LOCAL_HOME/bin/gatling.sh
GATLING_REMOTE_RUNNER=$GATLING_REMOTE_HOME/bin/gatling.sh

#Change to your simulation class name
SIMULATION_NAME='YOUR_SIMULATION'

#No need to change this
GATLING_LOCAL_REPORT_DIR=$GATLING_LOCAL_HOME/results/
GATLING_REMOTE_REPORT_DIR=$GATLING_REMOTE_HOME/results/

GATHER_REPORTS_DIR=~/Downloads/reports/

echo "Starting Gatling cluster run for simulation: $SIMULATION_NAME"

echo "Cleaning previous runs from localhost"
rm -rf $GATLING_LOCAL_REPORT_DIR
mkdir $GATLING_LOCAL_REPORT_DIR
rm -rf $GATLING_LOCAL_REPORT_DIR

rm -rf $GATHER_REPORTS_DIR
mkdir -p $GATHER_REPORTS_DIR

for HOST in "${HOSTS[@]}"
do
  echo "Cleaning previous runs from host: $HOST"
  ssh -i $PEM_FILE -n -f $USER_NAME@$HOST "sh -c 'rm -rf $GATLING_REMOTE_REPORT_DIR'"
done

for HOST in "${HOSTS[@]}"
do
  echo "Copying simulations to host: $HOST"
  scp -i $PEM_FILE -r $GATLING_LOCAL_SIMULATIONS_DIR/* $USER_NAME@$HOST:$GATLING_REMOTE_SIMULATIONS_DIR
done

for HOST in "${HOSTS[@]}"
do
  echo "Running simulation on host: $HOST"
  ssh -i $PEM_FILE -n -f $USER_NAME@$HOST "sh -c 'nohup $GATLING_REMOTE_RUNNER -nr -s $SIMULATION_NAME > $GATLING_REMOTE_HOME/run.log 2>&1 &'"
done

echo "Running simulation on localhost"
$GATLING_LOCAL_RUNNER -nr -s $SIMULATION_NAME

echo "Gathering result file from localhost"
ls -t $GATLING_LOCAL_REPORT_DIR | head -n 1 | xargs -I {} mv ${GATLING_LOCAL_REPORT_DIR}{} ${GATLING_LOCAL_REPORT_DIR}report
cp ${GATLING_LOCAL_REPORT_DIR}report/simulation.log $GATHER_REPORTS_DIR


for HOST in "${HOSTS[@]}"
do
  echo "Gathering result file from host: $HOST"
  ssh -i $PEM_FILE -n -f $USER_NAME@$HOST "sh -c 'ls -t $GATLING_REMOTE_REPORT_DIR | head -n 1 | xargs -I {} mv ${GATLING_REMOTE_REPORT_DIR}{} ${GATLING_REMOTE_REPORT_DIR}report'"
  scp -i $PEM_FILE $USER_NAME@$HOST:${GATLING_REMOTE_REPORT_DIR}report/simulation.log ${GATHER_REPORTS_DIR}simulation-$HOST.log
done

mv $GATHER_REPORTS_DIR $GATLING_LOCAL_REPORT_DIR
echo "Aggregating simulations"
$GATLING_LOCAL_RUNNER -ro reports

#using macOSX
open ${GATLING_LOCAL_REPORT_DIR}reports/index.html
Feb 17th, 2016

Round to the Left Most Digit

It’s probably unusual for me to write anything about Math. I hated math and I failed the subject all the time. But I got pretty excited when I knew this trick from my colleague. I also asked this question at stackoverflow.

The problem

Let’s say you have a number 423 and you want to round the number to the nearest left-most digit which in this case it’s 4. If you want to round to the left-most digit it’s going to be 400.

The solution

The solution is quiet simple. You just need to get the place value of the number, take the number in question divided by the place value and floor the number then multiply the result with the place value again. That’s it! Simple right?

So, the place value of 423 is 100.

\begin{align} \frac{423}{100} \end{align}

which you will get 4.23. The you floor the number

1
  Math.floor(4.23); // 4

And then you multiple 4 with 100 to get the rounded number.

\begin{align} {400}\cdot{100} = {400} \end{align}

The problem is how are we going to get the place value of the number?

You want logarithm.

The idea of this is to reverse the operation of exponentiation. For example, the log10 of 423 is 2.62634036738 then 10^2.62634036738 equals 423. But you want the place value. You would need to round the 2.62634036738 which is going to be 2 then 10^2 is 100. There! you get the place value of the 4.

\begin{align} d = \lfloor\frac{n}{10^{\lfloor\log_{10} n \rfloor}} \rfloor \cdot 10^{\lfloor\log_{10} n\rfloor} \end{align}

Show me the code

1
2
3
4
n = 423
d = Math.floor(Math.log10(n))

Math.floor(n / Math.pow(10, d)) * Math.pow(10, d) // 400
Jan 16th, 2016