繁体   English   中英

NSDictionary (obj-c) 和 HashMap (java) 之间的性能差异

[英]differences of performances between NSDictionary (obj-c) and HashMap (java)

我用这两种数据结构和这两种不同的语言做了一些性能测试。 结果不是我所期望的。 我认为 obj-c 程序会比 java 更快。 我的测试表明 java TreeMap 比 cocoa NSDictionary 快。 用于测试的代码是:
obj-c NSDictionary:

#import <Foundation/Foundation.h>
NSString * getRandomString();
int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary * dict = [NSMutableDictionary dictionary];
    unsigned long i;
    NSString * string1;
    NSString * string2;
    NSString * string3;
    NSString * lastString;
    //dictionary with 100'000 elements 
    srand(time(NULL));
    for (i=0;i<100000;i++){
        NSString * aString = getRandomString();
        [dict setObject:aString forKey:aString];
        if (i == 100) 
            string1 = aString;
        if (i == 1000)
            string2 = aString;
        if (i == 10000)
            string3 = aString;
        if (i == 100000-1)
            lastString = aString;
    }
    NSDate * now;

    now = [NSDate date];
    [dict objectForKey:string1];
    NSTimeInterval interval = [now timeIntervalSinceNow];
    NSLog(@"%f",interval *-1000);

    now = [NSDate date];
    [dict objectForKey:string2];
    interval = [now timeIntervalSinceNow];
    NSLog(@"%f",interval *-1000);


    now = [NSDate date];
    [dict objectForKey:string3];
    interval = [now timeIntervalSinceNow];
    NSLog(@"%f",interval *-1000);

    now = [NSDate date];
    [dict objectForKey:lastString];
    interval = [now timeIntervalSinceNow];
    NSLog(@"%f",interval *-1000);


    [pool drain];
    return 0;
}
NSString * getRandomString(){
    NSString * tmp = [NSString string];
for (int i = 0 ; i < 10;i++){
    tmp = [NSString stringWithFormat:@"%@%c",tmp,rand()%128];
}
return tmp;
}

命令行 output 是这样的:

2011-07-12 13:11:48.299 TestBench[1178:a0f] 0.008047
2011-07-12 13:11:48.302 TestBench[1178:a0f] 0.005007
2011-07-12 13:11:48.302 TestBench[1178:a0f] 0.003040
2011-07-12 13:11:48.303 TestBench[1178:a0f] 0.003994

Java 树集:

import java.util.Date;
import java.util.TreeMap;


public class Main {
    public static void main(String[] args) {
        String string1="",string2="",string3="",lastString="";
        TreeMap<String,String> map = new TreeMap<String,String>();
        for (long i=0;i<100000;i++){
            String aString = getRandomString();
            map.put(aString, aString);
            if (i == 100) 
                string1 = aString;
            if (i == 1000)
                string2 = aString;
            if (i == 10000)
                string3 = aString;
            if (i == 100000-1)
                lastString = aString;
        }
        Date start,end;

        start = new Date();
        map.get(string1);
        end = new Date();
        System.out.println(end.getTime()-start.getTime());

        start = new Date();
        map.get(string2);
        end = new Date();
        System.out.println(end.getTime()-start.getTime());

        start = new Date();
        map.get(string3);
        end = new Date();
        System.out.println(end.getTime()-start.getTime());

        start = new Date();
        map.get(lastString);
        end = new Date();
        System.out.println(end.getTime()-start.getTime());
    }
    public static String getRandomString(){
        String toRet = "";
        for (int i=0;i<10;i++){
            toRet+=(char)(Math.random()*128);
        }
        return toRet;
    }

}

命令行 output 是这样的:

0
0
0
0

对于obj-c,显然以毫秒为单位。 为什么 TreeMap 这么快? 或者...为什么 NSDictionary 这么慢? 谁能给我解释一下?? 对不起,我的英语很糟糕,非常感谢。

**添加问题* ** * ****我对代码进行了如下修改:
对象-c

