C ++ vs Java“new” (请不要发生火焰战!) [英] C++ vs Java "new" (no flame war please!)

查看:61
本文介绍了C ++ vs Java“new” (请不要发生火焰战!)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不要对此采取任何措施,它不是火焰或巨魔,而我不是新的Java我喜欢C ++。但是,我可能需要在合同

位置使用它,并担心它对应用程序的限制

代码。


以这个C ++构造为例:


class foo

{

char * m_name;

....

void * operator new(size_t size,char * string);

}

void * foo :: new(size_t size,char * string)

{

size_t cbstr = strlen(string)+1;

size_t cb = cbstr + size;

foo * t =(foo *)malloc(cb);

char * name =(char *)& t [1];

strcpy(name,string);

t-> m_name = name;

}


上面的示例是一种方法,可用于减少CPU和malloc的内存开销。你我认为这不是一个有效的问题,

但是如果你有10或1亿个对象,那么malloc块开销,单独使用
就可以了。提示:这实际上是一个简化,有些

次malloc根本就没用过,而且一个大阵列是预先分配好的,并且通过它每个新的工作
。 br />
有没有办法用合理的

系统配置在Java中创建10到1亿个对象?

解决方案

mlw写道:


(自定义''new''运算符的剪断描述)


有没有办法用合理的

系统配置在Java中创建10到1亿个对象?



当然,考虑到可用堆的相同考虑因素,你将在C ++世界中获得。


假设您要创建N个对象,其中N是最大数量的

这样的对象,这些对象适合可用内存。


List< Foostuff = new ArrayList< Foo(N);

for(int x = 0; x< N; ++ x)

{

stuff.add(new Foo(getAString()));

}

doSomethingWith(stuff);


如果你不是一次都需要它们,那就更容易了:


for(int x = 0; x< N; ++ x)

{

Foo foo = new Foo(getAString());

doSomethingWith(foo);

}


我假设''getAString()''方法,你将获得相当于

''char * string'的方法'在C ++示例中。我假设你会为每个Foo实例使用不同的字符串




- Lew

Lew写道:


mlw写道:


(剪切描述自定义''新''运算符)


>有没有办法用合理的系统配置在Java中创建10到1亿个对象?



当然,考虑到可用堆的相同考虑,你将在C ++世界中拥有




我猜是给予还是接受。


>

让's假设你想要创建N个对象,其中N是最大数量的

这样的对象,它们适合可用的内存。


列表< Foostuff = new ArrayList< Foo(N);



这是一个内存分配,当然。


for(int x = 0; x < N; ++ x)

{

stuff.add(new Foo(getAString()));

}



上面的代码正是我的Java问题。在C ++中,我可以重载新的
并将所有对象放在我想要的任何地方,甚至连接到一个连续的内存中。

块只调用一次malloc并将对象和字符串组合在一起

一次分配,例如:


(记住这是一个简化,例如用途,但技术

是重要的事情。)


unsigned char * myshared_block = shared_alloc(MAX_SIZE)

size_t curr_offset = 0;


void * foo :: operator new(size_t size,char * str)

{

size_t cbstr = strlen(str)+1;

size_t cb = size + cbstr;


foo * fooT =(foo *)& myshared_block [curr_offset];

curr_offset + = cb;

char * pstr =(char *)& foo [1];

strcpy(pstr,str);

fooT-> str = pstr;

return(void *)fooT;

}


在上面的代码中,我可以预先分配一个内存块并拉出物品

out o直到它为空。


每个内存分配都有开销,在GCC malloc中,它可能是4个字节,在64位系统上是
8个字节。所以,如果你有相当小的对象,并且它们很多,那么很多内存都会被malloc开销吞噬掉。如果

你有一个带有字符串的小对象,你将有两个内存

分配!


显然这是一个罕见的问题,但这是一个问题。


doSomethingWith(stuff);


>

如果你不是一次都需要它们,那就更容易了:


for(int x = 0; x< N; ++ x)

{

Foo foo = new Foo(getAString());

doSomethingWith(foo);

}


