首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MATLAB执行时间增加

MATLAB执行时间增加
EN

Stack Overflow用户
提问于 2014-08-07 20:55:44
回答 1查看 149关注 0票数 1

这是我的密码。我的意图是将Wireshark捕获保存到一个特别格式化的文本文件中。MATLAB代码应该对数据包进行遍历,对不同的协议进行分解,然后根据这些协议生成表。我现在已经为以太网/IP/UDP/MODBUS编写了这个程序。在这种情况下,每次遇到新的寄存器值时,它都会在MBTable中创建一个列,而且每次遇到对该寄存器值的更改时,它都会更新该表行中的值。MBTable的第一列是time,寄存器以第二列开始。

MBTable预先分配给超过100,000行(nol非常大),在执行此代码之前有10列。我从表中提取的文件中的实际数据大约有10,000行和4列,代码执行非常慢,所以必须停止它。tic/toc值每1000行计算一次,每次迭代后继续以指数方式增加。这是一个很大的循环,但我看不出有什么东西在以这样的方式增长,以致于每一次迭代都会使它运行得更慢。

所有变量都被初始化到顶部(为了减少代码数量而忽略了)。变量eth、eth.ip、eth.ip.udp和eth.ip.udp.modbus都是结构化的,eth.header和eth.ip.header也是如此。WSID是来自早些时候打开的.txt文件的文件ID。

