Java与C版相同的算法

时间:2012-05-02 10:02:52

标签: java c performance

我在Java中实现了一个程序,对于特定的测试用例,这个程序令人惊讶地占用了177M内存(我没有,因为程序是由一个网站测试的)。

问题是找出字符串S2中存在于字符串S1中的所有字符。还有N个这样的案例。

public static void main(String[] args) throws Exception {
    BufferedReader bin = new BufferedReader (new InputStreamReader (System.in));
    String jewel, stone;
    int t = Integer.parseInt (bin.readLine());
    int count;
    int i;

    while (t-->0) {
        count = 0;
        jewel = bin.readLine();
        stone = bin.readLine();
        for (i=0; i<stone.length(); i++) {
            if (jewel.indexOf(stone.charAt(i)) !=-1) {
                count++;
            }
        }
        System.out.println(count);
    }
}

我也不明白,它是如何服用177M的ram。即使他们正在测试一个巨大的文件,那么也只有2个字符串。但是代码完全正常,测试用例通过了。

由于java程序占用了大量内存,所以我打算写一个相同程序的C版本。以下是:

int main ()
{
  char * pch;
    char jewel[100], stone[100];
    int n;
    scanf("%d",&n);
    int len;    
    int tp;
    int count = 0;
    getchar(); // remove trailing '\n'
    while (n-->0) {

        gets(jewel);
        pch = gets(stone);
        count = 0;

        while(*pch ) {
            if (strchr(jewel, *pch)) {
                count++;
            }
            pch++;
        }
        printf("%d\n", count);
    }
  return 0;
}

在现有的几个案例中,它正在发挥作用。程序似乎也是正确的。但我无法理解为什么它正确传递所有测试用例。

所有字符串缓冲区都足以容纳传入的字符串,这些字符串由新行分隔。

编辑:""+stone.charAt(i))更改为stone.charAt(i))没有任何帮助,并且占用了相同数量的内存。 为什么这个C代码无法通过所有测试用例

2 个答案:

答案 0 :(得分:10)

""+stone.charAt(i)创建一个短暂的字符串对象。这占用了少量内存,最终将被垃圾收集器[*]释放。

另一方面,您的C代码根本不分配任何内存。

Java的垃圾收集器在需要之前不一定能够正常工作。如果你的程序有超过177MB的可用内存,并且该程序通过创建177MB的短期对象来生成,那么就这样吧。如果你开始耗尽内存,或者垃圾收集器注意到它可能正在运行的空闲时间,那么它将释放一些内存。因此,您的程序的内存使用可能会增长到适合可用的内容。

或者,即使仍有可用内存,GC也可能会运行。如果GC被强制运行(例如)每10MB的分配,那么你期望这段代码的内存使用大约为10MB,所以我想在这种情况下它没有。在另一个JVM上也许会。

[*] Java实现可以执行理论优化,注意到没有对该对象的引用转义循环,然后以不同方式分配/释放它以避免搅动GC。我猜这种情况并没有发生,但值得知道的是,不同的JVM或具有不同选项的相同JVM可能具有非常不同的垃圾收集策略。

答案 1 :(得分:2)

Java代码创建缓冲读取器和输入流读取器。这两个都保证使用大块内存,在垃圾收集器运行之前不会被释放(这可能直到程序退出!)。

jewel = bin.readLine();

在java中,每次调用.readline都会在堆上创建一个新字符串,该赋值会将前一个字符串标记为'free-able',但它会在内存中挂起,直到GC消除掉它。

C在内存管理方面做的很少。可能分配一块内存的唯一行是gets,但这可能只是使用控制台输入缓冲区,它不计入程序内存使用情况。

我认为你正在比较苹果和橙子来制作果汁。重写C代码以使用垃圾收集和缓冲读取类,您可能有一个等效的程序。