Internet: the 8th continent
Monday, November 21, 2022
Sunday, August 9, 2015
Saturday, January 19, 2013
Raspberry Pi Performance
With Groovy inside RPI, it is hard to resist running some performance tests after talking to my students. I know it will be unfair to compare RPI with a typical PC which costs more than 10-20 times however it will be interesting to see how far behind the RPI will be.
For that, I use 2 scenarios to evaluate the performance. The first scenario writes 2000 (by default) integers into a file. The second scenario reads the saved integers from the file and append them to a buffer. These scenarios exercise I/O, loop and string accumulation to a buffer. Each scenario runs 10 times, discards the best and worst performance then compute the average.
Raspberry Pi model B specs:
CPU: ARM11 700Mhz
RAM: 512MB
OS: Linux
Disk: 8GB class 4
PC specs:
CPU: Intel Core i5 2.6GHz Dual Core with hyper-threading technology
RAM: 16 GB
OS: Windows 7
Disk: 320GB 5400 RPM
Groovy Script to evaluate the performance:
int maxFile = 10
RPI Results:
Write to file: 4368 ms
Write to file: 2063 ms
Write to file: 1938 ms
Write to file: 1969 ms
Write to file: 1938 ms
Write to file: 1950 ms
Write to file: 1941 ms
Write to file: 1918 ms
Write to file: 1927 ms
Write to file: 1917 ms
Write to file avg:1955.5 ms
Read from file: 309 ms, sb length:6890
Read from file: 120 ms, sb length:6890
Read from file: 52 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 39 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file avg:50.125 ms
PC Results:
Write to file: 1647 ms
Write to file: 1411 ms
Write to file: 1410 ms
Write to file: 1627 ms
Write to file: 1372 ms
Write to file: 1443 ms
Write to file: 1177 ms
Write to file: 2094 ms
Write to file: 1387 ms
Write to file: 1206 ms
Write to file avg:1437.875 ms
Read from file: 16 ms, sb length:6890
Read from file: 14 ms, sb length:6890
Read from file: 8 ms, sb length:6890
Read from file: 18 ms, sb length:6890
Read from file: 11 ms, sb length:6890
Read from file: 11 ms, sb length:6890
Read from file: 12 ms, sb length:6890
Read from file: 7 ms, sb length:6890
Read from file: 6 ms, sb length:6890
Read from file: 2 ms, sb length:6890
Read from file avg:10.625 ms
You may have noticed that the RPI has a slow start and consistent after few iterations while the PC results are varying. In one occurrence, the PC "write" scenario is higher than most of RPI results. On average, the PC "write" scenario is ONLY 1.36 times faster than the RPI. That is really impressive for the RPI. For the "read" scenario, the PC is 4.7 times faster. Finally, by adding the cost on the table, the Raspberry Pi offers a way better cost-performance ratio. By extrapolating these results, it is not a surprise to see new/old companies building computers with several low cost processors such as ARM.
For that, I use 2 scenarios to evaluate the performance. The first scenario writes 2000 (by default) integers into a file. The second scenario reads the saved integers from the file and append them to a buffer. These scenarios exercise I/O, loop and string accumulation to a buffer. Each scenario runs 10 times, discards the best and worst performance then compute the average.
Raspberry Pi model B specs:
CPU: ARM11 700Mhz
RAM: 512MB
OS: Linux
Disk: 8GB class 4
PC specs:
CPU: Intel Core i5 2.6GHz Dual Core with hyper-threading technology
RAM: 16 GB
OS: Windows 7
Disk: 320GB 5400 RPM
Groovy Script to evaluate the performance:
int maxFile = 10
int maxValue = args.length
? args[0].toLong() : 2000
long start
def l = []
// write to file
maxFile.times {
File
f = new File("perf${it}.txt")
start
= System.currentTimeMillis()
maxValue.times
{
f
<< "${it}\n"
}
l
<< System.currentTimeMillis() - start
println
"Write
to file: ${l[it]} ms"
}
println "Write to file avg:${(l.sum() - l.max() - l.min())/(maxFile - 2)} ms"
// read from file
l = []
StringBuilder sb
maxFile.times {
sb
= new StringBuilder(10000)
File
f = new File("perf${it}.txt")
start
= System.currentTimeMillis()
f.eachLine
{
sb.append
it
}
l
<< System.currentTimeMillis() - start
println
"Read
from file: ${l[it]} ms, sb length:${sb.size()}"
}
println "Read from file avg:${(l.sum() - l.max() - l.min())/(maxFile - 2)} ms"
// delete file
maxFile.times {
File
f = new File("perf${it}.txt")
f.delete()
}
RPI Results:
Write to file: 4368 ms
Write to file: 2063 ms
Write to file: 1938 ms
Write to file: 1969 ms
Write to file: 1938 ms
Write to file: 1950 ms
Write to file: 1941 ms
Write to file: 1918 ms
Write to file: 1927 ms
Write to file: 1917 ms
Write to file avg:1955.5 ms
Read from file: 309 ms, sb length:6890
Read from file: 120 ms, sb length:6890
Read from file: 52 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 39 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file: 38 ms, sb length:6890
Read from file avg:50.125 ms
PC Results:
Write to file: 1647 ms
Write to file: 1411 ms
Write to file: 1410 ms
Write to file: 1627 ms
Write to file: 1372 ms
Write to file: 1443 ms
Write to file: 1177 ms
Write to file: 2094 ms
Write to file: 1387 ms
Write to file: 1206 ms
Write to file avg:1437.875 ms
Read from file: 16 ms, sb length:6890
Read from file: 14 ms, sb length:6890
Read from file: 8 ms, sb length:6890
Read from file: 18 ms, sb length:6890
Read from file: 11 ms, sb length:6890
Read from file: 11 ms, sb length:6890
Read from file: 12 ms, sb length:6890
Read from file: 7 ms, sb length:6890
Read from file: 6 ms, sb length:6890
Read from file: 2 ms, sb length:6890
Read from file avg:10.625 ms
You may have noticed that the RPI has a slow start and consistent after few iterations while the PC results are varying. In one occurrence, the PC "write" scenario is higher than most of RPI results. On average, the PC "write" scenario is ONLY 1.36 times faster than the RPI. That is really impressive for the RPI. For the "read" scenario, the PC is 4.7 times faster. Finally, by adding the cost on the table, the Raspberry Pi offers a way better cost-performance ratio. By extrapolating these results, it is not a surprise to see new/old companies building computers with several low cost processors such as ARM.
Sunday, January 13, 2013
Groove your Raspberry Pi
After playing with the GPIO by using Python as a programming language with my nephews, I was tempted to augment the Raspberry Pi (RPI) with Groovy programming language. Just image what you can do with a small machine and a modern programming language. To do that, you need to install Java and Groovy. Here I provide straightforward instructions to quickly groove your RPI.
Get a new 4GB+ SD card and flash the "Soft-float Debian, wheezy" image. The image is available at http://www.raspberrypi.org/downloads
Since you need more space to install Java and Groovy, you need to resize a partition or create a new partition. Here I provide instructions to resize the root file system for simplification. To resize the root file system, use raspi-config tool and select expand_rootfs; it will use all available space for that partition. Then reboot your RPI.
After run df -h to verify if the root file system has been resized.
Get Java 7 soft floating-point for embedded Linux (ARMv6/7 Linux - Headless EABI, VFP, SoftFP ABI, Little Endian) http://www.oracle.com/technetwork/java/embedded/downloads/javase/index.html
Create a java directory where you will unpack Java:
mkdir /home/pi/java
cd /home/pi/java
tar -zxvf ejre-7u10-fcs-b18-linux-arm-vfp-client_headless-28_nov_2012.tar.gz
Verify that java is properly installed by doing
./ejre1.7.0_10/bin/java -version
Get Groovy at http://groovy.codehaus.org/Download, here I use version 1.8.8 but you can use the latest.
Create a groovy directory where you will unpack Groovy:
mkdir /home/pi/groovy
cd /home/pi/groovy
unzip groovy-binary-1.8.8.zip
Set Java and Groovy home environment variables add their bin directory to the PATH environment variable.
export JAVA_HOME=/home/pi/java/ejre1.7.0_10
export GROOVY_HOME=/home/pi/groovy/groovy-1.8.8
export PATH=$PATH:$JAVA_HOME/bin:$GROOVY_HOME/bin
Verify Groovy installation by doing
groovy -v
groovy -e "println 'Hello World'"
Voilà you have grooved your Rapsberry Pi!
Get a new 4GB+ SD card and flash the "Soft-float Debian, wheezy" image. The image is available at http://www.raspberrypi.org/downloads
Since you need more space to install Java and Groovy, you need to resize a partition or create a new partition. Here I provide instructions to resize the root file system for simplification. To resize the root file system, use raspi-config tool and select expand_rootfs; it will use all available space for that partition. Then reboot your RPI.
After run df -h to verify if the root file system has been resized.
Get Java 7 soft floating-point for embedded Linux (ARMv6/7 Linux - Headless EABI, VFP, SoftFP ABI, Little Endian) http://www.oracle.com/technetwork/java/embedded/downloads/javase/index.html
Create a java directory where you will unpack Java:
mkdir /home/pi/java
cd /home/pi/java
tar -zxvf ejre-7u10-fcs-b18-linux-arm-vfp-client_headless-28_nov_2012.tar.gz
Verify that java is properly installed by doing
./ejre1.7.0_10/bin/java -version
Get Groovy at http://groovy.codehaus.org/Download, here I use version 1.8.8 but you can use the latest.
Create a groovy directory where you will unpack Groovy:
mkdir /home/pi/groovy
cd /home/pi/groovy
unzip groovy-binary-1.8.8.zip
Set Java and Groovy home environment variables add their bin directory to the PATH environment variable.
export JAVA_HOME=/home/pi/java/ejre1.7.0_10
export GROOVY_HOME=/home/pi/groovy/groovy-1.8.8
export PATH=$PATH:$JAVA_HOME/bin:$GROOVY_HOME/bin
Verify Groovy installation by doing
groovy -v
groovy -e "println 'Hello World'"
Voilà you have grooved your Rapsberry Pi!
Saturday, April 7, 2012
Not so final!
Last time I was reviewing a code and found out something interesting regarding the Java finally-clause. Suppose we have the code below which adds strings to a StringBuilder and returns this object.
public StringBuilder finallyReturnString() {
StringBuilder s = new StringBuilder();
s.append("init");
try {
s.append("-try");
return s;
} finally {
s.append("-finally");
}
}
It will return a StringBuilder containing “init-try-finally”. However, let’s dissemble the code above.
0: new #23; //class java/lang/StringBuilder
3: dup
4: invokespecial //StringBuilder()
7: astore_1
8: aload_1
9: ldc #80; //String init
11: invokevirtual //StringBuilder.append()
14: pop
15: aload_1
16: ldc #82; //String -try
18: invokevirtual #36; //StringBuilder.append()
21: pop
22: aload_1
23: astore_3
24: aload_1
25: ldc #84; //String -finally
27: invokevirtual //StringBuilder.append()
30: pop
31: aload_3
32: areturn
33: astore_2
34: aload_1
35: ldc #84; //String -finally
37: invokevirtual //StringBuilder.append()
40: pop
41: aload_2
42: athrow
Here the try-clause is represented by the lines 15-23 and 31-32 and the finally-clause between the lines 24-30. The "finally" string is appended to the variable 1 or 3 and then “init-try-finally” contained in variable 3 is returned. You may have noticed that the finally-clause is repeated at lines 35-40.
Now let's take a similar example. Here we will not append string but set a new String each time. This will return "try" and not "finally".
public StringBuilder finallyReturnString() {
StringBuilder s = new StringBuilder("init");
try {
s = new StringBuilder("try");
return s;
} finally {
s = new StringBuilder("finally");
}
}
The disassembled code looks like:
0: new #23; //class java/lang/StringBuilder
3: dup
4: ldc #79; //String init
6: invokespecial //StringBuilder(String)
9: astore_1
10: new #23; //class java/lang/StringBuilder
13: dup
14: ldc #65; //String try
16: invokespecial //StringBuilder(String)
19: astore_1
20: aload_1
21: astore_3
22: new #23; //class java/lang/StringBuilder
25: dup
26: ldc #73; //String finally
28: invokespecial //StringBuilder(String)
31: astore_1
32: aload_3
33: areturn
34: astore_2
35: new #23; //class java/lang/StringBuilder
38: dup
39: ldc #73; //String finally
41: invokespecial //StringBuilder(String)
44: astore_1
45: aload_2
46: athrow
Here the the try-clause is represented by the lines 10-21 and 32-33, and the finally-clause by the lines 22-31. "init" and "try" strings are stored in variables 1 and 3. "finally" string is stored in variable 1 but variable 3 which contains "try" is returned.
This time, we will make things more clear in case you did not catch the twist; we will use String (immutable class) as a return type. The finallyReturnString() will also return "try".
public String finallyReturnString() {
String s = "init";
try {
s = "try";
return s;
} finally {
s = "finally";
}
}
The disassembled code looks like:
0: ldc #75; //String init
2: astore_1
3: ldc #61; //String try
5: astore_1
6: aload_1
7: astore_3
8: ldc #69; //String finally
10: astore_1
11: aload_3
12: areturn
13: astore_2
14: ldc #69; //String finally
16: astore_1
17: aload_2
18: athrow
The try-clause is represented by lines 3-7 and 11-12, and the finally-clause by the lines 8-10. Same as previous example, "init" and "try" string are stored in variables 1 and 3. "finally" string is stored in variable 1 but variable 3 which contains "try" is returned.
Next time when you have a return statement in your try-clause combined with finally-clause which affects variables, watch-out! May be you need to refactor your code!
public StringBuilder finallyReturnString() {
StringBuilder s = new StringBuilder();
s.append("init");
try {
s.append("-try");
return s;
} finally {
s.append("-finally");
}
}
It will return a StringBuilder containing “init-try-finally”. However, let’s dissemble the code above.
0: new #23; //class java/lang/StringBuilder
3: dup
4: invokespecial //StringBuilder()
7: astore_1
8: aload_1
9: ldc #80; //String init
11: invokevirtual //StringBuilder.append()
14: pop
15: aload_1
16: ldc #82; //String -try
18: invokevirtual #36; //StringBuilder.append()
21: pop
22: aload_1
23: astore_3
24: aload_1
25: ldc #84; //String -finally
27: invokevirtual //StringBuilder.append()
30: pop
31: aload_3
32: areturn
33: astore_2
34: aload_1
35: ldc #84; //String -finally
37: invokevirtual //StringBuilder.append()
40: pop
41: aload_2
42: athrow
Here the try-clause is represented by the lines 15-23 and 31-32 and the finally-clause between the lines 24-30. The "finally" string is appended to the variable 1 or 3 and then “init-try-finally” contained in variable 3 is returned. You may have noticed that the finally-clause is repeated at lines 35-40.
Now let's take a similar example. Here we will not append string but set a new String each time. This will return "try" and not "finally".
public StringBuilder finallyReturnString() {
StringBuilder s = new StringBuilder("init");
try {
s = new StringBuilder("try");
return s;
} finally {
s = new StringBuilder("finally");
}
}
The disassembled code looks like:
0: new #23; //class java/lang/StringBuilder
3: dup
4: ldc #79; //String init
6: invokespecial //StringBuilder(String)
9: astore_1
10: new #23; //class java/lang/StringBuilder
13: dup
14: ldc #65; //String try
16: invokespecial //StringBuilder(String)
19: astore_1
20: aload_1
21: astore_3
22: new #23; //class java/lang/StringBuilder
25: dup
26: ldc #73; //String finally
28: invokespecial //StringBuilder(String)
31: astore_1
32: aload_3
33: areturn
34: astore_2
35: new #23; //class java/lang/StringBuilder
38: dup
39: ldc #73; //String finally
41: invokespecial //StringBuilder(String)
44: astore_1
45: aload_2
46: athrow
Here the the try-clause is represented by the lines 10-21 and 32-33, and the finally-clause by the lines 22-31. "init" and "try" strings are stored in variables 1 and 3. "finally" string is stored in variable 1 but variable 3 which contains "try" is returned.
This time, we will make things more clear in case you did not catch the twist; we will use String (immutable class) as a return type. The finallyReturnString() will also return "try".
public String finallyReturnString() {
String s = "init";
try {
s = "try";
return s;
} finally {
s = "finally";
}
}
The disassembled code looks like:
0: ldc #75; //String init
2: astore_1
3: ldc #61; //String try
5: astore_1
6: aload_1
7: astore_3
8: ldc #69; //String finally
10: astore_1
11: aload_3
12: areturn
13: astore_2
14: ldc #69; //String finally
16: astore_1
17: aload_2
18: athrow
The try-clause is represented by lines 3-7 and 11-12, and the finally-clause by the lines 8-10. Same as previous example, "init" and "try" string are stored in variables 1 and 3. "finally" string is stored in variable 1 but variable 3 which contains "try" is returned.
Next time when you have a return statement in your try-clause combined with finally-clause which affects variables, watch-out! May be you need to refactor your code!
Saturday, February 26, 2011
The Trio: DCNM, .Net, and Powershell
Few decades ago MS-DOS CLI was the only shell available on PC. Many of my friends do not want to hear about DOS shell even though they daily use Windows OS in their corporate environment. People trying to escape Microsoft, jump into flashy Apple world and quickly are obliged to use VMware fusion to get a piece of Windows OS to run non-converted Windows applications; what do you want Microsoft is dominant :)
It is true that DOS shell is limited for scripting and people use alternatives such as Perl, Python, Ruby, Groovy, Cygwin, etc. in Windows environment. But with Powershell, Microsoft is trying to catch up by providing a decent scripting language to administrators. With Powershell it is possible to instantiate .Net classes and access Windows OS API; that is indeed powerful for Windows environment. By adding DC network API to the mixture you get the perfect trio for your data center. Indeed, you get an OO (Object-Oriented) scripting environment where you can monitor the status and health of network resources (devices and servers), automate network and server tasks, and get events/alerts to conditions that impact network resources. These OO scripts can be seamlessly plugged into your existing environment to manage your DC network infrastructure. See the video and screen-shots below.
For the video use 720p HD and full-screen to see the shell detail.
Screen-shots
Wednesday, January 19, 2011
DC Network API
With the proliferation of mobile devices, social networks, virtualization, cloud computing, video contents, and personal computers to perform daily activities, the electronic services over the intranet and internet have tremendously increased in the last decade. This phenomenon has significantly boosted demand in the DC (Data Center) for more storage, computation power, and bandwidth. As a result in the DC, the number of network devices and computers have increased, and its management and monitoring become more and more complex and costly. While changing and growing, DC must be agile and automated to add latest network technologies without disturbing existing infrastructure or increasing downtime otherwise company might lose revenue, credibility and business. Today, network API springs up in few companies to assist IT in their quest to reduce network operation complexity and expense. In this area, Cisco Systems offers a DC network API worthy to discuss. This API is part of DCNM (Data Center Network Manager) product and allows to automate, manage and monitor the network portion of the Data Center. In DCNM, functional management areas (configuration, provisioning, inventory, monitor, fault and troubleshooting) are in a single product and works in unison, consequently its interfaces are not disparate increasing operational efficiencies. The DC network API can be an ingredient of your DC automation; it can be used as an Adapter to complement your existing management infrastructure and provides a unified and coherent views of your DC network. It may save you time and money, and on top of that the good news it is freely available. To read more about this article see:
http://sites.google.com/site/aznichet/dc-network-api
http://sites.google.com/site/aznichet/dc-network-api
Subscribe to:
Posts (Atom)