Disclaimer: I'm getting carried away here and most folks will want to bypass this post now.
Buffer fBuf_Create()
{ // Return an unclaimed empty Buffer, 'creating' one if needed.
Buffer buf
buf = pop unclaimed Buffer from the UnClaimed_Buffers Stack
if (null buf) // stack empty -
then buf = create() // a new one. return(buf)
} // end fBuf_Create()
Buffer fBuf_Create(int Size)
{ // Overloaded, make sure the Buffer starts at the given size
// Note: I am unsure about doing this...
Buffer buf = fBuf_Create()
if (Size >= 0) length(buf, Size)
return(buf)
} // end fBuf_Create(Size)
void fBuf_Delete(Buffer &buf)
{ // Claim the Buffer and make it available for other Functions
buf = "" // also set length to zero and/or setEmpty(buf) ??
push buf onto the UnClaimed_Buffers stack.
buf = null // ?? Will this mess up the stack?
} // end fBuf_Delete()
void fBuf_ReleaseAll()
{ // Delete all unclaimed Buffers
// Calling programs should call this before they exit;
// and possibly after other intense computing times
bool Done = false
while(!Done)
{ buf = pop unclaimed Buffer from the UnClaimed_Buffers Stack
if (null buf) // stack empty -
then Done = true
else delete(buf)
}
} // end fBufReleaseAll()
llandale - Wed Aug 10 14:30:36 EDT 2011 |
Re: Buffer Get and Release I would go even one step further. Memory Allocation is slow for sure, the bad thing is, it gets much (factor 100-1000 times) slower if you create more than 5000 Objects in DOORS (which is not much). Example: You store the contents of one attribute of one module in a buffer each and put them to a skip ... BOOM! For middle-sized modules your program will get a HUGE performance decrease. So recycling buffers is not sufficient to get around the performance drop. I implemented a StringBuffer that will store a couple of strings all in one buffer, and store the string starts in an array. This way you will have another advantage:
If you are interested I can post some code. Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS |
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 11 08:40:44 EDT 2011
If you are interested I can post some code. Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS [] Creating the 5000th Buffer/Skip/Whatever causes DOORS to degrade; even if you've deleted many already. for i 0-4999{buf = create(); delete(buf)} what follows is degraded. [] Having 5000 Buffers/Skip/Whatever in existence in one time causes degrade. [] 4999 does not [] What is "Whatever" [] There is some XFLAG or pragma whatever that can fix this, yes? lol Golly, I think I've been experiencing this on some old code used on some other huge project I'm not allowed to see. This is serious trouble I think.
|
Re: Buffer Get and Release llandale - Fri Aug 12 15:21:09 EDT 2011
It is indeed serious trouble for all DXL programs dealing with large data sets. The made me revive the array for a lot of datasets, where I used nested skips, just to get around the performance leak. If you run the attached DXL script, you will get an ouput like the below. Tick Interval Counter Total 15 1000 1000 31 1000 2000 78 1000 3000 125 1000 4000 156 1000 5000 203 1000 6000 250 1000 7000 ... 27640 1000 36000 29531 1000 37000 31484 1000 38000 33500 1000 39000
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS Attachments attachment_14672594_Memory.zip |
Re: Buffer Get and Release Mathias Mamsch - Tue Aug 16 04:29:07 EDT 2011
It is indeed serious trouble for all DXL programs dealing with large data sets. The made me revive the array for a lot of datasets, where I used nested skips, just to get around the performance leak. If you run the attached DXL script, you will get an ouput like the below. Tick Interval Counter Total 15 1000 1000 31 1000 2000 78 1000 3000 125 1000 4000 156 1000 5000 203 1000 6000 250 1000 7000 ... 27640 1000 36000 29531 1000 37000 31484 1000 38000 33500 1000 39000
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
I sure hope you mean "every data structure in DOORS that is 'create'd" and hope that 'ModuleVersion' was a typo. If not then there is a much bigger problem since you cannot de-allocate that. max: 200000 interval = 1000 Counter Ticks Delta Find 1000 0 0 0 2000 31 31 0 3000 32 1 15 4000 32 0 15 5000 47 15 16 6000 62 15 16 7000 62 0 16 8000 94 32 15 9000 94 0 16 10000 109 15 16 ... 30000 1078 172 78 ... 40000 2485 172 109 ... 50000 3562 -48 141 ... 60000 4453 63 156 ... 70000 5218 93 203 ... 80000 6063 110 312 ... 90000 6937 109 547 ... 100000 7687 62 922 ... 110000 8500 47 1391 ... 120000 9328 78 1968 ... 130000 10109 63 2328 ... 140000 10922 94 2813 ... 150000 11688 63 3218 ... 160000 12485 63 3640 ... 170000 13235 17 3984 ... 180000 14063 78 4312 ... 190000 14828 47 4641 191000 15000 172 4672 192000 15015 15 4750 193000 11922 -3093 4735 194000 7609 -4313 4781 195000 7782 173 4812 196000 8094 312 4844 197000 8234 140 4859 198000 8422 188 4891 199000 8703 281 4937 200000 8860 157 5015
// Modified by Landale
pragma runLim,0
int maxObjects = 200000
int interval = 1000
int Counter = 0
Skip skpBuffs = create() // KEY: 'int' sequency, DATA: 'Buffer'
Skip skpInterval = create() // ditto, only has interval entries
Buffer bCreate, bFound
Buffer bufResults = create()
bufResults += "max: " maxObjects "\tinterval = " interval "\n"
bufResults += "Counter\tTicks\tDelta\tFind\n"
int IntervalStartTime = getTickCount_(),
TicksThisInterval = 0, IntervalDelta, TicksLastInterval = 0,
i, FindStartTime, FindEndTime
for (Counter=1; Counter<=maxObjects; Counter++)
{
// Skip sk = create()
bCreate = create(100)
put(skpBuffs, Counter, bCreate)
put(skpInterval, Counter, bCreate)
// string s = "abc" ""
if ((Counter)%interval == 0) {
//tick = getTickCount_() - IntervalStartTime
//Counter += counter
// print "Interval: " tick " -> Count = " counter " Gesamt:" Counter "\n"
TicksThisInterval = getTickCount_() - IntervalStartTime
IntervalDelta = TicksThisInterval - TicksLastInterval
FindStartTime = getTickCount_()
for (i=(Counter-interval)+1; i<=Counter; i++)
{ find(skpBuffs, i, bFound)
bFound += "a"
}
delete(skpInterval)
skpInterval = create()
FindEndTime = getTickCount_() - FindStartTime
bufResults += Counter "\t" TicksThisInterval "\t" IntervalDelta "\t" FindEndTime "\n"
// Get ready for next loop:
IntervalStartTime = getTickCount_()
TicksLastInterval = TicksThisInterval
}
// delete(bCreate)
}
// bufResults += "Interval: " (getTickCount_() - IntervalStartTime) " Gesamt:" (Counter) "\n"
print tempStringOf(bufResults)
delete(bufResults)
for bCreate in skpBuffs do{delete(bCreate)}
delete(skpBuffs)
delete(skpInterval)
|
Re: Buffer Get and Release llandale - Wed Aug 17 09:46:19 EDT 2011
I sure hope you mean "every data structure in DOORS that is 'create'd" and hope that 'ModuleVersion' was a typo. If not then there is a much bigger problem since you cannot de-allocate that. max: 200000 interval = 1000 Counter Ticks Delta Find 1000 0 0 0 2000 31 31 0 3000 32 1 15 4000 32 0 15 5000 47 15 16 6000 62 15 16 7000 62 0 16 8000 94 32 15 9000 94 0 16 10000 109 15 16 ... 30000 1078 172 78 ... 40000 2485 172 109 ... 50000 3562 -48 141 ... 60000 4453 63 156 ... 70000 5218 93 203 ... 80000 6063 110 312 ... 90000 6937 109 547 ... 100000 7687 62 922 ... 110000 8500 47 1391 ... 120000 9328 78 1968 ... 130000 10109 63 2328 ... 140000 10922 94 2813 ... 150000 11688 63 3218 ... 160000 12485 63 3640 ... 170000 13235 17 3984 ... 180000 14063 78 4312 ... 190000 14828 47 4641 191000 15000 172 4672 192000 15015 15 4750 193000 11922 -3093 4735 194000 7609 -4313 4781 195000 7782 173 4812 196000 8094 312 4844 197000 8234 140 4859 198000 8422 188 4891 199000 8703 281 4937 200000 8860 157 5015
// Modified by Landale
pragma runLim,0
int maxObjects = 200000
int interval = 1000
int Counter = 0
Skip skpBuffs = create() // KEY: 'int' sequency, DATA: 'Buffer'
Skip skpInterval = create() // ditto, only has interval entries
Buffer bCreate, bFound
Buffer bufResults = create()
bufResults += "max: " maxObjects "\tinterval = " interval "\n"
bufResults += "Counter\tTicks\tDelta\tFind\n"
int IntervalStartTime = getTickCount_(),
TicksThisInterval = 0, IntervalDelta, TicksLastInterval = 0,
i, FindStartTime, FindEndTime
for (Counter=1; Counter<=maxObjects; Counter++)
{
// Skip sk = create()
bCreate = create(100)
put(skpBuffs, Counter, bCreate)
put(skpInterval, Counter, bCreate)
// string s = "abc" ""
if ((Counter)%interval == 0) {
//tick = getTickCount_() - IntervalStartTime
//Counter += counter
// print "Interval: " tick " -> Count = " counter " Gesamt:" Counter "\n"
TicksThisInterval = getTickCount_() - IntervalStartTime
IntervalDelta = TicksThisInterval - TicksLastInterval
FindStartTime = getTickCount_()
for (i=(Counter-interval)+1; i<=Counter; i++)
{ find(skpBuffs, i, bFound)
bFound += "a"
}
delete(skpInterval)
skpInterval = create()
FindEndTime = getTickCount_() - FindStartTime
bufResults += Counter "\t" TicksThisInterval "\t" IntervalDelta "\t" FindEndTime "\n"
// Get ready for next loop:
IntervalStartTime = getTickCount_()
TicksLastInterval = TicksThisInterval
}
// delete(bCreate)
}
// bufResults += "Interval: " (getTickCount_() - IntervalStartTime) " Gesamt:" (Counter) "\n"
print tempStringOf(bufResults)
delete(bufResults)
for bCreate in skpBuffs do{delete(bCreate)}
delete(skpBuffs)
delete(skpInterval)
I think you are mixing up some timings here ... In my previous post I was talking only about the time for allocations (create / delete). And to be clear, as you already states, this only refers to allocated objects, as soon as you delete them there is no performance loss anymore.
int MAX_ALLOCATIONS = 50000
int INTERVAL = 1000
int iCurrentAllocations = 0
Array arAllocs = create(MAX_ALLOCATIONS, 1)
// this function will allocate iCount objects and store them in the arAllocs array ...
void doAllocations(int iCount) {
int i; for i in 0:(iCount-1) do {
Skip val = create()
// Buffer val = create(100)
put (arAllocs, val, iCurrentAllocations + i, 0)
}
iCurrentAllocations += iCount
}
pragma runLim,0
print "Allocated\tDelta\n"
// how many times shall we repeat the search
int TESTLOOP = 500000 // use 500000 for buffer test, 20000 for skip test
// prepare test data for Skip find: create a skip with 10000 entries
Skip skTest = create()
{ int i; for i in 1:10000 do put(skTest, i,i) }
// prepare test data for buffer append
string sAppend = "1234567890"
Buffer buf = create(TESTLOOP * (length sAppend) + 100) // make sure the buffer does not overflow
while (iCurrentAllocations < MAX_ALLOCATIONS) {
doAllocations INTERVAL // make a couple of allocations => 1000 objects more
// make this loop as efficient as possible:
// --> only put the test code in there
int tickStart = getTickCount_()
buf = ""
int i,j; for i in 0:TESTLOOP do {
// find a value in the middle of the skip list a lot of times, to measure
// the speed of find
// find(skTest, 5000, j)
// append a string to a buffer a lot of times to measure the speed of append
buf += sAppend
}
int timeDelta = getTickCount_() - tickStart
print iCurrentAllocations "\t" timeDelta "\n"
}
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 18 04:47:14 EDT 2011
I think you are mixing up some timings here ... In my previous post I was talking only about the time for allocations (create / delete). And to be clear, as you already states, this only refers to allocated objects, as soon as you delete them there is no performance loss anymore.
int MAX_ALLOCATIONS = 50000
int INTERVAL = 1000
int iCurrentAllocations = 0
Array arAllocs = create(MAX_ALLOCATIONS, 1)
// this function will allocate iCount objects and store them in the arAllocs array ...
void doAllocations(int iCount) {
int i; for i in 0:(iCount-1) do {
Skip val = create()
// Buffer val = create(100)
put (arAllocs, val, iCurrentAllocations + i, 0)
}
iCurrentAllocations += iCount
}
pragma runLim,0
print "Allocated\tDelta\n"
// how many times shall we repeat the search
int TESTLOOP = 500000 // use 500000 for buffer test, 20000 for skip test
// prepare test data for Skip find: create a skip with 10000 entries
Skip skTest = create()
{ int i; for i in 1:10000 do put(skTest, i,i) }
// prepare test data for buffer append
string sAppend = "1234567890"
Buffer buf = create(TESTLOOP * (length sAppend) + 100) // make sure the buffer does not overflow
while (iCurrentAllocations < MAX_ALLOCATIONS) {
doAllocations INTERVAL // make a couple of allocations => 1000 objects more
// make this loop as efficient as possible:
// --> only put the test code in there
int tickStart = getTickCount_()
buf = ""
int i,j; for i in 0:TESTLOOP do {
// find a value in the middle of the skip list a lot of times, to measure
// the speed of find
// find(skTest, 5000, j)
// append a string to a buffer a lot of times to measure the speed of append
buf += sAppend
}
int timeDelta = getTickCount_() - tickStart
print iCurrentAllocations "\t" timeDelta "\n"
}
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
Oh and by the way: ModuleVersions (sourceVersion, targetVersion, moduleVersion, ...) all those perms ARE allocated objects and need to be deleted by the delete(ModuleVersion) perm. You can test for yourself:
int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
int *getCurrentDXLContextPtr () {
DB x = create ""
int *ptr = addr_ x
int *result = ptr @ 48
destroy x
return result
}
int *getMemoryBlockNodes (int *cc) { return cc @ 0x74 }
int *nextNode (int *memNode) { return memNode @ 8 }
int countAllocatedObjects() {
int *memBlocks = getMemoryBlockNodes getCurrentDXLContextPtr()
int count = 0
while (!null memBlocks) {
memBlocks = nextNode memBlocks
count++
}
return count
}
// comment me in to see the object counts increase;
// Skip sk = create(); Buffer buf = create()
print "Allocated Objects Before doing stuff:" countAllocatedObjects() "\n"
if (null current) error "Please open a module for this test!"
ModuleVersion mod = moduleVersion current
print "Allocated Objects with one moduleVersion:" countAllocatedObjects() "\n"
ModuleVersion mod2 = moduleVersion current
print "Allocated Objects with two moduleVersions:" countAllocatedObjects() "\n"
delete mod; delete mod2
print "Allocated Objects after deletions:" countAllocatedObjects() "\n"
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 18 04:59:24 EDT 2011
Oh and by the way: ModuleVersions (sourceVersion, targetVersion, moduleVersion, ...) all those perms ARE allocated objects and need to be deleted by the delete(ModuleVersion) perm. You can test for yourself:
int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
int *getCurrentDXLContextPtr () {
DB x = create ""
int *ptr = addr_ x
int *result = ptr @ 48
destroy x
return result
}
int *getMemoryBlockNodes (int *cc) { return cc @ 0x74 }
int *nextNode (int *memNode) { return memNode @ 8 }
int countAllocatedObjects() {
int *memBlocks = getMemoryBlockNodes getCurrentDXLContextPtr()
int count = 0
while (!null memBlocks) {
memBlocks = nextNode memBlocks
count++
}
return count
}
// comment me in to see the object counts increase;
// Skip sk = create(); Buffer buf = create()
print "Allocated Objects Before doing stuff:" countAllocatedObjects() "\n"
if (null current) error "Please open a module for this test!"
ModuleVersion mod = moduleVersion current
print "Allocated Objects with one moduleVersion:" countAllocatedObjects() "\n"
ModuleVersion mod2 = moduleVersion current
print "Allocated Objects with two moduleVersions:" countAllocatedObjects() "\n"
delete mod; delete mod2
print "Allocated Objects after deletions:" countAllocatedObjects() "\n"
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
So, an allocated object is anything with an associeated "delete" or "destroy"? I see if you delete(mod); mod = mod2 you effectively re-allocate it again. Scary. |
Re: Buffer Get and Release llandale - Thu Aug 18 16:36:14 EDT 2011
No, you do not reallocate it again? Why would you think that? | This is only This one creates the Skip Object | an arrow and returns an arrow to it | | | | V /------^--------\ Skip sk = create() // copy the arrow ... Skip sk2 = sk // delete the data, sk and sk2 both point to an invalid skip delete sk // create another skip without even storing a pointer. A new object is allocated but not accessible anymore, // through a pointer. create Skip
Baseline b = baseline (1,0,"") // this will allocate a baseline object. // how to free it? // delete b <- this is not a destructor, but will try to delete the baseline from the module! :-)
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 18 17:02:07 EDT 2011
No, you do not reallocate it again? Why would you think that? | This is only This one creates the Skip Object | an arrow and returns an arrow to it | | | | V /------^--------\ Skip sk = create() // copy the arrow ... Skip sk2 = sk // delete the data, sk and sk2 both point to an invalid skip delete sk // create another skip without even storing a pointer. A new object is allocated but not accessible anymore, // through a pointer. create Skip
Baseline b = baseline (1,0,"") // this will allocate a baseline object. // how to free it? // delete b <- this is not a destructor, but will try to delete the baseline from the module! :-)
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
I know I'm thick about this internal stuff, also thick about "*" and "addr_", and frankly cannot follow your code but presume its following a linked list. #Units After... 0 .. Start 1 .. mod = 2 .. mod2 = 1 .. delete(mod) 2 .. mod = mod2 1 .. delete mod2 0 .. delete mod
/*
posted Mathias Mamsch 18-Aug-2011
http://www.ibm.com/developerworks/forums/post!reply.jspa?messageID=14673586
Tweaked by Landale
*/
int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
int *getCurrentDXLContextPtr () {
DB x = create ""
int *ptr = addr_ x
int *result = ptr @ 48
destroy x
return result
}
int *getMemoryBlockNodes (int *cc) { return cc @ 0x74 } // 0x74 = 116
int *nextNode (int *memNode) { return memNode @ 8 }
int countAllocatedObjects() {
int *memBlocks = getMemoryBlockNodes getCurrentDXLContextPtr()
int count = 0
while (!null memBlocks) {
memBlocks = nextNode memBlocks
count++
}
return count
}
void DumpCount(string Label)
{ // dump the allocated units with the Label
print countAllocatedObjects() "\t.. " Label "\n"
}
print "#Units\tAfter...\n"
// comment me in to see the object counts increase;
//Skip sk = create(); Buffer buf = create()
DumpCount("Start")
if (null current) error "Please open a module for this test!"
ModuleVersion mod = moduleVersion current
DumpCount("mod = ")
ModuleVersion mod2 = moduleVersion current
DumpCount("mod2 = ")
// print "\t\t(mod == mod2): " (mod == mod2) "\n"
delete mod;
DumpCount("delete(mod)")
mod = mod2
DumpCount("mod = mod2")
delete (mod2)
DumpCount("delete mod2")
delete(mod)
DumpCount("delete mod")
|
Re: Buffer Get and Release llandale - Thu Aug 18 17:36:47 EDT 2011
I know I'm thick about this internal stuff, also thick about "*" and "addr_", and frankly cannot follow your code but presume its following a linked list. #Units After... 0 .. Start 1 .. mod = 2 .. mod2 = 1 .. delete(mod) 2 .. mod = mod2 1 .. delete mod2 0 .. delete mod
/*
posted Mathias Mamsch 18-Aug-2011
http://www.ibm.com/developerworks/forums/post!reply.jspa?messageID=14673586
Tweaked by Landale
*/
int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
int *getCurrentDXLContextPtr () {
DB x = create ""
int *ptr = addr_ x
int *result = ptr @ 48
destroy x
return result
}
int *getMemoryBlockNodes (int *cc) { return cc @ 0x74 } // 0x74 = 116
int *nextNode (int *memNode) { return memNode @ 8 }
int countAllocatedObjects() {
int *memBlocks = getMemoryBlockNodes getCurrentDXLContextPtr()
int count = 0
while (!null memBlocks) {
memBlocks = nextNode memBlocks
count++
}
return count
}
void DumpCount(string Label)
{ // dump the allocated units with the Label
print countAllocatedObjects() "\t.. " Label "\n"
}
print "#Units\tAfter...\n"
// comment me in to see the object counts increase;
//Skip sk = create(); Buffer buf = create()
DumpCount("Start")
if (null current) error "Please open a module for this test!"
ModuleVersion mod = moduleVersion current
DumpCount("mod = ")
ModuleVersion mod2 = moduleVersion current
DumpCount("mod2 = ")
// print "\t\t(mod == mod2): " (mod == mod2) "\n"
delete mod;
DumpCount("delete(mod)")
mod = mod2
DumpCount("mod = mod2")
delete (mod2)
DumpCount("delete mod2")
delete(mod)
DumpCount("delete mod")
Argh ... now you scared me :-) Ok, what I said is the normal case ... UNFORTUNATELY: There are a lot of 'custom' ::= operators defined in DXL. ModuleVersion ::= (ModuleVersion &, ModuleVersion)
_k ::= (_k&, _k)
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 18 17:58:05 EDT 2011
Argh ... now you scared me :-) Ok, what I said is the normal case ... UNFORTUNATELY: There are a lot of 'custom' ::= operators defined in DXL. ModuleVersion ::= (ModuleVersion &, ModuleVersion)
_k ::= (_k&, _k)
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
Surely someone with full and clever understanding of "*" and "addr_" and internal data structures could write this function, yes?
void delete(Comment &cmnt)
{
}
|
Re: Buffer Get and Release llandale - Fri Aug 19 15:26:13 EDT 2011 Surely someone with full and clever understanding of "*" and "addr_" and internal data structures could write this function, yes?
void delete(Comment &cmnt)
{
}
Anyway: An entry in the memory allocation list consists of
So what the delete (Skip) funtion does for example, is a) to call the destructor function of the skip list b) to unlink the skip entry from the memory allocation list Now we could manually unlink any variable in the memory allocation list, effectively leaking the memory, creating a true global variable, whose value will persist after the DXL ends. This would get around the performance penalty but still leak the memory. To really write a delete (Comment &) function you would need to call the destructor function. But we cannot call it from DXL directly. So this would require another bad hack. Is this of immediate concern for you? To delete Comment, Discussion or Baseline objects? Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS |
Re: Buffer Get and Release Mathias Mamsch - Fri Aug 19 18:09:53 EDT 2011
So what the delete (Skip) funtion does for example, is a) to call the destructor function of the skip list b) to unlink the skip entry from the memory allocation list Now we could manually unlink any variable in the memory allocation list, effectively leaking the memory, creating a true global variable, whose value will persist after the DXL ends. This would get around the performance penalty but still leak the memory. To really write a delete (Comment &) function you would need to call the destructor function. But we cannot call it from DXL directly. So this would require another bad hack. Is this of immediate concern for you? To delete Comment, Discussion or Baseline objects? Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS You cannot call a function given the address of that function? |
Re: Buffer Get and Release llandale - Mon Aug 22 14:03:38 EDT 2011 But there are other purposes for which I consider implementing such a thing. Extending DOORS DXL with fast C or Assembler code would allow a completly new way of interfacing with other applications. Instead of communicating over COM (writing a COM server for your application) you could directly talk to the other programs API. I am also thinking about fast export/data exchange/change management tools, which would be possible with fast string processing. If I had a nice SHA1 function available from DXL, I could do awesome change management and lightning fast comparison. Calling the Windows API could give a new way for user interfaces (e.g. solve the DOORS IDLE problem). But on the other hand, I guess in the end DXL will die sooner or later. So why bother ... Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS |
Re: Buffer Get and Release Mathias Mamsch - Mon Aug 22 15:58:00 EDT 2011 Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS I don't believe DXL is going anywhere, IBM and the community has FAR too much invested in it to let it go away. If they can maintain COBOL and RPG they can maintain DXL. Perhaps "frozen" however. |
Re: Buffer Get and Release I have definitely seen this non-linear behavior as more and more objects are allocated and released. For certain repetitive applications, I got major performance improvement by emptying and reusing objects in lieu of deleting them and re-allocating new ones. Is there a corollary to the database world and SQL connections? I know getting connections to a database is regarded as an "expensive" operation. As a result many websites use a "connection pool" of connections that can be tuned per application need. Would a similar utility be of use for DXL apps for Skip lists or Buffers? Mathias, do you have a "object pool" manager or was it something informal? What is a good tool for monitoring different variations to discover the best tuning for a situation. I've used some generic Microsoft monitoring S/W but they changed the name a few years ago and I forgot what they call it now. |
Re: Buffer Get and Release SystemAdmin - Mon Aug 22 19:02:26 EDT 2011
I am pretty sure that there is no performance penalty if you delete all allocated objects properly. However my experience is, most of the time you don't. Using the code above you can see if you did. If you did, you will experience your code running slower, because allocations become more and more expensive. Just reusing objects does only cure the symptom, not the cause. Sure when you have 40000 allocated objects every allocation becomes very expensive, so reusing an existing object will bring you a big performance gain. But If you get rid of the allocations itself (in most of my code I found unnecessary allocations, like ModuleVersions and stuff, which I simply did not free out of lazyness), then allocations will be super fast and you will be happy again.
string oleGetOld (OleAutoObj o, string n, OleAutoArgs a, OleAutoObj& r) { return oleGet(o,n,a,r) }
string oleGetOld (OleAutoObj o, string s, OleAutoObj &r) { return oleGet(o,s,r) }
string oleMethodOld (OleAutoObj o, string s, OleAutoArgs a, OleAutoObj &r) { return oleMethod(o,s,a,r) }
bool oleCloseAutoObjectOld (OleAutoObj& r) { return oleCloseAutoObject(r) }
string oleGet (OleAutoObj o, string n, OleAutoArgs a, OleAutoObj &r) { string res = oleGetOld(o,n,a,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
string oleGet (OleAutoObj o, string s, OleAutoObj &r) { string res = oleGetOld(o,s,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
string oleMethod (OleAutoObj o, string s, OleAutoArgs a, OleAutoObj &r) { string res = oleMethodOld(o,s,a,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
bool oleCloseAutoObject (OleAutoObj& r) { OleAutoObj rr = r; removeAllocatedObject ((addr_ rr) int, "OleAutoObj"); return oleCloseAutoObjectOld(r); }
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
Re: Buffer Get and Release Mathias Mamsch - Tue Aug 23 05:51:51 EDT 2011
I am pretty sure that there is no performance penalty if you delete all allocated objects properly. However my experience is, most of the time you don't. Using the code above you can see if you did. If you did, you will experience your code running slower, because allocations become more and more expensive. Just reusing objects does only cure the symptom, not the cause. Sure when you have 40000 allocated objects every allocation becomes very expensive, so reusing an existing object will bring you a big performance gain. But If you get rid of the allocations itself (in most of my code I found unnecessary allocations, like ModuleVersions and stuff, which I simply did not free out of lazyness), then allocations will be super fast and you will be happy again.
string oleGetOld (OleAutoObj o, string n, OleAutoArgs a, OleAutoObj& r) { return oleGet(o,n,a,r) }
string oleGetOld (OleAutoObj o, string s, OleAutoObj &r) { return oleGet(o,s,r) }
string oleMethodOld (OleAutoObj o, string s, OleAutoArgs a, OleAutoObj &r) { return oleMethod(o,s,a,r) }
bool oleCloseAutoObjectOld (OleAutoObj& r) { return oleCloseAutoObject(r) }
string oleGet (OleAutoObj o, string n, OleAutoArgs a, OleAutoObj &r) { string res = oleGetOld(o,n,a,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
string oleGet (OleAutoObj o, string s, OleAutoObj &r) { string res = oleGetOld(o,s,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
string oleMethod (OleAutoObj o, string s, OleAutoArgs a, OleAutoObj &r) { string res = oleMethodOld(o,s,a,r); OleAutoObj rr = r; addAllocatedObject ((addr_ rr) int, "OleAutoObj"); return res }
bool oleCloseAutoObject (OleAutoObj& r) { OleAutoObj rr = r; removeAllocatedObject ((addr_ rr) int, "OleAutoObj"); return oleCloseAutoObjectOld(r); }
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
But surely if you can look for places that allocate and insert your clever code, cannot you just make sure there is a 'delete' associated with it? I wonder how you find "Comment" allocations that have no associated 'create', nor what you do about them since they have no 'delete'. When you find a rouge allocation, can you determine which 'type' it is? I wonder about the following functions [] Allocations_RememberCurrent() - Finds and remembers all currently active allocations [] Allocations_DeleteRogues() - Finds all current allocations; those that were not ... remembered by the previous function are deleted. So a main program can do this: get list of all modules to processs for each module {.. Allocations_RememberCurrent() ... process module, creating lots of allocations ... Allocations_DeleteRogues() } Then a leak within a large module will slow down only that module, and speed picks back up again when its done.
|
Re: Buffer Get and Release llandale - Tue Aug 23 12:34:04 EDT 2011
For those Comments and stuff, well if there is no delete function I still hook creates to see how many I have and where in the code I allocated them, so I can see if there is a problem. If so I would need to reduce the allocations somehow, since I cannot just insert a delete. Rogue Allocations (that is functions that I did not hook from the include file) are a problem, since I do not know where in the code they happened. In this case I would first find out the address of the destructor, and then go and search for the data type with that destructor. When I know the data type I will add the allocation and destruction function to the include file. In the next run I will then know where the allocations happened. As for your idea of storing the allocation list and restoring it after the run. You would have the same problem as before, you would need to free the objects, not just leak them. Therefore you could create a list of destructor addresses with their corresponding datatypes and using that find each object in the list to call the appropriate delete function. Might work. Problematic would be global variables that were allocated during the loop, like a skip list with error messages or stuff like that. You could not decide which variables to keep. So I guess finding the place where the allocations happen and see that they get deleted might be the better approach. Regards, Mathias Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS |
Re: Buffer Get and Release Mathias Mamsch - Tue Aug 16 04:29:07 EDT 2011
It is indeed serious trouble for all DXL programs dealing with large data sets. The made me revive the array for a lot of datasets, where I used nested skips, just to get around the performance leak. If you run the attached DXL script, you will get an ouput like the below. Tick Interval Counter Total 15 1000 1000 31 1000 2000 78 1000 3000 125 1000 4000 156 1000 5000 203 1000 6000 250 1000 7000 ... 27640 1000 36000 29531 1000 37000 31484 1000 38000 33500 1000 39000
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS Hi guys !
First of all, I love the graphics entry ! ;) Here after a code using the print ...
pragma runLim,0 The tree lasts lines of my print:
4633 1000 498000 Now a version without the print feature ...
pragma runLim,0 And my 3 lasts lines :
2247 1000 498000
2262 ms without the print against 4664 ms for the "using print" version. So ... how do you usually follow the running of your scripts ?? Perhaps this can have a big impact on their global performances ... PS : yes, i know my print is not correct ... 1000 should be replaced by 5000 ... but there is no impact on performance o;) |
Re: Buffer Get and Release pommCannelle - Thu Dec 12 05:39:37 EST 2013 Hi guys !
First of all, I love the graphics entry ! ;) Here after a code using the print ...
pragma runLim,0 The tree lasts lines of my print:
4633 1000 498000 Now a version without the print feature ...
pragma runLim,0 And my 3 lasts lines :
2247 1000 498000
2262 ms without the print against 4664 ms for the "using print" version. So ... how do you usually follow the running of your scripts ?? Perhaps this can have a big impact on their global performances ... PS : yes, i know my print is not correct ... 1000 should be replaced by 5000 ... but there is no impact on performance o;) Didn't study your code, but yes each print statement takes a little longer than the previous one; and 1000s of prints will drasically slow down your code; and yes staging your desired print messages in a buffer and then printing the buffer is much faster. -Louie |
Re: Buffer Get and Release pommCannelle - Thu Dec 12 05:39:37 EST 2013 Hi guys !
First of all, I love the graphics entry ! ;) Here after a code using the print ...
pragma runLim,0 The tree lasts lines of my print:
4633 1000 498000 Now a version without the print feature ...
pragma runLim,0 And my 3 lasts lines :
2247 1000 498000
2262 ms without the print against 4664 ms for the "using print" version. So ... how do you usually follow the running of your scripts ?? Perhaps this can have a big impact on their global performances ... PS : yes, i know my print is not correct ... 1000 should be replaced by 5000 ... but there is no impact on performance o;) First of all, why would we include a print statement in the measurement at all. Normally you do something like:
You need to differentiate between a print on the DXL interaction window and a print in batch mode or using cout << ... Of course print statements on the DXL interaction window get slower, because DOORS needs to fill the richText box everytime with more content, so the graphic updates become slower. So print is a really "heavy" operation in interactive mode. So if I understand your question correctly you are asking about how to profile your DXL programs? The most important rule for optimizing is to first find out where your program needs most of its runtime. On larger programs I will normally go with logging timestamps on certain parts of the code. Normally you will have some kind of logging library, that will allow you to create log files for your programs. On BranchManager when branching a module for example I would log the time before, after opening the module, the time for creating the objects, the time for copying the attribute values, the time for creating the links, etc. This way you will have the knowledge where your program takes the most time. Then you optimize there. The first thing you look for is logic errors. This is where you save the most time. Opening and Closing modules to often, repeating expensive calculations that could be cached, etc. All DXL programs that handle large strings or a lot of allocations need to take more care to avoid memory leaks and do correct string handling (avoid cluttering of string table and do not copy large strings to often). Only sometimes when you have functions that are called very often (e.g. string replace, or something) then going into the detailed performance of the basic DXL operations is relevant. This is a science of its own - I did a lot of profiling for the basic operations of DXL and compared how long does a function call take compared with an assignment, etc. When you are interested, I can make a tutorial about profiling DXL. Regards, Mathias |
Re: Buffer Get and Release Mathias Mamsch - Thu Aug 18 04:59:24 EDT 2011
Oh and by the way: ModuleVersions (sourceVersion, targetVersion, moduleVersion, ...) all those perms ARE allocated objects and need to be deleted by the delete(ModuleVersion) perm. You can test for yourself:
int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
int *getCurrentDXLContextPtr () {
DB x = create ""
int *ptr = addr_ x
int *result = ptr @ 48
destroy x
return result
}
int *getMemoryBlockNodes (int *cc) { return cc @ 0x74 }
int *nextNode (int *memNode) { return memNode @ 8 }
int countAllocatedObjects() {
int *memBlocks = getMemoryBlockNodes getCurrentDXLContextPtr()
int count = 0
while (!null memBlocks) {
memBlocks = nextNode memBlocks
count++
}
return count
}
// comment me in to see the object counts increase;
// Skip sk = create(); Buffer buf = create()
print "Allocated Objects Before doing stuff:" countAllocatedObjects() "\n"
if (null current) error "Please open a module for this test!"
ModuleVersion mod = moduleVersion current
print "Allocated Objects with one moduleVersion:" countAllocatedObjects() "\n"
ModuleVersion mod2 = moduleVersion current
print "Allocated Objects with two moduleVersions:" countAllocatedObjects() "\n"
delete mod; delete mod2
print "Allocated Objects after deletions:" countAllocatedObjects() "\n"
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
Dear Mathias,
Is this code for countAllocatedObjects() supposed to work with DOORS 9.6.1.6? On my PC it results in an exception.
Regards, Gustavo
DOORS: **** Translating a structured exception ****
DOORS: Version 9.6.1.6, build number 96451, built on Mar 23 2016 22:04:27.
DOORS: Microsoft Windows 7
DOORS: DOORS: 64 percent of memory is in use.
DOORS: There are 8302096 total Kbytes of physical memory.
DOORS: There are 2946524 free Kbytes of physical memory.
DOORS: There are 16602332 total Kbytes of paging file.
DOORS: There are 9938340 free Kbytes of paging file.
DOORS: There are ffffff80 total Kbytes of virtual memory.
DOORS: There are ffc5816c free Kbytes of virtual memory.
DOORS: argv[0]: C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe
DOORS: argv[1]: -d
DOORS: argv[2]: <REMOVED>
DOORS: Exception timestamp: 09/11/2016 at 16:16:15
DOORS: doors.exe caused an EXCEPTION_ACCESS_VIOLATION in module doors.exe at 0000000041000058
DOORS: 0x00000141000058 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x00000141006db0 doors.exe
0x000001410008f2 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x0000014100445d doors.exe
0x000001410040f2 doors.exe
0x00000141003f48 doors.exe
0x000001410084d6 doors.exe
0x0000014100b64e doors.exe
0x00000140151cef doors.exe
0x000001402adf8e doors.exe
0x00000140b3660f doors.exe
0x00000140b34c8d doors.exe
0x00000140b2b785 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077196a9c USER32.dll, SetTimer()+00000364 byte(s)
0x00000077196ba1 USER32.dll, SendMessageW()+00000093 byte(s)
0x0007fefb340c73 COMCTL32.dll, TaskDialog()+00205139 byte(s)
0x0007fefb3448b2 COMCTL32.dll, TaskDialog()+00220562 byte(s)
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077193ba4 USER32.dll, CallWindowProcW()+00000156 byte(s)
0x00000077193b20 USER32.dll, CallWindowProcW()+00000024 byte(s)
0x00000140b3aa7d doors.exe
0x00000140b3aad6 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x000000771998e2 USER32.dll, TranslateMessage()+00000482 byte(s)
0x00000140b23d56 doors.exe
0x0000013fd93305 doors.exe
0x0000013fd7d962 doors.exe
0x0000013fd7e081 doors.exe
0x000000772959cd kernel32.dll, BaseThreadInitThunk()+00000013 byte(s)
0x000000773ca2e1 ntdll.dll, RtlUserThreadStart()+00000033 byte(s)
DOORS: **** end of event ****
DOORS: Writing exception details...
DOORS: Exception details have been written to: C:\Users\delfinog\AppData\Local\Temp\DOORS-96451-2016_11_09-16_16_15-1292-4964.dmp
DOORS: **** Translating a structured exception ****
DOORS: Version 9.6.1.6, build number 96451, built on Mar 23 2016 22:04:27.
DOORS: Microsoft Windows 7
DOORS: DOORS: 64 percent of memory is in use.
DOORS: There are 8302096 total Kbytes of physical memory.
DOORS: There are 2934264 free Kbytes of physical memory.
DOORS: There are 16602332 total Kbytes of paging file.
DOORS: There are 9900316 free Kbytes of paging file.
DOORS: There are ffffff80 total Kbytes of virtual memory.
DOORS: There are ffc5aedc free Kbytes of virtual memory.
DOORS: argv[0]: C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe
DOORS: argv[1]: -d
DOORS: argv[2]: <REMOVED>
DOORS: Exception timestamp: 09/11/2016 at 16:18:34
DOORS: doors.exe caused an EXCEPTION_ACCESS_VIOLATION in module doors.exe at 0000000041000058
DOORS: 0x00000141000058 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x00000141006db0 doors.exe
0x000001410008f2 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x0000014100445d doors.exe
0x000001410040f2 doors.exe
0x00000141003f48 doors.exe
0x000001410084d6 doors.exe
0x0000014100b64e doors.exe
0x00000140151cef doors.exe
0x000001402adf8e doors.exe
0x00000140b3660f doors.exe
0x00000140b34c8d doors.exe
0x00000140b2b785 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077196a9c USER32.dll, SetTimer()+00000364 byte(s)
0x00000077196ba1 USER32.dll, SendMessageW()+00000093 byte(s)
0x0007fefb340c73 COMCTL32.dll, TaskDialog()+00205139 byte(s)
0x0007fefb3448b2 COMCTL32.dll, TaskDialog()+00220562 byte(s)
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077193ba4 USER32.dll, CallWindowProcW()+00000156 byte(s)
0x00000077193b20 USER32.dll, CallWindowProcW()+00000024 byte(s)
0x00000140b3aa7d doors.exe
0x00000140b3aad6 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x000000771998e2 USER32.dll, TranslateMessage()+00000482 byte(s)
0x00000140b23d56 doors.exe
0x0000013fd93305 doors.exe
0x0000013fd7d962 doors.exe
0x0000013fd7e081 doors.exe
0x000000772959cd kernel32.dll, BaseThreadInitThunk()+00000013 byte(s)
0x000000773ca2e1 ntdll.dll, RtlUserThreadStart()+00000033 byte(s)
DOORS: **** end of event ****
DOORS: Writing exception details...
DOORS: Exception details have been written to: C:\Users\delfinog\AppData\Local\Temp\DOORS-96451-2016_11_09-16_18_34-1292-4964.dmp
|
Re: Buffer Get and Release Gustavo Delfino - Wed Nov 09 16:24:10 EST 2016 Dear Mathias,
Is this code for countAllocatedObjects() supposed to work with DOORS 9.6.1.6? On my PC it results in an exception.
Regards, Gustavo
DOORS: **** Translating a structured exception ****
DOORS: Version 9.6.1.6, build number 96451, built on Mar 23 2016 22:04:27.
DOORS: Microsoft Windows 7
DOORS: DOORS: 64 percent of memory is in use.
DOORS: There are 8302096 total Kbytes of physical memory.
DOORS: There are 2946524 free Kbytes of physical memory.
DOORS: There are 16602332 total Kbytes of paging file.
DOORS: There are 9938340 free Kbytes of paging file.
DOORS: There are ffffff80 total Kbytes of virtual memory.
DOORS: There are ffc5816c free Kbytes of virtual memory.
DOORS: argv[0]: C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe
DOORS: argv[1]: -d
DOORS: argv[2]: <REMOVED>
DOORS: Exception timestamp: 09/11/2016 at 16:16:15
DOORS: doors.exe caused an EXCEPTION_ACCESS_VIOLATION in module doors.exe at 0000000041000058
DOORS: 0x00000141000058 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x00000141006db0 doors.exe
0x000001410008f2 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x0000014100445d doors.exe
0x000001410040f2 doors.exe
0x00000141003f48 doors.exe
0x000001410084d6 doors.exe
0x0000014100b64e doors.exe
0x00000140151cef doors.exe
0x000001402adf8e doors.exe
0x00000140b3660f doors.exe
0x00000140b34c8d doors.exe
0x00000140b2b785 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077196a9c USER32.dll, SetTimer()+00000364 byte(s)
0x00000077196ba1 USER32.dll, SendMessageW()+00000093 byte(s)
0x0007fefb340c73 COMCTL32.dll, TaskDialog()+00205139 byte(s)
0x0007fefb3448b2 COMCTL32.dll, TaskDialog()+00220562 byte(s)
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077193ba4 USER32.dll, CallWindowProcW()+00000156 byte(s)
0x00000077193b20 USER32.dll, CallWindowProcW()+00000024 byte(s)
0x00000140b3aa7d doors.exe
0x00000140b3aad6 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x000000771998e2 USER32.dll, TranslateMessage()+00000482 byte(s)
0x00000140b23d56 doors.exe
0x0000013fd93305 doors.exe
0x0000013fd7d962 doors.exe
0x0000013fd7e081 doors.exe
0x000000772959cd kernel32.dll, BaseThreadInitThunk()+00000013 byte(s)
0x000000773ca2e1 ntdll.dll, RtlUserThreadStart()+00000033 byte(s)
DOORS: **** end of event ****
DOORS: Writing exception details...
DOORS: Exception details have been written to: C:\Users\delfinog\AppData\Local\Temp\DOORS-96451-2016_11_09-16_16_15-1292-4964.dmp
DOORS: **** Translating a structured exception ****
DOORS: Version 9.6.1.6, build number 96451, built on Mar 23 2016 22:04:27.
DOORS: Microsoft Windows 7
DOORS: DOORS: 64 percent of memory is in use.
DOORS: There are 8302096 total Kbytes of physical memory.
DOORS: There are 2934264 free Kbytes of physical memory.
DOORS: There are 16602332 total Kbytes of paging file.
DOORS: There are 9900316 free Kbytes of paging file.
DOORS: There are ffffff80 total Kbytes of virtual memory.
DOORS: There are ffc5aedc free Kbytes of virtual memory.
DOORS: argv[0]: C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe
DOORS: argv[1]: -d
DOORS: argv[2]: <REMOVED>
DOORS: Exception timestamp: 09/11/2016 at 16:18:34
DOORS: doors.exe caused an EXCEPTION_ACCESS_VIOLATION in module doors.exe at 0000000041000058
DOORS: 0x00000141000058 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x00000141006db0 doors.exe
0x000001410008f2 doors.exe
0x000001410012cc doors.exe
0x000001410008f2 doors.exe
0x0000014100445d doors.exe
0x000001410040f2 doors.exe
0x00000141003f48 doors.exe
0x000001410084d6 doors.exe
0x0000014100b64e doors.exe
0x00000140151cef doors.exe
0x000001402adf8e doors.exe
0x00000140b3660f doors.exe
0x00000140b34c8d doors.exe
0x00000140b2b785 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077196a9c USER32.dll, SetTimer()+00000364 byte(s)
0x00000077196ba1 USER32.dll, SendMessageW()+00000093 byte(s)
0x0007fefb340c73 COMCTL32.dll, TaskDialog()+00205139 byte(s)
0x0007fefb3448b2 COMCTL32.dll, TaskDialog()+00220562 byte(s)
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x00000077193ba4 USER32.dll, CallWindowProcW()+00000156 byte(s)
0x00000077193b20 USER32.dll, CallWindowProcW()+00000024 byte(s)
0x00000140b3aa7d doors.exe
0x00000140b3aad6 doors.exe
0x00000077199bdd USER32.dll, TranslateMessageEx()+00000669 byte(s)
0x000000771998e2 USER32.dll, TranslateMessage()+00000482 byte(s)
0x00000140b23d56 doors.exe
0x0000013fd93305 doors.exe
0x0000013fd7d962 doors.exe
0x0000013fd7e081 doors.exe
0x000000772959cd kernel32.dll, BaseThreadInitThunk()+00000013 byte(s)
0x000000773ca2e1 ntdll.dll, RtlUserThreadStart()+00000033 byte(s)
DOORS: **** end of event ****
DOORS: Writing exception details...
DOORS: Exception details have been written to: C:\Users\delfinog\AppData\Local\Temp\DOORS-96451-2016_11_09-16_18_34-1292-4964.dmp
Under DOORS 9.6.x 32 Bit probably. Under 64 Bit the code does not work anymore. Please read my post on 64 Bit memory management to find out why and how compatibility can be achieved. I am sure, someone adapted the code already for 64 bit. If someone could post the modified code, that would be nice. Regards, Mathias |