我假设''getAString()' '在C ++示例中,您将获得等同于''char * string''的方法。我假设你会为每个Foo实例使用不同的

字符串。



Lew写道:


>让我们假设您要创建N个对象,其中N是适合可用内存的最大数量的对象。

List< Foostuff = new ArrayList< FOO(N);



mlw写道:


这是一个内存分配,当然。



Lew写道:


> for(int x = 0; x< N; ++ x)
{
stuff.add(new Foo(getAString()));
}



mlw写道:


以上代码正是我的Java问题。在C ++中,我可以重载新的
并将所有对象放在我想要的任何地方,甚至连接到一个连续的内存中。

块只调用一次malloc并将对象和字符串组合在一起

一次分配,



您仍然需要计算该块的偏移量来修复每个的开始

个人对象。实际上,自定义分配器中的代码使用的内存比使用等效Java类的JVM要多得多。


每个内存分配都有开销,在GCC malloc中,它可能是4个字节,在64位系统上是
8个字节。所以,如果你有相当小的对象,并且它们很多,那么很多内存都会被malloc开销吞噬掉。如果

你有一个带有字符串的小对象,你将有两个内存

分配!



你的C ++类做了一个字符串的副本。一个Java类可能不会,因为

字符串是不可变的,所以它只会为Foo对象分配一个分配

而没有字符串分配。即使有人复制了字符串,Java分配和复制的时间开销也会比你b $ b显示的C ++代码少得多。首先,Java代码只会循环遍历String一次,

不会是C ++代码的两倍;它不需要计算strlen()。

内存开销也没有什么不同,因为副本是副本是副本。


但正如我所说,Java代码不会复制字符串,所以重点是没有意义。

Java版本中的一个分配和更少的内存开销。


显然这是一个罕见的问题,但这也是一个问题。



我不知道Java的问题是什么。

对Java有什么不好的影响?


内存开销是多少? Java中的对象只占用了它们所占用的空间。


这是时间开销吗? Java对象分配的运行周期为10-20

机器周期。对象的初始化可能需要一些时间,但是

对于您的自定义分配器也是如此。


您的描述似乎描述了一个问题您的自定义

分配器处理的C ++,但我认为这与Java无关。


- Lew


Do not take anything about this, it is not a flame or troll, while I''m not
new to Java I favor C++. However, I may need to use it in a contract
position, and am concerned that the restrictions it places on application
code.

Take, for instance, this C++ construct:

class foo
{
char *m_name;
....
void * operator new(size_t size, char *string);
}
void *foo::new(size_t size, char *string)
{
size_t cbstr = strlen(string)+1;
size_t cb = cbstr + size;
foo * t = (foo *) malloc(cb);
char * name = (char *) &t[1];
strcpy(name, string);
t->m_name = name;
}

The above example is a methodology that can be used to reduce the CPU and
memory overhead of malloc. You my argue that this is not a valid concern,
but if you have 10 or 100 million objects, the malloc block overhead,
alone, make this worth while. Hint: This is actually a simplification, some
times malloc is not used at all, and a big array is pre-alocated and work
through it with each new.
Is there a way to create 10 to 100 million objects in Java with a reasonable
system configuration?

解决方案

mlw wrote:

(snipped description of custom ''new'' operator)

Is there a way to create 10 to 100 million objects in Java with a reasonable
system configuration?

Sure, given the same considerations of available heap that you would have in
the C++ world.

Let''s assume you want to create N objects where N is the largest number of
such objects that would fit in available memory.

List <Foostuff = new ArrayList <Foo(N);
for ( int x = 0; x < N; ++x )
{
stuff.add( new Foo( getAString() ) );
}
doSomethingWith( stuff );

If you don''t need them all in memory at once, it''s even easier:

for ( int x = 0; x < N; ++x )
{
Foo foo = new Foo( getAString() );
doSomethingWith( foo );
}

I posit the ''getAString()'' method as where you''d obtain the equivalent of the
''char * string'' in the C++ example. I assumed you''d use a different string for
each instance of Foo.

-- Lew


Lew wrote:

mlw wrote:

(snipped description of custom ''new'' operator)

