人人网-英特尔技术专题讨论会实录

Intel/Qianxiang server workshop
(这横幅很搞 叫Qianxiang不如叫RenRen,千橡的英文:Oak Pacific)
intel技术专家
互联网大客户技术技术服务内容
1.idc机房相关
2.性能优化:调试、锁等基础知识

下面由请intel技术专家:一个阿姨先讲话,可能是,无自我介绍
数据中心专家:张静、oracle专家津鹏、泰勒、优化组的徐进
(以上纯音译)

泰勒说话
性能技术分享 cpu 至强服务器优化产品

数据中心 Optimized Datacenters

技术专家津鹏开始说话
国内普通机房2.2kw-3kw每机柜
放视频:英特尔原料的一个生产厂 现在是一个数据中心 一个三层的楼 (真TM大) 视频里一个老外一层一层地介绍 每机柜30kw(国内的十倍)(听不懂老外在介绍啥,没有字幕,一帮人在看纯视频)

视频放完

在研究散热与机柜

张静开始
PPT
数据中心未来的发展和案例分析
从九六年到零九年的服务器成本的柱状图。power & cooling的费用在增长。
数据中心:可靠性、可扩容性、管理
神奇了(第一个大哥讲了半天,第二个大哥上来说PPT是他准备的。。。)

津鹏大哥来说话了
数据分散
数据中心要求越高、成本越高、建的时间就越长。
运营数据中心与灾备数据中心。

张静大哥又回来了
数据中心的需求与建设的花费的策略:考虑未来几年的增长
空调的增加更加容易:逐渐投入
超级用户:类似腾讯,模块化的数据中心建设.集装箱数据中心。快速实施。
如何在数据中心里节能:PUE Data Center Power Usage Effectiveness
SPUE
TPUE = PUE+SPUE
目前通常在3.2
一个数据中心基本上只有三分之一是用来计算的。
1.使用更高效率的电源。80PLUS 铜 银 金
2.(UPS有三次电源转换:整流器 逆变器 变压器)英特尔在佬实验中取消了UPS (高压直流供电)
3.气流与温度
冷气流不够 上半部分服务器过热
风量过大 风速过大 冷空气短路(只有一半的温度降了),下面的解决办法:
1.封闭冷通道改变冷气流风向 可节能36% 温差变大后更能节能50%
2.烟窗式机柜

水冷

打了下瞌睡
现在是津鹏大哥在讲集装箱机房
案例:一家佬上市的国内顶级的互联网公司 我猜是百度
评估一个数据中心的好与坏

最后又是一个视频:的集装箱数据中心 有个的兄弟穿个MAIL的Tshirt很cool

津鹏这哥们播视频用的QQ影音

===
徐进大哥上台,这兄弟来过一回,讲CPU ASE全球对云计算/互联网数据中心的支持
这兄弟讲课老是晃
解决性能缺陷:概念和方法及策略
一个表,按获益排序:1.系统级(网络磁盘内存)  2.应用级(进程堆数据结构)  3.微架构级(微架构级优化指令集) 越前面的策略获益越高 难度越低

intel tools&libraries;
线程级并行:Thread Building Block Open Standards OpenMP
数据并行:Ct,C/C++ Stds

2008年的硬件概述
理论计算能力:102.4G指令/秒
实际只是三分之一到二分之一,经常是四分之一或者五分之一
2009年的硬件概述
理论计算能力:不变
内存带宽提高了3倍:6通道DDR3:64G/s
硬盘系统 SSD RAID5*6: IOPS:100,000(上百倍提升) SSD写性能远差于自己的读性能1:100 但也比传统的高
SSD随机读性能非常好 随机写一般

BIOS设置:-SMT/EIST/NUMA/Prefetcher
NUMA:不跨CPU访问内存 尽量不调度原来的CPU上的指令

SSD VS HD
一般情况下,索引文件都比较大。
在更新索引文件的过程中,磁盘压力较大,SSD能获得较好性能。

应用级的性能缺陷
多核环境下,多线程程序的设计需要非常细致的设计
-锁的粒度
-并发
-软件流水线的设计
-选择合适的线程库(TBB)

