测试配置数据占用的内存大小

游戏中一直不是很清楚配置数据占用了多少内存,现在是使用json转c#对象,转化使用时间也不清楚。

scriptableobject和json相比也不知道谁的性能更优。

现在使用的是dictionary来存储的数据,和hashtable相比谁更快,不知道。现在使用的key是string,使用int是否更快。

以上都需要测试结果:

1、先测试占用的内存。

打一个空场景。

占用的内存如图:

  • total 44.6
  • unity 13.8
  • mono 0.7
  • gfxdriver 17.0
  • fmod 252
  • profiler 12.2
  • assets 19.7
  • other 9.8
  • builtin resources 243.6
  • not saved 26.7
  • scene memory 8.7

原来的工程场景和资源太多了,打包一次太费时间,这里重新建一个工程

内存占用如图:

  • total 18.6
  • unity 2.7
  • mono 0.5
  • gfxdriver 3.3
  • fmod 310k
  • profiler 12.1
  • assets 1.5
  • other 2.1
  • builtin resources 231.1k
  • not saved 145.6k
  • scene memory 15.5k

log_config配置文件大小1M,json未压缩。使用resource.load导入内存增加:1.1M和原文件基本相同。多次使用Resources.load只会增加一份内存。(在assets中显示为text asset)

感觉消耗的内存由other移至assets中。再测试一次,unity死掉了。再重启测试一次,果真如此,other中asset0的东西没有了,assets中多了一个textasset名为log_config。

TextAsset text=Resources.Load(“log_config”) as TextAsset;
TextAsset text2 = Resources.Load(“log_config”) as TextAsset;

连续两行,内存也没有多少变化,TextAsset可能都是引用。果真只是引用。

神奇了。使用Resources.unload后,TextAsset log_config被释放内存。但是other中没有增加内存!!!

我把json中的字符串放入textbox中,内存消耗变的巨大:

主要是other中的managedHeap.usedSize变为了71M,在simple界面中可以看到mono也同步变为了71M。

测试结果,使用Resources.load 加载后,然后使用unload释放掉对象内存,但是好像该对象还可以继续使用 -.-!!。难道是因为内存区还保留着数据导致的?unloadAssets,如果被引用对象再次被使用,会从被加载的地方重新被加载。所以,一个对象完全不被使用后,再unloadAssets。

在这里,我们的配置文件被转化为了c#对象,所以可以直接unload掉,释放内存。

minijson中有个东西占用了内存,转换申请了6M内存,一直没有被释放。如果再转换一个小json比如“{}”就会将内存释放掉。

使用json进行转换,中间产生了8M内存占用,既使将引用对象设置为null,不调用GC.collection()也不会回收内存。

text asset转为json消耗2秒,json存入dictionary消耗1.5秒。

开始测试scriptableobject。

没有测试protobuf,scriptableobject比未压缩json容量仅为20%,加载时间仅为10%,内存消耗仅为20%。完全可以替代json。

另外,字符串可以考虑7z压缩,这样可以使用更小的内存,仅多消耗一点CPU。

 

 

unity3d 动态给按钮添加事件

UIEventListener.Get(bt1).onClick = click;

bt1 是按钮的gameobject

 

游戏登陆场景掉祯排查

我们游戏中场景经常出现掉祯的现象。

fps会突然从30降至15。

原来一直没有找到原因,最近学习unity,使用profiler看运行时的情况,看到我的手机上,掉祯出现时,cpu usage会突然飙升,同时gpu usage会也同步飙升。

cpu上升显示是camera.render使用率大量增加。

gpu上升定位至是RenderForwardOpaque.Render占用时间大量增加导致的。

 

 

 

 

unity3d 中捕获所有的异常

void Start () {
// System.AppDomain.CurrentDomain.UnhandledException +=new System.UnhandledExceptionEventHandler(  _erroHandler);
//Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new System.UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// Application.Run(new Game());
Application.RegisterLogCallback(_erroHandler);
Application.RegisterLogCallbackThreaded(_erroHandler);
}

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
}

private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
Debug.Log(“Application_threadException”);
}