代码语言:javascript
复制
MBTable = zeros(nol,10);
tval = tic;
while not(feof(WSID))
    packline = packline + 1;
    fl = fl + 1;

    %Get the next line from the file
    MBLine = fgetl(WSID);
    %Make sure line is not blank or short
    if length(MBLine) >= 3
        %Split the line into 1. Line no, 2. Data, 3. ASCII
        %MBAll = strsplit(MBLine,' ');
        %First line of new packet, if headers included
        if strcmp(MBLine(1:3),'No.')
            newpack = true;
            newtime = false;
            newdata = false;
            stoppack = false;
            packline = 1;
        end
        %If packet has headers, 2nd line contains timestamp
        if newpack
            Ordered = false;
            if packline == 2;
                newtime = true;
                %MBstrs = strsplit(MBAll{2},' ');
                packno = int32(str2double(MBLine(1:8)));
                t = str2double(MBLine(9:20));

                et = t - lastt;
                if lastt > 0 && et > 0
                    L = L + 1;
                    MBTable(L,1) = t;
                end
                %newpack = false;
            end
            if packline > 3              
                    dataline = int16(str2double(MBLine(1:4)));
                    packdata = strcat(packdata,MBLine(7:53));
            end
        end

    else
        %if t >= st

        if packline > 3
            stoppack = true;
            newpack = false;
        end
        if stoppack
            invalid = false;
            %eth = struct;

            eth.pack = packdata(~isspace(packdata));
            eth.length = length(eth.pack);

            %Dissect the packet data
            eth.stbyte = 1;
            eth.ebyte = eth.length;
            eth.header.stbyte = 1;
            eth.header.ebyte = 28;
            %Ethernet Packet Data
            eth.header.pack = eth.pack(eth.stbyte:eth.stbyte+27);
            eth.header.dest = eth.header.pack(eth.header.stbyte:eth.header.stbyte + 11);
            eth.header.src = eth.header.pack(eth.header.stbyte + 12:eth.header.stbyte + 23);
            eth.typecode = eth.header.pack(eth.header.stbyte + 24:eth.header.ebyte);

            if strcmp(eth.typecode,'0800')

                eth.type = 'IP';
                %eth.ip = struct;
                %IP Packet Data
                eth.ip.stbyte = eth.header.ebyte + 1;
                eth.ip.ver = eth.pack(eth.ip.stbyte);
                %IP Header length
                eth.ip.header.length = 4*int8(str2double(eth.pack(eth.ip.stbyte+1)));
                eth.ip.header.ebyte = eth.ip.stbyte + eth.ip.header.length - 1;
                %Differentiated Services Field
                eth.ip.DSF = eth.pack(eth.ip.stbyte + 2:eth.ip.stbyte + 3);
                %Total IP Packet Length
                eth.ip.length = hex2dec(eth.pack(eth.ip.stbyte+4:eth.ip.stbyte+7));
                eth.ip.ebyte = eth.ip.stbyte + max(eth.ip.length,46) - 1;
                eth.ip.pack = eth.pack(eth.ip.stbyte:eth.ip.ebyte);
                eth.ip.ID = eth.pack(eth.ip.stbyte+8:eth.ip.stbyte+11);
                eth.ip.flags = eth.pack(eth.ip.stbyte+12:eth.ip.stbyte+13);
                eth.ip.fragoff = eth.pack(eth.ip.stbyte+14:eth.ip.stbyte+15);
                %Time to Live
                eth.ip.ttl = hex2dec(eth.pack(eth.ip.stbyte+16:eth.ip.stbyte+17));
                eth.ip.typecode = eth.pack(eth.ip.stbyte+18:eth.ip.stbyte+19);
                eth.ip.checksum = eth.pack(eth.ip.stbyte+20:eth.ip.stbyte+23);

                %eth.ip.src = eth.pack(eth.ip.stbyte+24:eth.ip.stbyte+31);

                eth.ip.src = ...
                    [num2str(hex2dec(eth.pack(eth.ip.stbyte+24:eth.ip.stbyte+25))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+26:eth.ip.stbyte+27))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+28:eth.ip.stbyte+29))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+30:eth.ip.stbyte+31)))];

                eth.ip.dest = ...
                    [num2str(hex2dec(eth.pack(eth.ip.stbyte+32:eth.ip.stbyte+33))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+34:eth.ip.stbyte+35))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+36:eth.ip.stbyte+37))),'.', ...
                    num2str(hex2dec(eth.pack(eth.ip.stbyte+38:eth.ip.stbyte+39)))];

                if strcmp(eth.ip.typecode,'11')
                    eth.ip.type = 'UDP';

                    eth.ip.udp.stbyte = eth.ip.stbyte + 40;
                    eth.ip.udp.src = hex2dec(eth.pack(eth.ip.udp.stbyte:eth.ip.udp.stbyte + 3));
                    eth.ip.udp.dest = hex2dec(eth.pack(eth.ip.udp.stbyte+4:eth.ip.udp.stbyte+7));
                    eth.ip.udp.length = hex2dec(eth.pack(eth.ip.udp.stbyte+8:eth.ip.udp.stbyte+11));
                    eth.ip.udp.checksum = eth.pack(eth.ip.udp.stbyte+12:eth.ip.udp.stbyte+15);
                    eth.ip.udp.protoID = eth.pack(eth.ip.udp.stbyte+20:eth.ip.udp.stbyte+23);

                    if strcmp(eth.ip.udp.protoID,'0000')
                       eth.ip.udp.proto = 'MODBUS';

                       %eth.ip.udp.modbus = struct;
                       eth.ip.udp.modbus.stbyte = eth.ip.udp.stbyte+16;
                       eth.ip.udp.modbus.transID = eth.pack(eth.ip.udp.modbus.stbyte:eth.ip.udp.modbus.stbyte+3);
                       eth.ip.udp.modbus.protoID = eth.ip.udp.protoID;
                       eth.ip.udp.modbus.length = int16(str2double(eth.pack(eth.ip.udp.modbus.stbyte + 8:eth.ip.udp.modbus.stbyte + 11)));
                       eth.ip.udp.modbus.UID = eth.pack(eth.ip.udp.modbus.stbyte + 12:eth.ip.udp.modbus.stbyte + 13);
                       eth.ip.udp.modbus.func = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte + 14:eth.ip.udp.modbus.stbyte+15));
                       eth.ip.udp.modbus.register = eth.pack(eth.ip.udp.modbus.stbyte + 16: eth.ip.udp.modbus.stbyte+19);
                       %Number of words to a register, or the number of registers
                       eth.ip.udp.modbus.words = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte+20:eth.ip.udp.modbus.stbyte+23));
                       eth.ip.udp.modbus.bytes = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte+24:eth.ip.udp.modbus.stbyte+25));
                       eth.ip.udp.modbus.data = eth.pack(eth.ip.udp.modbus.stbyte + 26:eth.ip.udp.modbus.stbyte + 26 + 2*eth.ip.udp.modbus.bytes - 1);


                       %If func 16 or 23, loop through data/registers and add to table
                       if eth.ip.udp.modbus.func == 16 || eth.ip.udp.modbus.func == 23
                           stp = eth.ip.udp.modbus.bytes*2/eth.ip.udp.modbus.words;
                           for n = 1:stp:eth.ip.udp.modbus.bytes*2;
                              %Check for existence of register as a key?
                              if ~isKey(MBMap,eth.ip.udp.modbus.register)
                                MBCol = MBCol + 1;
                                MBMap(eth.ip.udp.modbus.register) = MBCol; 
                              end
                              MBTable(L,MBCol) = hex2dec(eth.ip.udp.modbus.data(n:n+stp-1));
                              eth.ip.udp.modbus.register = dec2hex(hex2dec(eth.ip.udp.modbus.register)+1);
                           end
                           lastt = t;
                       end

                       %If func 4, make sure it is the response, then put
                       %data into table for register column

                    elseif false

                        %need code to handle serial to UDP conversion box

                    else
                        invalid = true;
                    end

                else
                    invalid = true;
                end

            else
                invalid = true;
            end


            if ~invalid

            end
        end
        %end
    end
   %Display Progress
   if int64(fl/1000)*1000 == fl
       for x = 1:length(mess);
           fprintf('\b');
       end
       %fprintf('Lines parsed: %i',fl);
        mess = sprintf('Lines parsed: %i / %i',fl,nol);
        fprintf('%s',mess);
       %Check execution time - getting slower:
       %%{
       ext = toc(tval);
        mess = sprintf('\nExecution Time: %f\n',ext);
        fprintf('%s',mess);
       %%}
   end