锁的粒度
一个例子,对应用程序内部的缓存加锁造成的线程冲突,将缓存拆分成多个部分,分别加以保护,大大缓解了冲突,应用程序性能提高了21%

典型的应用性能缺陷
滥用STL:滥用可能会造成非常密集的内存管理作;多线程环境下会更坏
Glibc的malloc/free在多核环境下扩展性很差、如果在多线程环境下需要频繁分配和释放内存,可以考虑SmartHeap(收费的)\hoard\intel TBB
内存作:memcpy memset是耗时的,特别是在Xeon E5400平台上,每秒memcpy/memset 2GB将会对整个系统的性能造成极大的影响。
Bitmap:随机写位图的某些图,如果造成了缓存缺失每次访问都能造成上百个CPU cycle(一个小循环里写10W到20W次,读没有关系)

算法的选择 JPEG缩略图生成
通过在频率域减采样可以将原图非常快的缩小到1/(2的N次方)大小,然后再缩小到合适的大小,与直接缩小相比,性能提高了2.5倍(校内相册吕威大侠曾经说过,我记得是2.8倍)
加密算法AES VS TEA
AES比TEA要快3倍以上
搜索引擎中,为了减少磁盘访问,通常倒排表被压缩后存放,SSE4.2优化后的PForDelta算法可以达到3GB/s的解压速度,是VBYTE速度的10倍,而压缩率更好。

采取正确的IO API
SSD的IO延迟很小,并且能同时处理几十个IO请求,单线程上的同步IO不能最大化发SSD的性能。
要SSD发挥到最大,要使用许多个线程去同步作SSD。
BufferIO会造成内核的内存拷贝,如果需要每秒处理上GB的磁盘读作,则需要考虑是否需要采用Direct-IO mmap等无需拷贝的方式。
当文件大于系统内存的情况下,通过mmap的方式随机的访问会造成频繁缺页。

采用高性能库函数
intel ipp库:JPEG resize IPP是libjpeg的2部
Westmere上新的AES指令可以提供10倍于普通AES的性能,IPP将会在第一时间提供支持。

例子:用SSE4.2优化P_FOR_dELTA解压缩 很复杂 看不懂

===
四个内部案例
分享时间:小白 铁安 军辉

passport优化 小白

以前的情况
read->mysql->loginCache->write
Ice.Server.ThreadPool
第三个阶段非常慢,用户登录不上。

现在
read
Ice.Server.ThreadPool
mysql->loginCache->write
另一个pool

延长二十分钟在线,从产品上解决问题。

新鲜事重构 铁安
文件存储
索引存储4-5W写入每秒
每秒中用户产生的feed有500条左右,这500条需要发给特定的一群人,平均分给一百人,每秒大概5W

SearchCache  全站用户数据全缓存服务 长青
以struct形式存储用户,一个亿的用户会占65.2G内存,不包括内存碎片等实际开销。
去掉struct的内存结构化开销,通过序列化反序列化来压缩内存占用。
内存优化比例大概在40-70%之间。

锁的效率 军辉
原子作效率最好
自旋锁的效率还不错
hash函数:boobs(memcache里的) 性能和均匀程度最好的是murmur stdhash是最不好的
其他经验:
一个锁有严重的效率问题
锁的数目在并发线程数的10部时最好
pthread spinlock有效率问题 争用发生时延迟达5-10ms
spinlock的cpu消耗比mutex低
实现lockfree需要抛弃一些特性

专家说明:spinlock使用时可能会cpu特高,用的时候小心。

Ubuntu 9.10快速安装nginx+php环境手记[54chen科学院]

我(54chen)因为场景需要,特地在ubuntu9.10中安装nginx+php的环境,要快速不要优化,记录如下:

sudo apt-get install php5 php5-cgi php5-cli php5-gd php5-curl php5-mysql nginx

sudo apt-get install lighttpd

spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -u www-data -g www-data -f /usr/bin/php-cgi 上面的作解读:

1.安装php nginx