void _erroHandler(string name,string stack,LogType type)
{
}

svn服务器安装

mkdir -p /archive/download
mkdir -p /opt/compile

yum install apr apr-devel apr-util apr-util-devel gcc openssl openssl-devel


cd /opt/compile
tar xvfz /archive/download/httpd-2.2.21.tar.gz
cd httpd-2.2.21
LDFLAGS=”-L/lib64 -L/usr/lib64″ ./configure –prefix=/opt/apache2 –with-mpm=worker –enable-static-support –enable-module=rewrite -enable-dav -enable-so
#-enable-maintainer-mode
make
make install
cp /opt/apache2/bin/apachectl /sbin


tar xvfz /archive/download/subversion-1.7.9.tar.gz
cd subversion-1.7.9
yum install unzip
./get-deps.sh
./configure –prefix=/opt/subversion –with-apxs=/opt/apache2/bin/apxs –with-ssl –with-zlib=/usr/local/zlib
make
make install


vi httpd.conf
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
<Location /svn>
DAV svn
SVNParentPath /opt/svnroot/repository
AuthzSVNAccessFile /opt/svnroot/repository/authgroup
AuthType Basic
AuthName “Subversion Repository”
AuthUserFile /opt/svnroot/repository/authpass
Require valid-user
</Location>

mkdir -p /opt/svnroot/repository

svnserve -d -r /opt/svnroot

创建密钥文件、初始帐号
htpasswd  -c /opt/svnroot/repository/authpass yan
New password:

新增帐号
htpasswd  -b /opt/svnroot/repository/authpass newuser newpasswd

设置权限
vi /opt/svnroot/repository/authgroup
[groups]
admin=yan
test=tan

[/]
@admin = rw

[test:/]
@test = rw

—-

创建新的 project newApp
svnadmin create /opt/svnroot/repository/newApp


客户端
svn checkout http://192.168.1.x/svn/newApp

进入 newApp 目录,新建目录:
trunk
branches
tags
svn add/commit 准备好基础结构。

重新checkout
svn checkout http://192.168.1.x/svn/newApp/trunk
即可进入正常开发,以后根据需要为trunk目录增加branch、tag。

 

注:如果遇到以下问题

/usr/local/lib/libsvn_subr-1.so.0: undefined symbol: apr_hash_clear

这是因为httpd和subversion编译使用的apr和apr-util使用的库不相同造成的。

可以在编译httpd时指定–with-par 和 –withd-par-util参数来指定使用subversion相同的apr和apr-util来编译httpd.

LDFLAGS=”-L/lib64 -L/usr/lib64″ ./configure –prefix=/opt/apache2 –with-mpm=worker –enable-static-support –enable-module=rewrite -enable-dav -enable-so –with-apr=/opt/compile/subversion-1.7.9/apr –with-apr-util=/opt/compile/subversion-1.7.9/apr-util

在网上找到一个阿里云建VPN的一键脚本

#!/bin/bash

