第一组测试计算
max是:4234567890
max*max nonprint是把 printf("%ld\n", res); 去掉的意思
代码结构大概是这样的:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main(int argc, char** argv)
{
int op = atoi(argv[1]);
long max = atol(argv[2]);
struct timeval t1, t2;
gettimeofday(&t1, NULL);
long res = 0;
for (long i=0; i<max; i++)
{
if (op == 1)
{
res = max*max;
}
else
{
res = max+max;
}
}
gettimeofday(&t2, NULL);
printf("%ld\n", res);
printf("escape %d\n",(t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000);
gettimeofday(&t1, NULL);
res = 0;
for (long i=0; i<max; i++)
{
if (op == 1)
{
res = i*i;
}
else
{
res = i+i;
}
}
gettimeofday(&t2, NULL);
printf("%ld\n", res);
printf("escape %d\n",(t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000);
return 0;
}
测试结果:
np代表没有把结果print出来。这时优化后的CPP代码发现后面没有使用,有可能会把忽略。
结论:
1. 加法比乘法消耗时间多。
2. 另外java的代码也是加了优化的,比如使用寄存器等,所以会比晚去没有优化的CPP代码块。
3. 加了优化,后面没有引用结果的话,直接会忽略掉计算,消耗时间都是0.
4. 深度优化时,即使打印,对非一直变化的变量乘法计算也会被优化掉。(O9时只有一种情况下会发生计算。。。)
第二组测试:
遍历1.2G内存四次,计算数字和; memcpy4次。因为java有int32数组限制,另外,Heap内存最大限制也只有4G。
java -Xmx3800m calcmem 1 1234567890
代码逻辑如下:
public class calcmem {
public static void main(String[] args)
{
int op = Integer.parseInt(args[0]);
long max = Long.parseLong(args[1]);
byte[] pmem = new byte[(int) max];
byte[] pmem2 = new byte[(int) max];
for (int i=0; i<max; i++)
{
pmem[i] = (byte)i;
}
long t1 = System.currentTimeMillis();
long res = 0;
for(int j=0; j<4;j++){
for (int i=0; i<max; i++)
{
res += pmem[i];
}
}
long t2 = System.currentTimeMillis();
System.out.println(res);
System.out.println(String.format("escape %1$d", t2-t1));
t1 = System.currentTimeMillis();
System.arraycopy(pmem, 0, pmem2, 0, (int) max);
System.arraycopy(pmem, 4, pmem2, 10, (int) max-10);
System.arraycopy(pmem, 6, pmem2, 1000, (int) max-1000);
System.arraycopy(pmem, 7, pmem2, 300, (int) max-300);
t2 = System.currentTimeMillis();
System.out.println(String.format("escape %1$d", t2-t1));
}
}
结论:
结果显示内存拷贝都差不多时间。
计算非优化的CPP会比较慢。
其它问题:cpp中malloc后还没开始用时,内存是在虚拟内存上的。
3.测试网络和协议解析(更复杂的计算)
前面在VM上的一个测试
http://blog.csdn.net/anghlq/article/details/7103700
处理能力
C++ | JAVA | |
100个连接 | 3.6~5W /s | 2.4~2.5 W/s |
10个连接 | 3.1~4.8W/s | 2 W/S |
100个连接echo 1K数据性能 | 2.4 W/s | 1 W/s |
整个过程中,JAVA的框架 0.7W/s以上,数值继续往上冲击就速度很慢了,大概原因是CPU已经撑不住了。
而C++框架都是迅速冲击上2W的。
目前框架的瓶颈在CPU上, 框架进程的CPU占用率都是100%的.
结论
同等CPU能力下,C++框架效率是JAVA的1.5倍以上。
4. MD5计算
测试方法:一个77MB的文件,计算MD5 10次。
cpp的O0和O9都差不多2140ms(这是因为md5的库是已经经过优化的)
file size: 80105025
escape 2088
2b64557303b83f0835199f08df22f64f
java的是4824ms
结论:CPP比JAVA快超过1倍
代码分别如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
public class calctest {
public static void main(String[] args) throws NoSuchAlgorithmException
{
int loop = Integer.parseInt(args[1]);
File file = new File(args[0]);
Long filelength = file.length();
byte[] filecontent = new byte[filelength.intValue()];
try {
FileInputStream in = new FileInputStream(file);
in.read(filecontent);
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte tmp[] = null;
long t1 = System.currentTimeMillis();
for (int i=0; i<loop; i++)
{
md.update(filecontent);
tmp = md.digest();// MD5 的计算结果是一个 128 位的长整数,
}
long t2 = System.currentTimeMillis();
System.out.println(String.format("escape %1$d", t2-t1));
StringBuilder sb = new StringBuilder();
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
char str[] = new char[16 * 2];
int k = 0;
for (int i = 0; i < 16; i++) {
byte byte0 = tmp[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];// 取字节中高 4 位的数字转换,// >>>
// 为逻辑右移,将符号位一起右移
str[k++] = hexDigits[byte0 & 0xf];// 取字节中低 4 位的数字转换
}
System.out.println( new String(str));
}
}
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/md5.h>
#include <sys/time.h>
unsigned char result[MD5_DIGEST_LENGTH];
// Print the MD5 sum as hex-digits.
void print_md5_sum(unsigned char* md) {
int i;
for(i=0; i <MD5_DIGEST_LENGTH; i++) {
printf("%02x",md[i]);
}
}
// Get the size of the file by its file descriptor
unsigned long get_size_by_fd(int fd) {
struct stat statbuf;
if(fstat(fd, &statbuf) < 0) exit(-1);
return statbuf.st_size;
}
int main(int argc, char *argv[]) {
unsigned long file_size;
printf("using file:\t%s\n", argv[1]);
int loop=atoi(argv[2]);
int fd = open(argv[1], O_RDONLY);
file_size = get_size_by_fd(fd);
printf("file size:\t%lu\n", file_size);
char* buf = (char*)malloc(file_size);
size_t len = 0;
size_t pos = 0;
while ( len = read (fd,buf+pos, file_size ) >0)
{
pos+= len;
}
printf("start calc\n");
struct timeval t1, t2;
gettimeofday(&t1, NULL);
for (int i=0; i<loop; i++)
{
MD5((unsigned char*) buf, file_size, result);
}
gettimeofday(&t2, NULL);
printf("escape %d\n",(t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000);
print_md5_sum(result);
printf(" %s\n", argv[1]);
return 0;
}
g++ -O9 -lssl md5.cc -o md5o9
第五组测试:
累计计算,相对第一组无法优化到0
逻辑大概如下:
int main(int argc, char** argv)
{
int op = atoi(argv[1]);
long max = atol(argv[2]);
struct timeval t1, t2;
gettimeofday(&t1, NULL);
long res = 1;
for (long i=1; i<max; i++)
{
res += i;
}
gettimeofday(&t2, NULL);
printf("%ld\n", res);
printf("escape %d\n",(t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000);
gettimeofday(&t1, NULL);
res = 1;
for (long i=1; i<max; i++)
{
res = res * i;
}
gettimeofday(&t2, NULL);
printf("%ld\n", res);
printf("escape %d\n",(t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000);
return 0;
}
结论:
除了O0CPP的外,其它的计算效率差别不大。
总结: 两者的native操作性能差不多。
但是
1. CPP的编译器级别优化远强于JAVA。
2. 语言本身的设计CPP对底层点的操作需求要强于JAVA。
A. 栈的支持,如果涉及到栈操作性能会明显强于JAVA
B. 原生指针的支持, 传递效率高
C. 不损性能的各种灵活byte转long等强制转换(基于指针)
D. 内存操作更加灵活,比如共享内存直接可以挂上数组和结构体指针等就可以用了
E. F. G. ....
3. 网络性能CPP远强于JAVA(这跟他更底层有关)
并不是纯黑啊。。。笔者本身弄过多种开发,C#,JAVA,RUBY,HTML,JS,OBJ-C,python,C,CPP等等,其实是很客观的罗列,开发应用时,绝对是哪种框架支持好,速度快,社区活跃,或者直接有开源成熟方案就用哪种,但是作为高频调用,涉及到海量问题时就要在核心或者底层需要更多的微秒级别的优化了。