2.安装lighttpd,为啥要安装这个,因为他有个spawn-fcgi,因为apt下来的php不是php-fpm。

3.用spawn-fcgi启动php-cgi在9000端口监听。

sudo vim /etc/php5/cgi/php.ini

修改php.ini文件

cgi.fix_pathinfo=1; 这样php-cgi方能正常使用SCRIPT_FILENAME这个变量 sudo vim /etc/nginx/sites-enabled/www.54chen.com

server {
listen 80; //端口
server_name wiki.54chen.com; //虚拟域名
access_log /var/log/nginx/hwiki.54chen.com.access.log; //访问日志
location / {
root /home/wiki.54chen.com; //size根目录
index index.php;
} location ~ \.php$ { #php fastcgi的配置
fastcgi_pass 127.0.0.1:9000; #php fastcgi的代理端口与ip
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/wiki.54chen.com$fastcgi_script_name; #要处理的php文件的路径
include /etc/nginx/fastcgi_params; #fastcgi的参数文件地址
} }
好,上面的作就建立了一个虚拟主机,保存好。

sudo killall apache2

杀掉apache,启动nginx.

sudo /etc/init.d/nginx start

大功告成!整个过程不超过十五分钟。呼呼~~

圣诞快乐!!!

艾睿网 CMAX(RIA)技术峰会归来 演稿分享

感谢junidea、kenshin等牛人的组织和邀请,为这次技术峰会的成功举办感到由衷的高兴,这一群新兴的群体,在一线的朋友们,到场的牛人还有《Flex 3 RIA开发详解与精深实践》作者杨占坡、杨铭、《银光开发者工作室》的魏永超、还有出版社和媒体的各位朋友,大家都为各自领域的见解进行了深刻的探讨,在会上我作了《HTTP:RIA REST CLOUD》的分享,同时借此结交了不少各行业兴趣相投的好朋友。

以下是活动海报,还有上海和广州的会场,那边关心RIA的朋友可以关注一下时间:

http://www.airia.cn/cmax2009/welcome.html

我分享的主题的演示稿在下面(请使用firefox打开):

http://www.54chen.com/ria/200912.xul

稍候应该还有图片和视频资料送出。

人人网招聘JAVA、AS、C++工程师(科学院特供,两月内有效)

科学院年底发布人人网职位推荐消息:

人人网Flash (AS3)程序员 1.计算机、软件类相关专业本科以上学历
2.AS2\Flex\AS3一年以上开发经验 人人网JAVA架构师 1.计算机及相关专业本科以上学历
2.三年以上Java开发经验 人人网产品经理 1.本科以上学历
2.两年以上互联网工作经验 游戏制作人(游戏中心) 1.本科以上学历
2.两年以上主策划工作经验
3.两个以上完整上线项目经验者优先

C++工程师(分win下和linux下的)

1.win:C++基础扎实,有客户端界面和控件开发经验

2.linux:两年以上开发经验

以上为科学院精简人力废话版本招聘条件,如果任何一条不满足请不要把简历投到cc0cc@126.com,也不要纯洁地问工资情况,人力告诉你的要准确得多,另这些都是中高级职位,有意者牛X者尽管过来,有酒肉。

PHP JAVA C上传文件如何准确判断文件类型-mime知识普及

MIME的英文全称是"Multipurpose Internet Mail Extensions" 多功能Internet 邮件扩充服务,它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。服务器会将它们发送的多媒体数据的类型告诉 浏览器,而通知手段就是说明该多媒体数据的MIME类型,从而让浏览器知道接收到的信息哪些是MP3文件,哪些是Shockwave文件等等。服务器将 MIME标志符放入传送的数据中来告诉浏览器使用哪种插件读取相关文件。

文件 用IE7上传 用Firefox3.0上传
GIF

image/gif

image/gif

JPG

image/pjpeg

image/jpeg

ZIP application/x-compressed application/octet-stream
JSP

text/html

text/html

EXE application/octet-stream application/octet-stream
上边的图哦不红图表示出了不同的浏览器所上传的不同的mime的区别,研究了一下,暂时没有发现可修改假冒mime的方法。

