Opened 4 years ago
Last modified 3 years ago
#6429 new defect
[MM] Add listFlatten and listFlattenReverse in C for more performance
Reported by: | Adrian Pop | Owned by: | Martin Sjölund |
---|---|---|---|
Priority: | high | Milestone: | |
Component: | MetaModelica | Version: | 1.18.0-dev |
Keywords: | Cc: | Per Östlund |
Description
Currently List.flatten is implmeneted as:
listAppend(lst for lst in listReverse(inList))
which has rather bad performance (time and memory wise).
Implement this in C.
Change History (9)
comment:1 by , 4 years ago
Cc: | added |
---|---|
Version: | 1.16.2 → 1.18.0-dev |
comment:2 by , 4 years ago
comment:3 by , 4 years ago
If you have 20 lists it will create 19 lists in the process via each listAppend.
If you do it in C you will create one.
comment:4 by , 4 years ago
No, it will only create 1 list:
while(1) { tmp1 = 1; if (!listEmpty(_lst_loopVar)) { _lst = MMC_CAR(_lst_loopVar); _lst_loopVar = MMC_CDR(_lst_loopVar); tmp1--; } if (tmp1 == 0) { __omcQ_24tmpVar54 = _lst; __omcQ_24tmpVar55 = listAppend(__omcQ_24tmpVar54, __omcQ_24tmpVar55); } else if (tmp1 == 1) { break; } else { MMC_THROW_INTERNAL(); } }
listAppend only allocates memory for the first argument; the second argument is kept verbatim.
comment:5 by , 4 years ago
Then we thought wrong, I thought it would be like one listAppend for each 2 elements in the list of lists, yes the second one is kept intact but on the next iteration it would be copied also.
comment:6 by , 4 years ago
No, is actually like I said, you lose a lot of memory on this. In C you would allocate once based on the length of the lists and then just copy the elements of all the lists except the last one.
comment:7 by , 4 years ago
It's going to be the same with just listAppend :)
listAppend({a},listAppend({b},{c}));
Would allocate a cell for b to create tmp=b::{c} (the original c).
And then allocate a cell for a to create tmp2=c::tmp.
The difference is the overhead of allocations in libgc. But I don't think this is a huge difference in memory cost. You get some locality though (and you won't collect any part of the list until none of it is used).
comment:8 by , 4 years ago
Of course, it will not allocate each element since listAppend already does the listLength thing internally (compared to manually creating the list using ::
in MetaModelica).
Is it really that bad? You need to create the full list anyway, and it's performing only the listReverse more than the necessary number?