Vector problem? - How can I make the faster?
- From: Chun <chun.tse@xxxxxxxxx>
- Date: Fri, 26 Oct 2007 22:49:00 -0700
Hello,
I've written some code in C++ to decode a binary file. First I read
the contents of the file and then create an index to each record and
field in the file. Then I have method to dump to stdio or I used
populate TCL structures for use in tcl scripts.
When I run on windows then it decodes a large file faily quickly.
However, when I run on Sun solaris then it "stalls" every now before
finally completing. Someone said that this is to do with me using
vectors and the "stall" was the vector algorithm finding more memory
to increase it's size.
I've attached my code. Could someone comment on it and where it could
be improved? I'm particular interested in performance "tricks".
Thanks in advance
Michael
============================= ama.h
===================================
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <bitset>
#include <time.h>
#include <tcl.h>
class ama {
public:
ama();
~ama();
void init(std::string filename);
inline int ama::getI16(unsigned long offset) {
return (memblock[offset+1] & 0xff) << 8 | memblock[offset] &
0xff;
}
inline unsigned int ama::getH(unsigned long offset) {
return (memblock[offset] & 0xff);
}
inline int ama::getI32(unsigned long offset) {
return (memblock[offset] & 0xff ) << 24 |
(memblock[offset+1] & 0xff) << 16 |
(memblock[offset+3] & 0xff) << 8 |
memblock[offset+4] & 0xff;
}
// Package 100 Extraction
inline std::string ama::getDateTime(unsigned long offset) {
char ts[100];
unsigned int year = getH(offset+1);
unsigned char month = getH(offset+2);
unsigned char day = getH(offset+3);
unsigned char hour = getH(offset+4);
unsigned char min = getH(offset+5);
unsigned char secs = getH(offset+6);
unsigned char F0 = getH(offset+7) & 0x1;
//unsigned char F7 = (getH(offset+7) >> 6) & 0x1;
//unsigned char F8 = (getH(offset+7) >> 7) & 0x1;
if (F0 == 1) {
year = year + 2000;
} else {
year = year + 1900;
}
sprintf(ts,"%04d%02d%02d%02d%02d
%02d",year,month,day,hour,min,secs);
return ts;
}
inline unsigned long ama::getDuration(unsigned long offset) {
return ((unsigned long)(memblock[offset+2] & 0xff) << 16 |
(unsigned long)(memblock[offset+1] & 0xff) << 8 |
(unsigned long)(memblock[offset] & 0xff)) & 0xffffff;
}
inline bool ama::getIsDateStart(unsigned long offset) {
unsigned char F7 = (getH(offset+7) >> 6) & 0x1;
if (F7 == 1) {
return false;
} else {
return true;
}
}
inline unsigned long ama::getFlags3byte(unsigned long offset) {
return ((unsigned long)(memblock[offset+2] & 0xff) << 16 |
(unsigned long)(memblock[offset+1] & 0xff) << 8 |
(unsigned long)(memblock[offset] & 0xff)) & 0xffffff;
}
inline std::string ama::getDigits(unsigned long offset, int mask) {
char s[513];
static char dmap[] = "0123456789abcdef";
int digits = (memblock[offset] & mask);
int length = (digits / 2) + (digits % 2) + 1;
int index=0;
for (int i = 1; i < length; i++) {
s[index++] = dmap[((memblock[offset+i] & 0xf0) >> 4)];
s[index++] = dmap[memblock[offset+i] & 0xf];
}
// First character specifies the number of digits in field
s[digits] = '\0';
return s;
}
inline std::string ama::getHs(unsigned long offset, int length) {
char s[513];
static char dmap[] = "0123456789abcdef";
if (length == 0) return "";
int index=0;
for (int i = 0; i < length; i++) {
s[index++] = dmap[((memblock[offset+i] & 0xf0) >> 4)];
s[index++] = dmap[memblock[offset+i] & 0x0f];
}
// First character specifies the number of digits in field
s[length*2] = '\0';
return s;
}
inline std::string ama::getC(unsigned long offset, int length) {
int alen = length;
// Strip of spaces from end
for (int i = length; i > 0; i--) {
if ((int)memblock[offset + i - 1] == 32) {
alen--;
} else {
break;
}
}
std::string r(&memblock[offset],alen);
return r;
}
std::ifstream::pos_type filesize;
std::vector<unsigned long> _roffset;
unsigned int records;
class fieldinfo {
public:
unsigned long offset;
int length;
int type;
std::string name;
fieldinfo(unsigned long p, int l, int t, std::string n) {
offset = p; length = l; type = t; name = n;
}
};
class recordmap {
public:
std::vector<fieldinfo> headfldpos;
std::vector<fieldinfo> bodyfldpos;
int length;
};
std::vector<unsigned long int> block_offset;
std::vector<recordmap> filemap;
class pkginfo {
public:
bool set;
int number;
std::string name;
bool fixed;
int length_offset;
// If not fixed then length is retrieved from field
length_offset
// otherwise if Length_offset -1 then length is calculated
// and needs specical function
pkginfo(int n,char * s, bool f, int l_o) {
set = true; number = n; name = s; fixed = f; length_offset =
l_o;
}
pkginfo() {
set = false;
}
};
std::vector<pkginfo> pkgcfg;
void ama::dump(int rec_no);
unsigned long ama::decodeHeader(unsigned long offset);
unsigned long ama::decodeBody(unsigned long offset, unsigned long
end);
char * memblock;
private:
};
===================================== ama.cpp ======================
#include <ama.h>
ama::~ama() {
delete [] memblock;
}
// Open file
void ama::init(std::string filename) {
unsigned int length;
unsigned long offset;
std::ifstream file (filename.c_str(), std::ios::in|std::ios::binary|
std::ios::ate);
filesize = file.tellg();
memblock = new char [filesize];
file.seekg (0, std::ios::beg);
file.read ((char *)memblock, filesize);
file.close();
records = 0;
offset = 0;
// Block is 8192 bytes
while (offset < filesize) {
//std::cout << offset << std::endl;
block_offset.push_back(offset);
offset=offset + 8192;
}
std::vector<unsigned long int>::iterator theIterator;
offset = 0;
for(theIterator = block_offset.begin(); theIterator !=
block_offset.end(); theIterator++) {
unsigned long int c = *theIterator;
// Last record of a block could finish at the block border
// If so then then next block of records would already have
// been read
if (offset > c)
continue;
offset = c;
// if first byte not 0x84 (132) then skip to next block
while (getH(offset) == 0x84) {
_roffset.push_back(offset);
length = getI16(offset+1) & 0xfff;
offset=offset + length;
records++;
}
}
//std::cout << "Block Check Complete" << std::endl;
//std::cout << "Filemap Complete: Records " << records <<
std::endl;
}
void ama::dump(int rec_no) {
unsigned int length;
unsigned long offset;
int bodyOffset;
std::cout << "-------------- Record " << rec_no + 1 << "
--------------" << std::endl;
offset = _roffset[rec_no];
length = getI16(offset+1) & 0xfff;
bodyOffset = ama::decodeHeader(offset);
ama::decodeBody(offset + bodyOffset, offset + length);
}
unsigned long ama::decodeHeader(unsigned long offset) {
unsigned long flags;
int roffset = 0;
// Record Indetifier 1
// Record Length 1.4
// Flags 3
std::cout << "0x" << std::hex << offset << std::dec << ": ";
std::cout << "RecordIndentifer H'" << std::hex << getH(offset) <<
std::dec << std::endl;
std::cout << "RecordLength " << (getI16(offset+1) & 0xfff)
<< std::endl;
// if F18 is set (1) then the record owner type is in header
// if F16 is no set (0) then the record owner DN is in header
flags = ama::getFlags3byte(offset+3);
roffset = roffset + 6;
std::cout << "Flags H'" << std::hex << flags <<
std::dec << std::endl;
if (flags >> 7 & 0x1) {
// F18 = 1
// Record Sequence/Charge Status 0.4/0.4
// Record Owner Type 1
std::cout << "RecordOwnerType" << std::endl;
roffset = roffset + 2;
} else {
// F18 = 0
// Record Sequence/Charge Status 1
std::cout << "RecordSequence " << ((getH(roffset) >> 4) &
0xF) << std::endl;
std::cout << "ChargeSequence " << (getH(roffset) & 0xF) <<
std::endl;
// LAC Length/Owner ID Length 0.3/0.5
// LAC Length/Owner ID Length 0.3/0.5
// LAC + Directory Number (DN) Depends above
int lacLen = (getH(offset+7) >> 5) & 0x7 ;
int ownerIdLen = getH(offset+7) & 0x1F;
std::cout << "RecordOwnerDN.LacLength " << lacLen <<
std::endl;
std::cout << "RecordOwnerDN.OwnerIdLength " << ownerIdLen <<
" : digits "<< ama::getDigits(offset + 7,0x1F) << std::endl;
roffset = roffset + 2;
roffset = roffset + ( ownerIdLen % 2) + (ownerIdLen / 2);
}
return roffset;
}
unsigned long ama::decodeBody(unsigned long offset, unsigned long end)
{
unsigned int pkgId;
unsigned int roffset = offset;
unsigned int length;
unsigned int digits;
while (roffset < end) {
pkgId = getH(roffset);
if (pkgcfg[pkgId].set == false) {
std::cout << "Unsupported Package(" << pkgId << ")" << "
Skipping..." << std::endl;
return offset;
}
if (pkgcfg[pkgId].fixed == true) {
// Fixed Length
length = pkgcfg[pkgId].length_offset;
} else {
// Variable Length
if (pkgcfg[pkgId].length_offset > -1) {
// Depends on another field
length = getH(roffset + pkgcfg[pkgId].length_offset);
} else {
switch (pkgId) {
case 118:
case 101:
digits = getH(roffset + 1) & 0x1F;
length = (digits / 2) + (digits % 2) + 2;
break;
default :
std::cout << "Variable Skipping Package(" << pkgId
<< ")" << std::endl;
return offset;
break;
}
}
}
std::cout << "0x" << std::hex << roffset << std::dec << ": ";
switch (pkgId) {
case 100:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << " : ";
if (ama::getIsDateStart(roffset)) {
std::cout << "StartTime " << ama::getDateTime(roffset)
<< " : ";
} else {
std::cout << "EndTime " << ama::getDateTime(roffset)
<< " : ";
}
std::cout << "Duration " << ama::getDuration(roffset+8) <<
std::endl;
break;
case 101:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << " : ";
std::cout << ama::getDigits(roffset + 1, 0x1F) <<
std::endl;
break;
case 102:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << ".";
std::cout << "ServiceIndicator " << getH(roffset+1) << ",
";
std::cout << pkgcfg[pkgId].name << ".";
std::cout << "AdditonalInformation " << getH(roffset+2) <<
", ";
std::cout << pkgcfg[pkgId].name << ".";
std::cout << "F1 " << (getH(roffset+3) & 0x1) <<
std::endl;
break;
case 103:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << " : ";
std::cout << (getI32(roffset+1) & 0xFFFFFF) << std::endl;
break;
case 104:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << " : ";
std::cout << getI16(roffset+1) << std::endl;
break;
default:
std::cout << "Package(" << pkgId << ") " <<
pkgcfg[pkgId].name << "XXX" << std::endl;
break;
}
roffset = roffset + length;
}
return offset;
}
ama::ama() {
// Setup configuration
pkgcfg.assign(256,pkginfo());
// no fieldname fixed
length/offset
pkgcfg[100] = pkginfo(100,"DateTimeDuration", true,
11);
pkgcfg[101] = pkginfo(101,"PartnerDirectoryNumber", false,
-1);
pkgcfg[102] = pkginfo(102,"ServiceInfo", true,
4);
pkgcfg[103] = pkginfo(103,"ChargeUnitsForConnection", true,
4);
pkgcfg[104] = pkginfo(104,"ChargeUnitsForFau", true,
3);
}
.
- Follow-Ups:
- Re: Vector problem? - How can I make the faster?
- From: rossum
- Re: Vector problem? - How can I make the faster?
- From: Richard Harter
- Re: Vector problem? - How can I make the faster?
- From: Alan Morgan
- Re: Vector problem? - How can I make the faster?
- From: CBFalconer
- Re: Vector problem? - How can I make the faster?
- Prev by Date: Re: Please help!
- Next by Date: Re: Please help!
- Previous by thread: Please help!
- Next by thread: Re: Vector problem? - How can I make the faster?
- Index(es):
Relevant Pages
|