<form enctype="multipart/form-data" action="URL" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="1000"> <input name="myFile" type="file"> <input type="submit" value="上传文件"> </form>

这个代码上传文件后:

使用PHP:

$_FILES['myFile']['type']   文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。

使用struts2限制类型:

<interceptor-ref name="fileUpload">
<param name="allowedTypes">application/zip,application/x-zip-compressed,application/rar,application/octet-stream</param>
<param name="maximumSize">3145728</param>
</interceptor-ref>

使用C/java(由人人网文斌大侠提供):

public static boolean isImageJpeg(byte[] blob) {

       if (blob != null && blob.length > 2) {

           // 0xFFD8

           if (blob[0] == (byte)0xFF &&

              blob[1] == (byte)0xD8) {

              return true;

           }

       }

       return false;

    }

    public static boolean isImageBmp(byte[] blob) {

       if (blob != null && blob.length > 2) {

           // BM: Windows 3.1x, 95, NT, …

           // BA: OS/2 Bitmap Array

           // CI: OS/2 Color Icon

           // CP: OS/2 Color Pointer

           // IC: OS/2 Icon

           // PT: OS/2 Pointer

           if ((blob[0] == 'B' &&

               blob[1] == 'M')

               ||

              (blob[0] == 'B' &&

               blob[1] == 'A')) {

              return true;

           }

       }

       return false;

    }

    public static boolean isImagePng(byte[] blob) {

       if (blob != null && blob.length > 8) {

           // 89 50 4E 47 0D 0A 1A 0A

           if (blob[0] == (byte)0x89 &&

              blob[1] == (byte)0x50 &&

              blob[2] == (byte)0x4E &&

              blob[3] == (byte)0x47    &&

              blob[4] == (byte)0x0D &&

              blob[5] == (byte)0x0A &&

              blob[6] == (byte)0x1A &&

              blob[7] == (byte)0x0A)

              return true;

       }

       return false;

    }

    public static boolean isImageGif(byte[] blob) {

       if (blob != null && blob.length > 3) { // 只有3字节的gif?这里仅避免异常

           if (blob[0] == 'G' &&

              blob[1] == 'I' &&

              blob[2] == 'F')

              return true;

       }

       return false;

    }

Java List转byte[]的方法

先做一个试验:

Test.java

package test;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Integer> lst = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
lst.add(i);
} System.out.print(lst.toString());
} } 得到结果:列出了所有的数字

[0, 1, 2, 3, 4, 5, 6。。。
进一步进行改进:
package test;

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
List<BlockData> lst = new ArrayList<BlockData>();
for (int i = 0; i < 100; i++) {

lst.add(new BlockData(i,i));
} System.out.print(lst.toString());
} /**
* 定义一个乱七八糟的class
* @author cc
* */
public static class BlockData {
public int version;
public int count;
public List<String> list;

public BlockData(int version, int count) {
this.version = version;
this.count = count;
this.list = new ArrayList<String>(count);
}

public BlockData(int version, int count, List<String> list) {
this.version = version;
this.count = count;
this.list = list;
} }
} 运行后的结果:

[test.Test$BlockData@1bc4459, test.Test$BlockData@12b6651, ...
从后面一个例子看到的object在toString的时候,对象只是一个串了,要想再恢复成object不可能了。54chen曾想把list.toString.getBytes,被证明是不靠谱的做法。

而要想把一个list变成byte[]在网络上传输,看下面的代码:

public void encode(OutputStream os) throws IOException {
List<NuclearStorageValue> list = data.list;

if (list != null && list.size() > 0) {

for (NuclearStorageValue value : list) {
// 依次写入每条数据的长度和数据内容
byte[] bytes = value.toByteArray();

os.write(int2bytes(bytes.length));
os.write(bytes);
} }
}

public byte[] int2bytes(int val) {
byte[] b = new byte[4];
b[0] = (byte) (val >> 24);
b[1] = (byte) ((val << 8) >> 24);
b[2] = (byte) ((val << 16) >> 24);
b[3] = (byte) ((val << 24) >> 24);
return b;
}