>Is there a way to create 10 to 100 million objects in Java with a
reasonable system configuration?


Sure, given the same considerations of available heap that you would have
in the C++ world.

Give or take, I guess.

>
Let''s assume you want to create N objects where N is the largest number of
such objects that would fit in available memory.

List <Foostuff = new ArrayList <Foo(N);

That''s one memory alloc, sure.

for ( int x = 0; x < N; ++x )
{
stuff.add( new Foo( getAString() ) );
}

The above code is exactly my problem with Java. In C++ I can overload new
and put all the objects anywhere I want, even in to one contiguous memory
block calling malloc merely once and combining the object and the string in
one allocation, for instance:

(Remember this is a simplification for example purposes, but the technique
is the important thing.)

unsigned char * myshared_block = shared_alloc(MAX_SIZE)
size_t curr_offset=0;

void *foo::operator new(size_t size, char * str)
{
size_t cbstr = strlen(str)+1;
size_t cb = size + cbstr;

foo * fooT = (foo *) &myshared_block[curr_offset];
curr_offset += cb;
char *pstr = (char *)&foo[1];
strcpy(pstr, str);
fooT->str = pstr;
return (void *) fooT;
}

In the above code, I can pre-allocate a single memory block and pull objects
out of it until it is empty.

Every memory allocation has overhead, in GCC malloc, it is probably 4 bytes,
8 bytes on 64 bit systems. So, if you have fairly small objects, and lots
of them, a good chunk of memory will be eaten up with malloc overhead. If
you have a small object with a string, you will have two memory
allocations!

Obviously this is a rare problem, but it is a problem none the less.

doSomethingWith( stuff );

>
If you don''t need them all in memory at once, it''s even easier:

for ( int x = 0; x < N; ++x )
{
Foo foo = new Foo( getAString() );
doSomethingWith( foo );
}

I posit the ''getAString()'' method as where you''d obtain the equivalent of
the ''char * string'' in the C++ example. I assumed you''d use a different
string for each instance of Foo.



Lew wrote:

>Let''s assume you want to create N objects where N is the largest number of
such objects that would fit in available memory.

List <Foostuff = new ArrayList <Foo(N);

mlw wrote:

That''s one memory alloc, sure.

Lew wrote:

> for ( int x = 0; x < N; ++x )
{
stuff.add( new Foo( getAString() ) );
}

mlw wrote:

The above code is exactly my problem with Java. In C++ I can overload new
and put all the objects anywhere I want, even in to one contiguous memory
block calling malloc merely once and combining the object and the string in
one allocation,

You still need to calculate offsets into that block to fix the start of each
individual object. In fact, the code in your custom allocator uses more
memory and much more time than would the JVM for the equivalent Java class.

Every memory allocation has overhead, in GCC malloc, it is probably 4 bytes,
8 bytes on 64 bit systems. So, if you have fairly small objects, and lots
of them, a good chunk of memory will be eaten up with malloc overhead. If
you have a small object with a string, you will have two memory
allocations!

Your C++ class did a copy of the string. A Java class likely would not, since
Strings are immutable, so it would only do one allocation for the Foo object
and none for the String. Even if one did copy the String, the time overhead
of the Java allocation and copy would be much less than for the C++ code you
showed. For one thing, the Java code would only loop through the String once,
not twice as in your C++ code; it would have no need to calculate "strlen()".
The memory overhead would be no different since a copy is a copy is a copy.

But as I said, the Java code would not copy the String, so the point is moot.
One allocation and less memory overhead in the Java version.

Obviously this is a rare problem, but it is a problem none the less.

I don''t see what the problem with Java is. What is the bad effect that
concerns you with Java?

Is it memory overhead? Objects in Java take up only as much space as they take.

Is it time overhead? Java object allocations run on the order of 10-20
machine cycles. Initialization of the object takes some time, perhaps, but
that would be true with your custom allocator as well.

Your description seems to delineate a problem with C++ that your custom
allocator handles, but I see nothing of this relevant to Java.

-- Lew


这篇关于C ++ vs Java“new” (请不要发生火焰战!)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