function installVPN(){
	echo "begin to install VPN services";
	#check wether vps suppot ppp and tun
	
	yum remove -y pptpd ppp
	iptables --flush POSTROUTING --table nat
	iptables --flush FORWARD
	rm -rf /etc/pptpd.conf
	rm -rf /etc/ppp
	
	arch=`uname -m`
	
	wget http://www.hi-vps.com/downloads/dkms-2.0.17.5-1.noarch.rpm
	wget http://wty.name/linux/sources/kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm
	wget http://www.hi-vps.com/downloads/kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm
	wget http://www.hi-vps.com/downloads/pptpd-1.3.4-2.el6.$arch.rpm
	wget http://www.hi-vps.com/downloads/ppp-2.4.5-17.0.rhel6.$arch.rpm


	yum -y install make libpcap iptables gcc-c++ logrotate tar cpio perl pam tcp_wrappers
	rpm -ivh dkms-2.0.17.5-1.noarch.rpm
	rpm -ivh kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm
	rpm -qa kernel_ppp_mppe
	rpm -Uvh ppp-2.4.5-17.0.rhel6.$arch.rpm	
	rpm -ivh pptpd-1.3.4-2.el6.$arch.rpm

	mknod /dev/ppp c 108 0 
	echo 1 > /proc/sys/net/ipv4/ip_forward 
	echo "mknod /dev/ppp c 108 0" >> /etc/rc.local
	echo "echo 1 > /proc/sys/net/ipv4/ip_forward" >> /etc/rc.local
	echo "localip 172.16.36.1" >> /etc/pptpd.conf
	echo "remoteip 172.16.36.2-254" >> /etc/pptpd.conf
	echo "ms-dns 8.8.8.8" >> /etc/ppp/options.pptpd
	echo "ms-dns 8.8.4.4" >> /etc/ppp/options.pptpd

	pass=`openssl rand 6 -base64`
	if [ "$1" != "" ]
	then pass=$1
	fi

	echo "vpn pptpd ${pass} *" >> /etc/ppp/chap-secrets

	iptables -t nat -A POSTROUTING -s 172.16.36.0/24 -j SNAT --to-source `ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk 'NR==1 { print $1}'`
	iptables -A FORWARD -p tcp --syn -s 172.16.36.0/24 -j TCPMSS --set-mss 1356
	service iptables save

	chkconfig iptables on
	chkconfig pptpd on

	service iptables start
	service pptpd start

	echo "VPN service is installed, your VPN username is vpn, VPN password is ${pass}"
	
}

function repaireVPN(){
	echo "begin to repaire VPN";
	mknod /dev/ppp c 108 0
	service iptables restart
	service pptpd start
}

function addVPNuser(){
	echo "input user name:"
	read username
	echo "input password:"
	read userpassword
	echo "${username} pptpd ${userpassword} *" >> /etc/ppp/chap-secrets
	service iptables restart
	service pptpd start
}

echo "which do you want to?input the number."
echo "1. install VPN service"
echo "2. repaire VPN service"
echo "3. add VPN user"
read num

case "$num" in
[1] ) (installVPN);;
[2] ) (repaireVPN);;
[3] ) (addVPNuser);;
*) echo "nothing,exit";;
esac

注:这个脚本最后一步进行iptables转发时,会指向为阿里云的内网地址,需要手工操作一下,修改为公网IP。

nginx 日志切割

#!/bin/bash
## 零点执行该脚本
## Nginx 日志文件所在的目录
LOGS_PATH=/usr/local/nginx/logs
## 获取昨天的 yyyy-MM-dd
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
## 移动文件
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log

tar cvfz ${LOGS_PATH}/access_${YESTERDAY}.log.tar.gz ${LOGS_PATH}/access_${YESTERDAY}.log

## 向 Nginx 主进程发送 USR1 信号。USR1 信号是重新打开日志文件
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)

日志按大小进行分割

#!/bin/bash
## 按文件大小切割日志文件
## 注:实际测试中发现,对log文件进行切割后,rsyslogd短时间内会继续往mv后的文件写日志

## 文件日志所在的目录
LOG_PATH=/opt/logs/router-log

## 日志文件超过多少字节后,进行切割,最多进行100份切割,超过后,按时间为后缀
## 100M : 104857600
## 500M : 524288000
## 1G   : 1073741824

LOG_MAX_SIZE=5240

currentDate1=`date "+%Y%m%d_%H%M"`
currentLogDate=`date "+%Y-%m-%d"`

echo "start log_rotate.sh $currentDate1"
echo "LOG_PATH:$LOG_PATH"
echo "LOG_MAX_SIZE:$LOG_MAX_SIZE"

sendHUP=0

