/* author: ncomputers.org */
#include<cstdlib>
#include<iostream>
using namespace std;
void*operator new[](size_t s){
return malloc(s);
}
void operator delete[](void*p){
free(p);
}
void operator delete[](void*p,size_t s){
//It doesn't support objects with destructor.
if(realloc(p,s)!=p)throw 0;
}
int main(){
typedef int A;
A*a=new A[100];
//Suggested syntax:
//delete[90]a;
operator delete[](a,10*sizeof(A));
delete[]a;
return 0;
}
Best regards,
http://ncomputers.org
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
The performance offered by the std::vector when shrinking could be overcome by own implementations or native arrays.
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??
#include<cstdlib>
#include<stdio.h>
#include<iostream>
using namespace std;
void*operator new[](size_t s){
return malloc(s);
}
void operator delete[](void*p){
free(p);
}
void operator delete[](void*p,size_t s){
if(realloc(p,s)!=p)throw 0;
}
int main(){
unsigned s=1024,S=1024*1024*1024;
char*a=new char[S]();
cout<<S<<" bytes allocated and initialized, press any key to shrink array to "<<s<<" bytes"<<endl;
getchar();
operator delete[](a,s);
cout<<"Array shrunk to "<<s<<" bytes, press any key to delete it"<<endl;
getchar();
delete[]a;
return 0;
}
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??
Because the number of vectors or arrays used by the code by one of our codes is undefined. It can vary with the time. The first second can be only 1, then 10, then 1,000, then 10, and so on.
#include<iostream>
#include<vector>
using namespace std;
struct A{
A(){
cout<<"constructor"<<endl;
}
~A(){
cout<<"detructor"<<endl;
}
};
int main(){
delete new vector<A>(5);
}
#include<iostream>
#include<vector>
using namespace std;
int main(){
try{
unsigned S=1024;
vector<int>a(S);
for(unsigned s=S-1;s>0;--s){
int*b=&a[0];
cout<<b<<endl;
a.resize(s);
a.shrink_to_fit();
int*c=&a[0];
cout<<c<<endl;
if(b!=c){
throw "Data moved!";
}
}
cout<<"Data never moved"<<endl;
}
catch(char const*const& e){
cout<<e<<endl;
}
return 0;
}
#include<cstdlib>
#include<iostream>
using namespace std;
int main(){
try{
unsigned S=1024;
int*a=(int*)malloc(S*sizeof(int));
for(unsigned s=S-1;s>0;--s){
int*b=&a[0];
cout<<b<<endl;
a=(int*)realloc(a,s*sizeof(int));
int*c=&a[0];
cout<<c<<endl;
if(b!=c){
throw "Data moved!";
}
}
free(a);
cout<<"Data never moved"<<endl;
}
catch(char const*const& e){
cout<<e<<endl;
}
return 0;
}
- The amount of vectors that the code will use is undefine during compile time.
because it usualy moves the data,
I've tested realloc with glibc and it never moved the data.
If all you are doing is using POD types (such as int), why not just use realloc and be done with it?--
realloc is a horrible interface that only works for things with trivial copy constructors. To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it, which would be a much bigger proposal than n3495.
So why not use a vector of vectors?
To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it,
No; it bitwise copies the data.
Well, yeah, because you do exactly *one* heap allocation in your program and then shrink the space; shrinking never has to move anything. Not exactly a realistic test for most programs...
If all you are doing is using POD types (such as int), why not just use realloc and be done with it?
void*operator new[](size_t s){
return malloc(s);
}
void operator delete[](void*p){
free(p);
}
void operator delete[](void*p,size_t s){
//It doesn't support objects with destructor.
if(realloc(p,s)!=p)throw 0;
}
To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it, which would be a much bigger proposal than n3495.
which would be a much bigger proposal than n3495.
may require replacing the entire malloc implementation to support it
I’d think the functionality could be sliced off any existing malloc.
There should be a generic interface for resizing allocations simply for the sake of custom allocators. If it’s something that many can do, then it should be represented by the common interface.
N3495 looks completely different from the one proposal I recall with a C++ adaptation of realloc, which also had issues.
Maybe I’ll take a shot at it one day :P . But N3495 does hit most of the right notes.
Thank you very much for your time and your answer!
I didn't understand exactly what you wrote:I’d think the functionality could be sliced off any existing malloc.
I didn't understand this:N3495 looks completely different from the one proposal I recall with a C++ adaptation of realloc, which also had issues.
Which porposal is "C++ adaptation of realloc"?
What did you want to express?
it shouldn’t be a big deal when a platform doesn’t support it.
There have been several, but I’m not digging for the others right now.
//Awaiting shrinkable arrays:
delete [oldSize - newSize] pointer;
C++ adaptation of realloc
Nevin said that resizing malloc allocations would require a rewrite of malloc. I think that it would not be a total rewrite, but only an adaptation of code that should already exist for realloc. And anyway, it shouldn’t be a big deal when a platform doesn’t support it.
I understand it. So far my experience says, it is easier to propose something new, than that the proposals become accepted. We're excepting that it could even require more than ten years,
that the std::allocator become standardized to allow in-place resizing.
Unfortunately we don't have neither the necessary experience nor the time to write a paper,
But malloc is typically in the domain of C and the OS. On some systems for instance, you can intercept the malloc calls and replace them. It is not trivial to add a reallocate-in-place facility that remains compatible with all these real world malloc implementations.
To properly take advantage of this, you need to change vector, allocators and malloc. Now, given that most programs interleave allocations made in different objects (think about a vector<string>, for instance), you then have to benchmark your implementation to show under what circumstances it is a clear win for adding all this complexity.
You can get phenomenal performance by tuning a program to use a few string arenas without interleaving. The bytes recovered by an eager shrink-to-fit operation on the last allocation are going to be in L1 cache, and they’re the next to get allocated.
How much improvement to everyday programs, when shrink-to-fit is enabled with malloc? Maybe not much. But that’s only one side of the argument. It’s still worthwhile to enable better performance in fast allocators with proper support. Right now, the allocator gets coupled unnecessarily to the algorithm because this one generic interface is missing.
On 18 October 2014 01:41, David Krauss <pot...@gmail.com> wrote:You can get phenomenal performance by tuning a program to use a few string arenas without interleaving. The bytes recovered by an eager shrink-to-fit operation on the last allocation are going to be in L1 cache, and they’re the next to get allocated.Oh, sure.How much improvement to everyday programs, when shrink-to-fit is enabled with malloc? Maybe not much. But that’s only one side of the argument. It’s still worthwhile to enable better performance in fast allocators with proper support. Right now, the allocator gets coupled unnecessarily to the algorithm because this one generic interface is missing.You cannot say it is worthwhile until you've actually measured it.
All I'm saying is that it is a lot of work to do to get it to a point where a proposal has a decent chance of succeeding (IMHO). If you are volunteering to do it, I say go for it!
That’s why my suggestion is to focus on the generic Allocator concept, not on std::allocator.
It’s still worthwhile to enable better performance in fast allocators with proper support.
David,That’s why my suggestion is to focus on the generic Allocator concept, not on std::allocator.
Is std::allocator the responsable of allocate memory with the new operator? Or is the "generic allocator" that you mention?
May I know better how would this interface be?
It’s still worthwhile to enable better performance in fast allocators with proper support.
I agree with you. I think that, fast allocators search better performance.
Hopefully someone else will attempt, they’ll post here first, and I’ll influence them not to be too ambitious or specific but to prioritize the essentials.
std::allocator calls (specifically) ::operator new calls (in practice) malloc.
Custom allocators improve performance at a huge cost in convenience :/ . As I mentioned to Nevin, my take on this issue isn’t really about improving performance of existing programs, but to improve portability and modularity of certain program architectures. Maybe even help bring high-performance libraries to the masses, but still, porting a program to use custom allocators is a major hurdle which isn’t going away.
std::allocator calls (specifically) ::operator new calls (in practice) malloc.
delete (argument) [] pointer;
We're trying to overload the delete[] operator to achieve shrinkable oriented to objects arrays.
It works fine with data types without specific destructor.
When the data type has a specified destructor, the new[] operator needs extra bytes.
Could you help us please to answer these questions?
- Why does the new[] operator require extra bytes for data types with specific destructor?
- Will always the new[] operator request these bytes or is it library dependent?
- Is it possible to know if the data type has a specific destructor with an if statement?
The code should throw an unhandled exception when it tries to shrink the array of B's.
#include<cstdlib>
#include<iostream>
using namespace std;
void*operator new[](size_t s){
cout<<"Block size: "<<s<<endl;
return malloc(s);
}
void operator delete[](void*p){
free(p);
}
void operator delete[](void*p,size_t s){
//Is it possible to know if the data type has a specific destructor?
bool destructor=0;
if(destructor){
p=(char*)p-8,s+=8;
}
cout<<"New block size: "<<s<<endl;
if(realloc(p,s)!=p)throw 0;
}
struct A{
char a;
A():a(0){}
~A()=default;
};
struct B{
char b;
B():b(0){}
~B(){}
};
int main(){
unsigned S=10,s=4;
cout<<"Creating "<<S<<" A's"<<endl;
A*a=new A[S];
cout<<"Creating "<<S<<" B's"<<endl;
B*b=new B[S];
cout<<"Shrinking A to "<<s<<" elements"<<endl;
operator delete[](a,sizeof(A)*s);
cout<<"Shrinking B to "<<s<<" elements"<<endl;
operator delete[](b,sizeof(B)*s);
cout<<"Deleting A and B"<<endl;
delete[]b,delete[]a;
return 0;
}
Someday when you get the opportunity to refactor/optimize your personal lib, a good proposal becomes possible. It takes more time but less risk.
delete (argument)[] pointer
like its counterpart new (argument)[size]
?I am trying to have an overloaded delete[] operator that accepts specific arguments. Because the only way to call a delete[] operator with specific arguments is explicitly, it loses the support for objects with destructor. I've almost achieved personal shrinkable arrays. This is the last complication I have. Do you have any idea of how can we enable a sugar syntactic call to an overloaded delete[] operator with specific arguments:delete (argument)[] pointer
like its counterpartnew (argument)[size]
?
take a look into the implementation of std::vector and std::allocator
I should find a way of dropping that affirmative tone from my tongue(hand????), and make more use of 'plz' and 'one might'.