end
ext = toc - exst;

更新:我更新了上面的代码,以删除重载的操作符(disp和它被替换为mess和lastt)。

被要求使用分析器,因此我限制在表中的2000行(添加&L >=2000到while循环)来限制执行时间,下面是分析器的顶级结果:

代码语言:javascript
复制
SGAS_Wireshark_Parser_v0p7_fulleth        1    57.110 s     9.714 s
Strcat                                 9187    29.271 s    13.598 s
Blanks                                 9187    15.673 s    15.673 s
Uigetfile                                 1    12.226 s     0.009 s
uitools\private\uigetputfile_helper       1    12.212 s     0.031 s
FileChooser.FileChooser>FileChooser.show    1  12.085 s      0.006s
...er>FileChooser.showPeerAndBlockMATLAB    1  12.056 s      0.001s
...nChooser>FileOpenChooser.doShowDialog    1  12.049 s    12.049 s
hex2dec                               44924     2.944 s     2.702 s
num2str                               16336     1.139 s     0.550 s
str2double                            17356     1.025 s     1.025 s
int2str                               16336     0.589 s     0.589 s
fgetl                                 17356     0.488 s     0.488 s
dec2hex                                6126     0.304 s     0.304 s
fliplr                                44924     0.242 s     0.242 s

似乎是strcat调用在做这件事。我只在一行上显式地调用strcat。我正在做的其他字符串操作是否间接调用strcat?每个循环都应该调用strcat的次数相同,所以我仍然不明白为什么它运行的时间越长越长。

而且,hex2dec被称为很多,但并不真正影响时间。

但是无论如何,还有其他方法可以使用组合字符串吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-08 20:12:50

以下是问题所在:

字符串(MATLAB中的一个char数组)包数据被一次又一次地调整和重新分配。这就是为什么这段代码慢下来的原因。我做了以下步骤:

我消除了冗余变量包数据,现在只使用eth.pack。

我预先分配了eth.pack和两个已知长度的“辅助变量”,在循环开始之前为每个变量运行一次空白。

代码语言:javascript
复制
eth.pack = blanks(604);
thisline = blanks(47);
smline = blanks(32);

(注: 604是基于报头+ MODBUS协议的包数据的最大可能大小)

然后,我创建了一个指针变量来指向写入packdata的最后一个字符的位置。

代码语言:javascript
复制
pptr = 1;

...

dataline = int16(str2double(MBLine(1:4)));

thisline = MBLine(7:53); %Always 47 characters

smline = [thisline(~isspace(thisline)),blanks(32-sum(~isspace(thisline)))]; %Always 32 Characters

eth.pack(pptr:pptr+31) = smline;

pptr = pptr + 32;

上面的内容位于'if packline > 3‘块中,代替了'packdata =’语句,然后在'if塞place‘块的末尾是reset语句:

代码语言:javascript
复制
pptr = 1; %Reset Pointer

FYI,不足为奇的是,这带来了我的代码的其他缺陷,我已经修复了,但仍然需要完成。这不是一个大问题,因为这个循环执行闪电快速与这些变化。感谢伊万为我指明了正确的方向。

我一直在想我的大桌子,MBTable是问题所在.但这与此无关。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25192010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档