#import <Foundation/Foundation.h>
NSString * getRandomString();
int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary * dict = [NSMutableDictionary dictionary];
    long int i;
    NSString * string1;
    NSString * string2;
    NSString * string3;
    NSString * lastString;
    //dictionary with 100'000 elements 
    srand(time(NULL));
    double sum = 0;
    for (int j = 0 ;j<10;j++){
        NSDate * now;
        now = [NSDate date];
        for (i=0;i<100000;i++){
            NSString * aString = getRandomString();
            [dict setObject:aString forKey:aString];
            if (i == 100) 
                string1 = aString;
            if (i == 1000)
                string2 = aString;
            if (i == 10000)
                string3 = aString;
            if (i == 100000-1)
                lastString = aString;
        }
        NSLog(@"Finished adding elements in %f ms",[now timeIntervalSinceNow]*-1000);
        now = [NSDate date];
        for (int i = 0;i<1000000;i++)
            [dict objectForKey:string1];
        for (int i = 0;i<1000000;i++)
            [dict objectForKey:string2];
        for (int i = 0;i<1000000;i++)
            [dict objectForKey:string3];
        for (int i = 0;i<1000000;i++)
            [dict objectForKey:lastString];
        NSTimeInterval interval = [now timeIntervalSinceNow];
        sum+=interval;
    }
    NSLog(@"medium lookup time: %f ms",sum/10/4*-1000);
    [pool drain];
    return 0;
}
NSString * getRandomString(){
    NSString * tmp = [NSString string];
    for (int i = 0 ; i < 10;i++){
        tmp = [NSString stringWithFormat:@"%@%c",tmp,rand()%128];
    }
    return tmp;
}

output:

2011-07-12 14:48:36.519 TestBench[974:a0f] Finished adding elements in 1950.287998 ms
2011-07-12 14:48:38.722 TestBench[974:a0f] Finished adding elements in 1899.537027 ms
2011-07-12 14:48:41.340 TestBench[974:a0f] Finished adding elements in 1939.461946 ms
2011-07-12 14:48:43.681 TestBench[974:a0f] Finished adding elements in 1991.870999 ms
2011-07-12 14:48:45.854 TestBench[974:a0f] Finished adding elements in 1857.455015 ms
2011-07-12 14:48:48.636 TestBench[974:a0f] Finished adding elements in 2205.457032 ms
2011-07-12 14:48:50.782 TestBench[974:a0f] Finished adding elements in 1866.232991 ms
2011-07-12 14:48:53.106 TestBench[974:a0f] Finished adding elements in 1847.414017 ms
2011-07-12 14:48:55.537 TestBench[974:a0f] Finished adding elements in 1982.506990 ms
2011-07-12 14:49:00.629 TestBench[974:a0f] Finished adding elements in 4536.152005 ms
2011-07-12 14:49:00.962 TestBench[974:a0f] medium lookup time: 107.704024 ms

Java

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;


public class Main {

    /**
     * @param args
     */

    public static void main(String[] args) {
        String string1="",string2="",string3="",lastString="";
        Map<String,String> map = new HashMap<String,String>();
        long sum=0;
        for (int j=0;j<10;j++){
            Date start,end;
            start = new Date();
            for (long i=0;i<100000;i++){
                String aString = getRandomString();
                map.put(aString, aString);
                if (i == 100) 
                    string1 = aString;
                if (i == 1000)
                    string2 = aString;
                if (i == 10000)
                    string3 = aString;
                if (i == 100000-1)
                    lastString = aString;
            }
            end = new Date();
            System.out.println("Finished adding elements in "+(end.getTime()-start.getTime())+" ms");
            start = new Date();
            for (int i = 0;i<1000000;i++)
                map.get(string1);
            for (int i = 0;i<1000000;i++)
                map.get(string2);
            for (int i = 0;i<1000000;i++)
                map.get(string3);
            for (int i = 0;i<1000000;i++)
                map.get(lastString);
            end = new Date();
            sum+=end.getTime()-start.getTime();
        }
        System.out.println("medium lookup time: "+sum/10/4+" ms");
    }
    public static String getRandomString(){
        String toRet = "";
        for (int i=0;i<10;i++){
            toRet+=(char)(Math.random()*128);
        }
        return toRet;
    }

}