for name in $LOG_PATH/*
do
        if [ -f "$name" ]; then
                if [ "${name##*.}" == "log" ]; then
                        filesize=$(stat -c '%s' $name)
                        if [[ $filesize -ge $LOG_MAX_SIZE ]]; then
                        rotating=0

                        for((i=1;i<=100;i++))
                        do
                                if [ ! -f "$name.$i" ]; then
                                        echo "mv $name $name.$i"
                                        mv $name $name.$i
                                        rotating=1
                                        sendHUP=1
                                        break
                                fi


                        done

                        if [ $rotating -eq 0 ]; then
                                currentDate=`date "+%Y%m%d_%H%M"`
                                mv $name $name.$currentDate
                                sendHUP=1
                        fi
                        fi
                fi

        fi

        if [ -d "$name" ]; then

                if [ -d "$name/$currentLogDate" ]; then

                        for name2 in $name/$currentLogDate/*
                        do
                                if [ -f "$name2" ]; then
                                        if [ "${name2##*.}" == "log" ]; then
                                        filesize=$(stat -c '%s' $name2)
                                        if [[ $filesize -ge $LOG_MAX_SIZE ]]; then
                                                rotating=0

                                                for((i=1;i<=100;i++))
                                                do
                                                        if [ ! -f "$name2.$i" ]; then
                                                                echo "mv $name2 $name2.$i"
                                                                mv $name2 $name2.$i
                                                                rotating=1
                                                                sendHUP=1
                                                                break
                                                        fi


                                                done

                                                if [ $rotating -eq 0 ]; then
                                                        currentDate=`date "+%Y%m%d_%H%M"`
                                                        mv $name2 $name2.$currentDate
                                                        sendHUP=1
                                                fi
                                        fi
                                        fi
                                fi
                        done
                fi

        fi
done

if [ $sendHUP -eq 1 ]; then
        echo "send HUP to rsyslogd.pid:$(cat /var/run/syslogd.pid)"
        kill -HUP $(cat /var/run/syslogd.pid)
else
        echo "not send HUP"
fi

svn批量添加文件

svn批量添加文件:

svn st | awk '{if($1 == "?"){print $2}}'|xargs svn add

好吧,一个makefile的初学者学习skynet中

1、第一步就是项目的组织方式。skynet经常要更新,所以要尽量避免在自己项目共用同一个git。从群中和云风的文章中了解到,使用submodule引用skynet是一种比较理想的方式。我一个makefile基本为0的人要理解submodule的编写很不容易,而且也不知道过程对不对,但现在至少已经可以初步达到目标了。

# hello game
#

.PHONY : all clean skynet

CC ?= gcc
PLAT ?=linux

LUA_CLIB_PATH=/opt/git/hellogame/luaclib
CSERVICE_PATH=/opt/git/hellogame/cservice

SKYNET_BUILD_PATH ?=/opt/git/hellogame

all : skynet

skynet :
        cd module_skynet && $(MAKE) CC=$(CC) SKYNET_BUILD_PATH=$(SKYNET_BUILD_PATH) LUA_CLIB_PATH=$(LUA_CLIB_PATH) CSERVICE_PATH=$(CSERVICE_PATH) linux

clean :
        cd module_skynet && $(MAKE) CC=$(CC) SKYNET_BUILD_PATH=$(SKYNET_BUILD_PATH) LUA_CLIB_PATH=$(LUA_CLIB_PATH) CSERVICE_PATH=$(CSERVICE_PATH) clean

写的很差,先用着吧。module_skynet是引用的skynet

2、复制module_skynet/example/config到本地目录。

然后修改config中的lua地址:

root = "./"
thread = 8
logger = nil
harbor = 1
address = "127.0.0.1:2526"
master = "127.0.0.1:2013"
start = "main"  -- main script
bootstrap = "snlua bootstrap"   -- The service for bootstrap
standalone = "0.0.0.0:2013"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;".."module_skynet/service/?.lua;"..root.."module_skynet/test/?.lua;"..root.."module_skynet/examples/?.lua"
lualoader = "lualib/loader.lua"
-- preload = "./examples/preload.lua"   -- run preload.lua before every lua service run
snax = root.."examples/?.lua;"..root.."test/?.lua"
cpath = root.."cservice/?.so"
-- daemon = "./skynet.pid"

只修改其中 luaservice的地址。

3、启动 ./skynet config,提示找不到lualib/loader.lua,又建立了一个软连接指向module_skynet/lualib,可以顺利解决问题。

4、以上方式不保证是最合适的,但至少可以进行开发了。