当前位置:  编程技术>移动开发
本页文章导读:
    ▪erlang 内存储器被大量占用,跟踪过程        erlang 内存被大量占用,跟踪过程 第一步:查看进程数目是否正常? erlang:system_info(process_count).   第二步:查看节点的内存消耗在什么地方?> erlang:memory(). [{total,2099813400}, {processes,1985444264}, {proce.........
    ▪ wp7 开发学习之 ListBox 小施用二        wp7 开发学习之 ListBox 小应用二 xaml页面 <ListBox Name="noteListBox" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"> <ListBox.I.........
    ▪ wp7 开发学习之 ProgressBar 小运用       wp7 开发学习之 ProgressBar 小应用 xaml页面 <ProgressBar Height="48" HorizontalAlignment="Left" Margin="101,97,0,0" Name="progressBar1" Verti.........

[1]erlang 内存储器被大量占用,跟踪过程
    来源: 互联网  发布时间: 2014-02-18
erlang 内存被大量占用,跟踪过程

第一步:
查看进程数目是否正常? erlang:system_info(process_count).

 

第二步:
查看节点的内存消耗在什么地方?
> erlang:memory().
[{total,2099813400},
 {processes,1985444264},
 {processes_used,1985276128},
 {system,114369136},
 {atom,4479545},
 {atom_used,4477777},
 {binary,22756952},
 {code,10486554},
 {ets,47948808}]
显示内存大部分消耗在进程上,由此确定是进程占用了大量内存

 

第三步:
查看哪些进程占用内存最高?
> spawn(fun() -> etop:start([{output, text}, {interval, 1}, {lines, 20}, {sort, memory}]) end).
(以输出text方式启动etop,其间隔为1秒,输出行数为20行,按照内存排序. 这里spawn一个新进程,目的是输出etop数据时不影响erlang shell 输入.)

 

第四步:
查看占用内存最高的进程状态
> erlang:process_info(pid(0,12571,0)).          
[{current_function,{mod_player,send_msg,2}},
 {initial_call,{erlang,apply,2}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[<0.12570.0>]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.46.0>},
 {total_heap_size,12538050},
 {heap_size,12538050},
 {stack_size,10122096},
 {reductions,3795950},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
 {suspending,[]}]

其中” {total_heap_size,12538050},” 表示占用内存为 12358050 words(32位系统word size为4,64位系统word size为8, 可以通过erlang:system_info(wordsize) 查看),在64位系统下将近100M, 太夸张了!

 

第五步:
手动gc回收,希望问题可以解决
>  erlang:garbage_collect(pid(0,12571,0)).
true
再次查看进程内存,发现没有任何变化!gc没有回收到任何资源,因此消耗的内存还在发挥作用,没有回收!

 

 

第六步:
不要怀疑系统,首先要怀疑自己的代码
认真观察代码,其大致结构如下:
send_msg(Socket, Pid) ->
   try
        receive
            {send, Bin} ->
                ...
            {inet_reply, _Sock, Result} ->
               ...
   catch
       _:_ ->
           send_msg(Sock, Pid)
   end.
其目的是循环等待数据,然后进行发送,其使用了try...catch捕获异常.
这段代码有问题么?
对,这段代码的确有问题, 其不是尾递归! try...catch会在stack中保存相应的信息,异常捕获需要放置在函数内部,所以send_msg最后调用的是try...catch,而不是自身,所以不是尾递归!
可以通过代码得到验证:
 cat test.erl
-module(test).
-compile([export_all]).


t1() ->
   Pid = spawn(fun() -> do_t1() end),
   send_msg(Pid, 100000).

t2() ->
   Pid = spawn(fun() -> do_t2() end),
   send_msg(Pid, 100000).

send_msg(_Pid, 0) ->
   ok;
send_msg(Pid, N) ->
   Pid ! <<2:(N)>>,
   timer:sleep(200),
   send_msg(Pid, N-1).

do_t1() ->
   erlang:garbage_collect(self()),
   Result = erlang:process_info(self(), [memory, garbage_collection]),
   io:format("~w ~n", [Result]),
   io:format("backtrace:~w~n~n", [erlang:process_display(self(), backtrace)]),
   try
     receive
         _ ->
             do_t1()
     end
   catch
     _:_ ->
         do_t1()
   end.

do_t2() ->
   erlang:garbage_collect(self()),
   Result = erlang:process_info(self(), [memory, garbage_collection]),
   io:format("~w ~n", [Result]),
   io:format("backtrace:~w~n~n", [erlang:process_display(self(), backtrace)]),
   receive
     _ ->
         do_t2()
   end.

版本1:erlc test.erl && erl -eval "test:t1()"
版本2:erlc test.erl && erl -eval "test:t2()"
你会看到版本1代码的调用堆栈在不断增长,内存也在增长, 而版本2函数调用地址保持不变,内存也没有发生变化!

总结:
1,服务器编程中,循环一定确保为尾递归
2,善于使用OTP,如果使用gen_server替换手写loop,就不会出现这个问题!

 

本文属转载


    
[2] wp7 开发学习之 ListBox 小施用二
    来源: 互联网  发布时间: 2014-02-18
wp7 开发学习之 ListBox 小应用二

xaml页面

<ListBox Name="noteListBox"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<HyperlinkButton Name="noteLocation"
HorizontalContentAlignment="Stretch"
FontSize="42"
VerticalContentAlignment="Stretch"
Content="{Binding noteLocation}"
Click="Mylik_click"
Tag="{Binding filename}"/>
<TextBlock Name="noteCreatetime"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="10"
Text="{Binding noteCreatetime}"
/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

cs页面


//点击日记进行导航
private void Mylik_click(object sender, RoutedEventArgs e)
{
HyperlinkButton likbtn = (HyperlinkButton)sender;
string filename = likbtn.Tag.ToString();
string url = String.Format("/MyNote;component/ViewEdit.xaml?id={0}", filename);
NavigationService.Navigate(new Uri(url, UriKind.Relative));
}

这里主要是想说下点击的时候区别哪个点的


    
[3] wp7 开发学习之 ProgressBar 小运用
    来源: 互联网  发布时间: 2014-02-18
wp7 开发学习之 ProgressBar 小应用

xaml页面

<ProgressBar Height="48"

HorizontalAlignment="Left"
Margin="101,97,0,0"
Name="progressBar1"
VerticalAlignment="Top"
Width="250"
Background="Red"/>
<ProgressBar Height="4"
HorizontalAlignment="Left"
Margin="169,377,0,0"
Name="progressBar2"
VerticalAlignment="Top"
Width="460"
IsIndeterminate="True"/>

这里有两个进度条,第一个在cs设置了委托事件(可以算百分比,边进度边显示),第二个设置了IsIndeterminate="True" 循环进度显示

cs页面

public partial class ProgressBar : PhoneApplicationPage
{
int count = 0;
public ProgressBar()
{
InitializeComponent();
}

//进度的改变事件
private void progressBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
//获取进度的值 然后进行给title赋值显示
this.PageTitle.Text = e.NewValue.ToString();
}

void dt_Tick(object sender, EventArgs e)
{
//tick一次加一
count++;
//把值赋给进度条
progressBar1.Value = count;
//然后委托进度条的值的改变事件
progressBar1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(progressBar1_ValueChanged);

}

//加载
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
//创建一个时间
DispatcherTimer dt = new DispatcherTimer();
//设置时间间隔100秒
dt.Interval = TimeSpan.FromMilliseconds(100);
//委托事件tick的委托事件
dt.Tick += new EventHandler(dt_Tick);
//启动
dt.Start();


}
}


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之手游转电视游戏的模拟操控 iis7站长之家
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3