hashmap 的结果:

Finished adding elements in 314 ms
Finished adding elements in 275 ms
Finished adding elements in 263 ms
Finished adding elements in 285 ms
Finished adding elements in 309 ms
Finished adding elements in 284 ms
Finished adding elements in 270 ms
Finished adding elements in 395 ms
Finished adding elements in 320 ms
Finished adding elements in 1804 ms
medium lookup time: 8 ms

树形图的结果

Finished adding elements in 400 ms
Finished adding elements in 430 ms
Finished adding elements in 474 ms
Finished adding elements in 581 ms
Finished adding elements in 562 ms
Finished adding elements in 599 ms
Finished adding elements in 654 ms
Finished adding elements in 625 ms
Finished adding elements in 638 ms
Finished adding elements in 1750 ms
medium lookup time: 194 ms

所以我认为 NSDictionary 不是用 hash function 制作的,而是用一棵树制作的。 为什么在 NSDictionary 中添加元素需要这么多时间? cocoa 中是否存在与 java 哈希集具有相似性能的 map? 谢谢你

您无法真正比较这些值,因为在 Java 中您有long s,而在 Cocoa 中您有double s。 如果你将NSTimeInterval (它是一个double )转换为 long,你会得到完全相同的结果。

此外,为了获得有用的结果,仅计时一次方法调用是不够的。 做一个循环,至少调用几千次。

Java 非常擅长优化不做任何事情的代码。 在这方面,它通常比 C/C++ 快得多。 但是,当涉及到实际工作时,差异通常要小得多。

map.get()除了new Date()什么都不做,这比System.currentTimeMillis()慢得多如果你想计时短操作,你最好使用System.nanoTime()并计算结果立即丢弃。

此外,值得运行大约 2 秒的测试以获得最佳结果。


import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        testMap(new TreeMap<String, String>());
        testMap(new HashMap<String, String>());
    }

    private static void testMap(Map<String, String> map) {
        System.out.println("Using " + map.getClass().getSimpleName());

            String[] strings = new String[100000];
            for (int i = 0; i < 100000; i++)
                strings[i] = getRandomString();

            {
                long start = System.nanoTime();
                for (int i = 0; i < 100000; i++) {
                    String aString = strings[i];
                    map.put(aString, aString);
                }
                long time = System.nanoTime() - start;
                System.out.printf("... added elements in %.6f ms%n", time / 1e6);
            }
            String string1 = strings[100], string2 = strings[1000], string3 = strings[10000], string4 = strings[100000 - 1];
        final int runs = 3000000;
        {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++)
                string1 = map.get(string1);
            long time = System.nanoTime() - start;
            System.out.printf("... average get() time was %.6f ms%n", time / 1e6 / runs);
        }
        {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++)
                string2 = map.get(string2);
            long time = System.nanoTime() - start;
            System.out.printf("... average get() time was %.6f ms%n", time / 1e6 / runs);
        }
        {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++)
                string3 = map.get(string3);
            long time = System.nanoTime() - start;
            System.out.printf("... average get() time was %.6f ms%n", time / 1e6 / runs);
        }
        {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++)
                string4 = map.get(string4);
            long time = System.nanoTime() - start;
            System.out.printf("... average get() time was %.6f ms%n", time / 1e6 / runs);
        }
    }

    public static String getRandomString() {
        String toRet = "";
        for (int i = 0; i < 10; i++) {
            toRet += (char) (Math.random() * 128);
        }
        return toRet;
    }
}

印刷

Using TreeMap
... added elements in 85.856512 ms
... average get() time was 0.000095 ms
... average get() time was 0.000121 ms
... average get() time was 0.000124 ms
... average get() time was 0.000119 ms
Using HashMap
... added elements in 20.189437 ms
... average get() time was 0.000016 ms
... average get() time was 0.000015 ms
... average get() time was 0.000012 ms
... average get() time was 0.000012 ms

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM