में हमारे कोड आधार को प्रोफाइल करते समय मैंने कुछ अजीब देखा। ऐसा लगता है कि एक टाइप किए गए तुलनित्र के साथ सॉर्टिंग (उदा। Comparator<MyClass>
) हमेशा पहले एक विधि Comparator<MyClass>.compare(Object,Object)
कहा जाता है जिसे तब विधि Comparator<MyClass>.compare(MyClass,MyClass)
कहा जाता है। इसके अलावा, उस समय का विशाल बहुमत Comparator<MyClass>.compare(Object,Object)
में बिताया गया था। आगे का पता लगाने के लिए, मैं एक छोटे से परीक्षण कार्यक्रम बनाया:तुलनात्मक के माध्यम से जावा सॉर्ट <T> तुलना में अपने अधिकांश समय (ऑब्जेक्ट, ऑब्जेक्ट)
public class Sandbox {
public static void main(String argv[]) {
for(int j=0; j<100; j++) {
int n = 10000;
SortMe[] sortMes = new SortMe[n];
for (int i=0; i<n; i++) {
sortMes[i] = new SortMe(Math.random());
}
Arrays.sort(sortMes, new SortMeComp());
System.out.println(Arrays.toString(sortMes));
}
for(int j=0; j<100; j++) {
int n = 10000;
SortMe[] sortMes = new SortMe[n];
for (int i=0; i<n; i++) {
sortMes[i] = new SortMe(Math.random());
}
Arrays.sort(sortMes, new SortMeCompTypeless());
System.out.println(Arrays.toString(sortMes));
}
}
}
टाइप किया तुलनाकारी:
public class SortMeComp implements Comparator<SortMe>{
public int compare(SortMe one, SortMe two) {
if(one.getValue()>two.getValue()) {
return -1;
} else if (one.getValue()<two.getValue()) {
return 1;
} else {
return 0;
}
}
}
untyped तुलनाकारी मैं तुलना के लिए बने:
public class SortMeCompTypeless implements Comparator{
public int compare(Object oneObj, Object twoObj) {
SortMe one = (SortMe) oneObj;
SortMe two = (SortMe) twoObj;
if(one.getValue()>two.getValue()) {
return -1;
} else if (one.getValue()<two.getValue()) {
return 1;
} else {
return 0;
}
}
}
यहाँ परिणाम (से हैं YourKit profiler; अगर आपको स्क्रीनशॉट होना है तो मुझे बताएं):
+----------------------------------------------------+-----------------+-----------------+--------------------+
| Name | Time (ms) | Own Time (ms) | Invocation Count |
+----------------------------------------------------+-----------------+-----------------+--------------------+
| +---java.util.Arrays.sort(Object[], Comparator) | 23,604 100 % | 8,096 | 200 |
| | | | | |
| +---SortMeComp.compare(Object, Object) | 11,395 48 % | 7,430 | 12,352,936 |
| | | | | | |
| | +---SortMeComp.compare(SortMe, SortMe) | 3,965 17 % | 3,965 | 12,352,936 |
| | | | | |
| +---SortMeCompTypeless.compare(Object, Object) | 4,113 17 % | 4,113 | 12,354,388 |
+----------------------------------------------------+-----------------+-----------------+--------------------+
मैंने फ़िल्टरिंग के बिना प्रोफाइल चलाया, और आप विलय करने के लिए रिकर्सिव कॉल देखते हैं (जो इसे पढ़ने में मुश्किल बनाते हैं), लेकिन ब्याज की कोई बात नहीं।
तो यहां क्या हो रहा है? उस विधि को SortMeComp.compare (ऑब्जेक्ट, ऑब्जेक्ट) कहां से आ रहा है? हमने सोचा कि यह ऐसा कुछ था जो जावा जेनेरिक से निपटने के लिए आंतरिक रूप से बनाता है, लेकिन इतना समय लग सकता है? मुझे लगता है कि जेवीएम सिर्फ एक सामान्य विधि का इलाज करेगा जैसे "untyped"/ऑब्जेक्ट विधि। जैसा कि आप देख सकते हैं, एक साधारण कास्ट बहुत तेज़ है। इसके अलावा, मुझे लगता है कि यह वास्तव में ऐसी चीज है जो जेवीएम को दूर की तरह सामान की आवश्यकता होती है, भले ही वह दूर हो जाए। यहाँ क्या चल रहा है?
वैसे:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)
संपादित करें:
जवाब में जवाब savinos लिए, मैं एक 'untyped' तुलनाकारी कि बस की तुलना एक टाइप करने के लिए डाली के साथ अतिरिक्त विधि कॉल का अनुकरण करने की कोशिश की:
+---------------------------------------------------------+-----------------+-----------------+--------------------+
| Name | Time (ms) | Own Time (ms) | Invocation Count |
+---------------------------------------------------------+-----------------+-----------------+--------------------+
| +---java.util.Arrays.sort(Object[], Comparator) | 31,044 100 % | 8,061 | 200 |
| | | | | |
| +---SortMeComp.compare(Object, Object) | 11,554 37 % | 7,617 | 12,354,392 |
| | | | | | |
| | +---SortMeComp.compare(SortMe, SortMe) | 3,936 13 % | 3,936 | 12,354,392 |
| | | | | |
| +---SortMeCompMethodCalls.compare(Object, Object) | 11,427 37 % | 7,613 | 12,352,146 |
| | | | | |
| +---SortMeCompMethodCalls.compare(SortMe, SortMe) | 3,814 12 % | 3,814 | 12,352,146 |
+---------------------------------------------------------+-----------------+-----------------+--------------------+
:
public class SortMeCompMethodCalls implements Comparator{
public int compare(Object oneObj, Object twoObj) {
return compare((SortMe)oneObj, (SortMe)twoObj);
}
public int compare(SortMe one, SortMe two) {
if(one.getValue()>two.getValue()) {
return -1;
} else if (one.getValue()<two.getValue()) {
return 1;
} else {
return 0;
}
}
}
यहाँ के परिणाम हैं
तो ऐसा लगता है कि savinos सही है! अतिरिक्त समय केवल अतिरिक्त विधि कॉल (साथ ही कलाकार के लिए थोड़ा सा) है। वह मेरे लिए पागल लगता है; आपको लगता है कि जेआईटी दूर हो जाएगा? ठीक है।
मैंने संपादन 2 हटा दिया और इसे उत्तर के रूप में जोड़ा क्योंकि यह मूल रूप से होना चाहिए था।
हम्म मैं आपकीकिट से परिचित नहीं हूं लेकिन किसी भी तरह से आउटपुट गड़बड़ हो रहा है। यदि टोपलवेल 100% पर है, तो इसका मतलब है कि बच्चों को माता-पिता के समय में शामिल किया जाना चाहिए। हालांकि, समय वास्तव में जोड़ नहीं है। क्या यह हो सकता है कि दूसरे व्यक्ति ने कोड को इस तरह से जूट किया ताकि दूसरे 11 के लिए उन 11sec की तुलना की तुलना में क्रमबद्ध() में गिना जा सके? –
@ बी। बूचहोल्ड: मर्जोर्ट में अधिकांश प्रकार का खर्च किया जा रहा है (वास्तविक सरणी हेरफेर, रिकर्सिव कॉल आदि)। अगर मैं फ़िल्टरिंग बदल गया, तो आप यह सब देखेंगे (और यह 100% तक होगा) लेकिन यह व्यावहारिक रूप से अपठनीय है (विशेष रूप से रिकर्सन के कारण)। डिफ़ॉल्ट रूप से, आपकीकिट जावा लाइब्रेरी विधियों में कॉल को सघन करने की कोशिश करता है। –
परिणाम की गणना करने के लिए आप क्या उपयोग कर रहे हैं? बेंचमार्क? कौन सा कार्यक्रम? – DarthVader