এক্স Java64 জাভাতে ইন্টের চেয়ে দীর্ঘ ধীর কেন?


92

আমি একটি সারফেস প্রো 2 ট্যাবলেটে জাভা 7 আপডেট 45 x64 (32 বিট জাভা ইনস্টল করা নেই) সহ উইন্ডোজ 8.1 x64 চালাচ্ছি।

নীচের কোডটিতে 1688ms লাগে যখন i টাইপ দীর্ঘ হয় এবং 109ms যখন আমি কোন int হয় int লম্বা (একটি bit৪ বিটের ধরণের) একটি bit৪ বিট জেভিএম সহ একটি bit৪ বিট প্ল্যাটফর্মের চেয়ে প্রস্থের ক্রমটি ধীর গতির কেন?

আমার একটাই অনুমান যে 32 বিটের চেয়ে 64 বিট পূর্ণসংখ্যার যোগ করতে সিপিইউ বেশি সময় নেয়, তবে এটি অসম্ভব বলে মনে হয়। আমার সন্দেহ হয় হাসওয়েল রিপল ক্যারি অ্যাডার ব্যবহার করে না।

আমি এটি এক্সপ্লিপ কেপলার এসআর 1, বিটিডব্লুতে চালাচ্ছি।

public class Main {

    private static long i = Integer.MAX_VALUE;

    public static void main(String[] args) {    
        System.out.println("Starting the loop");
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheck()){
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Finished the loop in " + (endTime - startTime) + "ms");
    }

    private static boolean decrementAndCheck() {
        return --i < 0;
    }

}

সম্পাদনা করুন: ভিএস 2013 (নীচে), একই সিস্টেম দ্বারা সংকলিত সমমানের সি ++ কোড থেকে ফলাফলগুলি এখানে। দীর্ঘ: 72265ms ইন: 74656 মিমি এই ফলাফলগুলি ডিবাগ 32 বিট মোডে ছিল।

Bit৪ বিট রিলিজ মোডে: দীর্ঘ: 875 মিমি দীর্ঘ দীর্ঘ: 906ms ইন: 1047ms

এটি পরামর্শ দেয় যে আমি যে ফলাফলটি পর্যবেক্ষণ করেছি তা হল সিপিইউ সীমাবদ্ধতার চেয়ে জেভিএম অপ্টিমাইজেশন অদ্ভুততা।

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "limits.h"

long long i = INT_MAX;

using namespace std;


boolean decrementAndCheck() {
return --i < 0;
}


int _tmain(int argc, _TCHAR* argv[])
{


cout << "Starting the loop" << endl;

unsigned long startTime = GetTickCount64();
while (!decrementAndCheck()){
}
unsigned long endTime = GetTickCount64();

cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl;



}

সম্পাদনা: জাভা 8 আরটিএম-এ আবার এটি চেষ্টা করে দেখুন, উল্লেখযোগ্য কোনও পরিবর্তন হয়নি।


8
সম্ভবত সন্দেহভাজন আপনার সেটআপ, সিপিইউ বা জেভিএমের বিভিন্ন অংশ নয় the আপনি নির্ভরযোগ্যভাবে এই পরিমাপ পুনরুত্পাদন করতে পারেন? লুপটি পুনরাবৃত্তি না করা, জেআইটি উষ্ণ না করা, ব্যবহার currentTimeMillis(), চলমান কোড যা তুচ্ছভাবে সম্পূর্ণরূপে অপ্টিমাইজ করা যায় ইত্যাদি ইত্যাদি অবিশ্বাস্য ফলাফলের প্রত্যাহার।

4
আমি কিছুক্ষণ আগে বেঞ্চমার্কিং করছিলাম, আমাকে longলুপ কাউন্টার হিসাবে ব্যবহার করতে হয়েছিল , কারণ আমি যখন একটি ব্যবহার করেছি তখন জেআইটি সংকলক লুপটি অপ্টিমাইজ করেছিল int। উত্পাদিত মেশিন কোডের বিচ্ছিন্নতার দিকে নজর দেওয়া দরকার।
স্যাম

7
এটি একটি সঠিক মাইক্রোব্যাঙ্কমার্ক নয় এবং আমি আশা করব না যে এর ফলাফলগুলি কোনওভাবেই বাস্তবে প্রতিফলিত করে।
লুই ওয়াসারম্যান

7
যথাযথ জাভা মাইক্রোব্যাঙ্কমার্ক লিখতে ব্যর্থ হওয়ার জন্য ওপিকে ঝুঁকিপূর্ণ মন্তব্যগুলির সবগুলিই অনির্বচনীয়ভাবে অলস। এই জিনিসটি বাছাই করা খুব সহজ যা আপনি যদি সন্ধান করেন এবং দেখুন যে JVM কোডটি কী করে।
tmyklebu

4
@ মাআর্টিনাস: স্বীকৃত অনুশীলনটি অনুশীলন হিসাবে গ্রহণ করা হয় কারণ এটি জ্ঞাত সমস্যাগুলির তালিকার কাজ করে। যথাযথ জাভা বেঞ্চমার্কের ক্ষেত্রে, আপনি নিশ্চিত করতে চান যে আপনি সঠিকভাবে অপ্টিমাইজড কোডটি পরিমাপ করছেন, কোনও অন-স্ট্যাক প্রতিস্থাপন নয়, এবং আপনি নিশ্চিত করতে চান যে আপনার পরিমাপটি শেষে পরিষ্কার clean ওপি একটি সম্পূর্ণ আলাদা সমস্যা খুঁজে পেয়েছিল এবং তিনি যে মানদণ্ডটি সরবরাহ করেছিলেন তা এটি যথাযথভাবে প্রদর্শন করেছিল। এবং যেমনটি উল্লেখ করা হয়েছে, এই কোডটিকে একটি যথাযথ জাভা বেনমার্কে রূপান্তর করা আসলে অদ্ভুততা দূর করে না। এবং সমাবেশ কোড পড়া কঠিন নয়।
tmyklebu

উত্তর:


82

আপনি যখন ব্যবহার করেন আমার জেভিএম অভ্যন্তরীণ লুপটিতে এটি বেশ সোজা কাজটি করে long:

0x00007fdd859dbb80: test   %eax,0x5f7847a(%rip)  /* fun JVM hack */
0x00007fdd859dbb86: dec    %r11                  /* i-- */
0x00007fdd859dbb89: mov    %r11,0x258(%r10)      /* store i to memory */
0x00007fdd859dbb90: test   %r11,%r11             /* unnecessary test */
0x00007fdd859dbb93: jge    0x00007fdd859dbb80    /* go back to the loop top */

এটি ঠকায়, কঠিন, যখন আপনি intএস ব্যবহার করেন ; প্রথমে কিছু ভুল আছে যা আমি বোঝার দাবি করি না তবে একটি অনিবন্ধিত লুপের জন্য সেটআপের মতো দেখায়:

0x00007f3dc290b5a1: mov    %r11d,%r9d
0x00007f3dc290b5a4: dec    %r9d
0x00007f3dc290b5a7: mov    %r9d,0x258(%r10)
0x00007f3dc290b5ae: test   %r9d,%r9d
0x00007f3dc290b5b1: jl     0x00007f3dc290b662
0x00007f3dc290b5b7: add    $0xfffffffffffffffe,%r11d
0x00007f3dc290b5bb: mov    %r9d,%ecx
0x00007f3dc290b5be: dec    %ecx              
0x00007f3dc290b5c0: mov    %ecx,0x258(%r10)   
0x00007f3dc290b5c7: cmp    %r11d,%ecx
0x00007f3dc290b5ca: jle    0x00007f3dc290b5d1
0x00007f3dc290b5cc: mov    %ecx,%r9d
0x00007f3dc290b5cf: jmp    0x00007f3dc290b5bb
0x00007f3dc290b5d1: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b5d5: mov    %r9d,%r8d
0x00007f3dc290b5d8: neg    %r8d
0x00007f3dc290b5db: sar    $0x1f,%r8d
0x00007f3dc290b5df: shr    $0x1f,%r8d
0x00007f3dc290b5e3: sub    %r9d,%r8d
0x00007f3dc290b5e6: sar    %r8d
0x00007f3dc290b5e9: neg    %r8d
0x00007f3dc290b5ec: and    $0xfffffffffffffffe,%r8d
0x00007f3dc290b5f0: shl    %r8d
0x00007f3dc290b5f3: mov    %r8d,%r11d
0x00007f3dc290b5f6: neg    %r11d
0x00007f3dc290b5f9: sar    $0x1f,%r11d
0x00007f3dc290b5fd: shr    $0x1e,%r11d
0x00007f3dc290b601: sub    %r8d,%r11d
0x00007f3dc290b604: sar    $0x2,%r11d
0x00007f3dc290b608: neg    %r11d
0x00007f3dc290b60b: and    $0xfffffffffffffffe,%r11d
0x00007f3dc290b60f: shl    $0x2,%r11d
0x00007f3dc290b613: mov    %r11d,%r9d
0x00007f3dc290b616: neg    %r9d
0x00007f3dc290b619: sar    $0x1f,%r9d
0x00007f3dc290b61d: shr    $0x1d,%r9d
0x00007f3dc290b621: sub    %r11d,%r9d
0x00007f3dc290b624: sar    $0x3,%r9d
0x00007f3dc290b628: neg    %r9d
0x00007f3dc290b62b: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b62f: shl    $0x3,%r9d
0x00007f3dc290b633: mov    %ecx,%r11d
0x00007f3dc290b636: sub    %r9d,%r11d
0x00007f3dc290b639: cmp    %r11d,%ecx
0x00007f3dc290b63c: jle    0x00007f3dc290b64f
0x00007f3dc290b63e: xchg   %ax,%ax /* OK, fine; I know what a nop looks like */

তারপরে নিবন্ধবিহীন লুপটি নিজেই:

0x00007f3dc290b640: add    $0xfffffffffffffff0,%ecx
0x00007f3dc290b643: mov    %ecx,0x258(%r10)
0x00007f3dc290b64a: cmp    %r11d,%ecx
0x00007f3dc290b64d: jg     0x00007f3dc290b640

তারপরে অনিয়ন্ত্রিত লুপের জন্য টিয়ারডাউন কোড, নিজেই একটি পরীক্ষা এবং একটি সরল লুপ:

0x00007f3dc290b64f: cmp    $0xffffffffffffffff,%ecx
0x00007f3dc290b652: jle    0x00007f3dc290b662
0x00007f3dc290b654: dec    %ecx
0x00007f3dc290b656: mov    %ecx,0x258(%r10)
0x00007f3dc290b65d: cmp    $0xffffffffffffffff,%ecx
0x00007f3dc290b660: jg     0x00007f3dc290b654

সুতরাং এটি ইনটগুলির জন্য 16 গুণ দ্রুত গতিতে চলেছে কারণ জেআইটি int16 বার longলুপটি আনলোল করেছে, তবে লুপটি মোটেও আনرولল করে নি ।

সম্পূর্ণতার জন্য, এখানে কোডটি আমি চেষ্টা করেছি যা:

public class foo136 {
  private static int i = Integer.MAX_VALUE;
  public static void main(String[] args) {
    System.out.println("Starting the loop");
    for (int foo = 0; foo < 100; foo++)
      doit();
  }

  static void doit() {
    i = Integer.MAX_VALUE;
    long startTime = System.currentTimeMillis();
    while(!decrementAndCheck()){
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Finished the loop in " + (endTime - startTime) + "ms");
  }

  private static boolean decrementAndCheck() {
    return --i < 0;
  }
}

অ্যাসেম্বলি ডাম্পগুলি বিকল্পগুলি ব্যবহার করে তৈরি করা হয়েছিল -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly। মনে রাখবেন যে আপনার কাজটিও আপনার জন্য জেভিএম ইনস্টলেশনের সাথে জড়িয়ে পড়তে হবে; আপনার ঠিক কিছু জায়গায় এলোমেলোভাবে ভাগ করা লাইব্রেরি লাগাতে হবে বা এটি ব্যর্থ হবে।


9
ঠিক আছে, তাই নেট-নেটটি longসংস্করণটি ধীরে ধীরে নয়, intসংস্করণটির চেয়ে দ্রুত হয়। এটা বোধগম্য. জেআইটিকে longঅভিব্যক্তিটি অনুকূল করে তোলার ক্ষেত্রে ততটা প্রচেষ্টা ব্যয় করা হয়নি ।
হট লিক্স

4
... আমার অজ্ঞতা ক্ষমা করুন, তবে "ফ্যানোললড" কী? আমি এই শব্দটি সঠিকভাবে গুগল করেও দেখতে পাচ্ছি না এবং এটিই প্রথমবারের মতো ইন্টারনেটে কোনও শব্দটির অর্থ কাউকে জিজ্ঞাসা করতে হয়েছিল।
ব্রায়ানএইচ

4
@ ব্রায়ানহাল "পতাকা" এর জন্য কমান্ড-লাইন সুইচ হিসাবে gccব্যবহার করে -fএবং এটি বলে unroll-loopsঅপ্টিমাইজেশন চালু হয় -funroll-loops। আমি কেবল অপ্টিমাইজেশন বর্ণনা করতে "আনারোল" ব্যবহার করি।
ক্রাইলিস -সাহাটিউপটিস্টিক-

4
@ বিআরপোকক: জাভা সংকলক পারবেন না, তবে জেআইটি নিশ্চিত করতে পারে।
tmyklebu

4
কেবল স্পষ্ট করে বলতে গেলে, এটি এটিকে "ফানরোল" করেনি। এটি এটিকে আনআরোলড করে নিবন্ধভুক্ত লুপকে রূপান্তরিত করেছে i-=16, অবশ্যই 16x দ্রুত।
আলেকজান্ডার ডাবিনস্কি

22

জেভিএম স্ট্যাক শব্দের সাথে সংজ্ঞায়িত করা হয়েছে , যার আকারটি বাস্তবায়নের বিশদ তবে কমপক্ষে 32 বিট প্রস্থ হতে হবে। জেভিএম বাস্তবায়নকারী 64৪ -বিট শব্দ ব্যবহার করতে পারে, তবে বাইটোকোড এটির উপর নির্ভর করতে পারে না, এবং তাই longবা doubleমানগুলির সাথে অপারেশনগুলি অতিরিক্ত যত্ন সহকারে পরিচালনা করতে হবে। বিশেষত, জেভিএম পূর্ণসংখ্যা শাখার নির্দেশাবলী ঠিক ধরণের উপরে সংজ্ঞায়িত করা হয় int

আপনার কোডের ক্ষেত্রে, বিচ্ছিন্ন করা শিক্ষণীয়। intওরাকল জেডিকে 7 দ্বারা সংকলিত সংস্করণটির বাইটকোডটি এখানে রয়েছে :

private static boolean decrementAndCheck();
  Code:
     0: getstatic     #14  // Field i:I
     3: iconst_1      
     4: isub          
     5: dup           
     6: putstatic     #14  // Field i:I
     9: ifge          16
    12: iconst_1      
    13: goto          17
    16: iconst_0      
    17: ireturn       

নোট করুন যে JVM আপনার স্ট্যাটিক i(0) এর মান লোড করবে , একটিকে বিয়োগ করবে (3-4), স্ট্যাকের (5) মানটি নকল করবে এবং এটিকে পরিবর্তনশীল (6) এ আবার ঠেলে দেবে। এটি তখন শূন্য শাখার সাথে তুলনা করে ফিরে আসে।

এর সংস্করণটি longআরও জটিল:

private static boolean decrementAndCheck();
  Code:
     0: getstatic     #14  // Field i:J
     3: lconst_1      
     4: lsub          
     5: dup2          
     6: putstatic     #14  // Field i:J
     9: lconst_0      
    10: lcmp          
    11: ifge          18
    14: iconst_1      
    15: goto          19
    18: iconst_0      
    19: ireturn       

প্রথমত, যখন জেভিএম স্ট্যাকের নতুন মানটিকে নকল করে (5), তখন এটি দুটি স্ট্যাক শব্দের নকল করতে হবে। আপনার ক্ষেত্রে, এটি সম্ভবত সম্ভব যে এটি নকল করা ছাড়া আর কোনও ব্যয়বহুল নয়, যেহেতু JVM সুবিধাজনক হলে একটি 64-বিট শব্দ ব্যবহার করতে পারে free তবে আপনি দেখতে পাবেন যে শাখার যুক্তি এখানে আরও দীর্ঘ। longশূন্যের সাথে তুলনা করার জন্য জেভিএমের কোনও নির্দেশনা নেই , সুতরাং এটি 0Lস্ট্যাকের উপর একটি ধ্রুবককে ধাক্কা দিতে হবে (9), একটি সাধারণ longতুলনা (10) করতে হবে এবং তারপরে তার মানটির উপর ব্রাঞ্চ করতে হবে গণনার ।

এখানে দুটি প্রশংসনীয় পরিস্থিতি রয়েছে:

  • জেভিএম ঠিক বাইটকোড পথ অনুসরণ করছে। এক্ষেত্রে long, এটি সংস্করণে আরও কাজ করছে , বেশ কয়েকটি অতিরিক্ত মান ধাক্কা দিয়ে এবং পপ করছে এবং এগুলি ভার্চুয়াল পরিচালিত স্ট্যাকের উপর রয়েছে , আসল হার্ডওয়্যার-সহিত সিপিইউ স্ট্যাক নয়। যদি এটি হয় তবে আপনি এখনও ওয়ার্মআপের পরে একটি উল্লেখযোগ্য পারফরম্যান্সের পার্থক্য দেখতে পাবেন।
  • জেভিএম বুঝতে পারে যে এটি এই কোডটি অনুকূল করতে পারে। এই ক্ষেত্রে, ব্যবহারিকভাবে অপ্রয়োজনীয় কিছু ধাক্কা / তুলনা যুক্তিটিকে অপ্টিমাইজ করতে অতিরিক্ত সময় নিচ্ছে। যদি এটি হয় তবে আপনি ওয়ার্মআপের পরে পারফরম্যান্সের খুব কম পার্থক্য দেখতে পাবেন।

আমি আপনাকে সুপারিশ করছি আপনি জেআইটি কিক ইন করার প্রভাবটি নির্মূল করার জন্য একটি সঠিক মাইক্রোব্যাঙ্কমার্ক লিখুন , এবং এটিও চূড়ান্ত শর্ত নয় যা জেভিএমকে এটির সাথে একই তুলনা করতে বাধ্য করতে চূড়ান্ত শর্ত দিয়ে চেষ্টা intকরুন long


4
পছন্দ করুন খুব বিশেষত, ক্লায়েন্ট এবং সার্ভার হটস্পট জেভিএম সম্পূর্ণ আলাদা বাস্তবায়ন, এবং ইলিয়া সার্ভার নির্বাচন করার নির্দেশ দেয় নি (ক্লায়েন্ট সাধারণত 32-বিট ডিফল্ট হয়)।
ক্রাইলিস -সাহাটিউপটিস্টিক-

4
@tmyklebu ইস্যুটি হ'ল বেঞ্চমার্কটি একবারে বিভিন্ন জিনিস পরিমাপ করছে। ননজারো টার্মিনাল শর্ত ব্যবহার করে ভেরিয়েবলের সংখ্যা হ্রাস পায়।
ক্রাইলিস -কোটিরিওপটিস্টিস্টিক-

4
@ টিমাইক্লেবু মূল কথাটি হ'ল ওপির ইচ্ছা ছিল দীর্ঘতর লম্বা ইনটগুলির সাথে ইনক্রিমেন্ট, হ্রাস এবং তুলনার গতি তুলনা করা। পরিবর্তে (এই উত্তরটি সঠিক বলে ধরে নিচ্ছেন) তারা কেবল তুলনা মাপছিলেন, এবং কেবল 0 এর বিপরীতে যা একটি বিশেষ ক্ষেত্রে। যদি অন্য কিছু না হয় তবে এটি মূল বেঞ্চমার্ককে বিভ্রান্তিমূলক করে তোলে - দেখে মনে হচ্ছে এটি তিনটি সাধারণ কেস পরিমাপ করে, যখন বাস্তবে এটি একটি, নির্দিষ্ট ক্ষেত্রে পরিমাপ করে।
ysavit

4
@ টিমাইক্লেবু আমাকে ভুল করবেন না, আমি প্রশ্ন, এই উত্তর এবং আপনার উত্তরটিকে উজ্জীবিত করেছি। তবে আমি আপনার এই বক্তব্যের সাথে একমত নই যে @ ক্রাইলিস যে পার্থক্যটি পরিমাপের চেষ্টা করছেন তা পরিমাপ করা বন্ধ করার জন্য মাপদণ্ডকে সামঞ্জস্য করছে। আমি ভুল হলে ওপি আমাকে সংশোধন করতে পারে তবে তারা কেবলমাত্র / প্রাথমিকভাবে পরিমাপ করার চেষ্টা করছে == 0বলে মনে হচ্ছে না, যা বেঞ্চমার্ক ফলাফলের একটি অসমসাহীনভাবে বড় অংশ বলে মনে হয়। আমার কাছে আরও সম্ভবত মনে হয় যে ওপি আরও সাধারণ পরিসীমা পরিমাপের চেষ্টা করছে এবং এই উত্তরটি নির্দেশ করে যে বেঞ্চমার্ক সেই সমস্ত অপারেশনের মধ্যে কেবল একটির দিকেই তীব্রভাবে ঝুঁকছে।
ysavit

4
@tmyklebu মোটেও নয় আমি মূল কারণগুলি বোঝার জন্যই আছি। তবে, একটি প্রধান মূল কারণটি চিহ্নিত করা হয়েছে যে বেঞ্চমার্কটি স্কিউ করা হয়েছিল, এটি স্কিউ অপসারণের জন্য বেঞ্চমার্ক পরিবর্তন করা অবৈধ নয়, পাশাপাশি সেই স্কিউ সম্পর্কে আরও খনন করতে এবং আরও বুঝতে হবে (উদাহরণস্বরূপ, এটি আরও দক্ষ সক্ষম করতে পারে) বাইটকোড, এটি লুপগুলি আনারল করা সহজ করে তোলে ইত্যাদি)। এই কারণেই আমি এই উত্তরটি (যা স্কিউ চিহ্নিত করেছিল) এবং আপনার (যা আরও বিস্তারিতভাবে স্কুতে খনন করে) উভয়কেই উত্সাহিত করেছিল।
ysavit

8

একটি জাভা ভার্চুয়াল মেশিনে ডেটা বেসিক ইউনিট শব্দ হয়। ডান শব্দের আকার নির্বাচন করা জেভিএম বাস্তবায়নের পরে বাকি রয়েছে। একটি জেভিএম প্রয়োগের ক্ষেত্রে বিটগুলির সর্বনিম্ন শব্দের আকার চয়ন করা উচিত। দক্ষতা অর্জনের জন্য এটি উচ্চতর শব্দের আকার চয়ন করতে পারে। উভয় ক্ষেত্রেই কোনও বিধিনিষেধ নেই যে word৪ বিট জেভিএম কেবলমাত্র bit৪ বিট শব্দ চয়ন করবে।

অন্তর্নিহিত আর্কিটেকচার শব্দের আকারও একই হতে হবে এমনটি নিয়ম করে না। জেভিএম প্রতিটি শব্দ লিখে ডেটা পড়ে / লিখে। এই কারণে এটি একটি জন্য সময় নিচ্ছে করা যেতে পারে হয় দীর্ঘ একটি চেয়ে int- এ

এখানে আপনি একই বিষয়ে আরও সন্ধান করতে পারেন।


4

আমি সবেমাত্র ক্যালিপার ব্যবহার করে একটি বেঞ্চমার্ক লিখেছি

ফলাফল ব্যবহার করার জন্য একটি ~ 12x speedup: মূল কোড সহ বেশ সামঞ্জস্যপূর্ণ হয় intবেশি long। এটি অবশ্যই মনে হয় যে tmyklebu বা খুব অনুরূপ কিছু দ্বারা প্রতিবেদন করা লুপটি অনিয়ন্ত্রিত হচ্ছে।

timeIntDecrements         195,266,845.000
timeLongDecrements      2,321,447,978.000

এটি আমার কোড; নোট করুন যে এটিতে নতুনভাবে নির্মিত স্ন্যাপশট ব্যবহার করা হয়েছে caliper, যেহেতু আমি তাদের বিদ্যমান বিটা রিলিজের বিপরীতে কীভাবে কোড করব তা বুঝতে পারি না।

package test;

import com.google.caliper.Benchmark;
import com.google.caliper.Param;

public final class App {

    @Param({""+1}) int number;

    private static class IntTest {
        public static int v;
        public static void reset() {
            v = Integer.MAX_VALUE;
        }
        public static boolean decrementAndCheck() {
            return --v < 0;
        }
    }

    private static class LongTest {
        public static long v;
        public static void reset() {
            v = Integer.MAX_VALUE;
        }
        public static boolean decrementAndCheck() {
            return --v < 0;
        }
    }

    @Benchmark
    int timeLongDecrements(int reps) {
        int k=0;
        for (int i=0; i<reps; i++) {
            LongTest.reset();
            while (!LongTest.decrementAndCheck()) { k++; }
        }
        return (int)LongTest.v | k;
    }    

    @Benchmark
    int timeIntDecrements(int reps) {
        int k=0;
        for (int i=0; i<reps; i++) {
            IntTest.reset();
            while (!IntTest.decrementAndCheck()) { k++; }
        }
        return IntTest.v | k;
    }
}

1

রেকর্ডের জন্য, এই সংস্করণটি একটি অশোধিত "ওয়ার্মআপ" করে:

public class LongSpeed {

    private static long i = Integer.MAX_VALUE;
    private static int j = Integer.MAX_VALUE;

    public static void main(String[] args) {

        for (int x = 0; x < 10; x++) {
            runLong();
            runWord();
        }
    }

    private static void runLong() {
        System.out.println("Starting the long loop");
        i = Integer.MAX_VALUE;
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheckI()){

        }
        long endTime = System.currentTimeMillis();

        System.out.println("Finished the long loop in " + (endTime - startTime) + "ms");
    }

    private static void runWord() {
        System.out.println("Starting the word loop");
        j = Integer.MAX_VALUE;
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheckJ()){

        }
        long endTime = System.currentTimeMillis();

        System.out.println("Finished the word loop in " + (endTime - startTime) + "ms");
    }

    private static boolean decrementAndCheckI() {
        return --i < 0;
    }

    private static boolean decrementAndCheckJ() {
        return --j < 0;
    }

}

সামগ্রিক সময়গুলি প্রায় 30% উন্নতি করে তবে উভয়ের মধ্যে অনুপাত প্রায় একই থাকে।


@ টেডহপ্প - আমি আমার লুপ সীমাটি পরিবর্তন করার চেষ্টা করেছি এবং এটি মূলত অপরিবর্তিত রয়েছে।
হট লিক্স

@ টেকরকেট ৯: আমি intএই কোড সহ একই ধরণের সংখ্যা পেয়েছি ( ২০ গুণ বেশি দ্রুত)।
tmyklebu

1

রেকর্ডগুলির জন্য:

যদি আমি ব্যবহার করি

boolean decrementAndCheckLong() {
    lo = lo - 1l;
    return lo < -1l;
}

("l--" "l = l - 1l" তে পরিবর্তিত) দীর্ঘ কর্মক্ষমতা 50% দ্বারা উন্নত


0

পরীক্ষার জন্য আমার কাছে একটি bit৪ বিট মেশিন নেই, তবে বড় পার্থক্য থেকে বোঝা যায় যে কর্মক্ষেত্রে সামান্য দীর্ঘ বাইকোডের চেয়ে আরও বেশি কিছু রয়েছে।

আমি আমার 32-বিট 1.7.0_45 এ দীর্ঘ / ইনট (4400 বনাম 4800 মিমি) এর খুব কাছাকাছি সময় দেখি।

এটি কেবল অনুমান , তবে আমি দৃ strongly ়ভাবে সন্দেহ করি যে এটি কোনও মেমরি মিস্যালাইনমেন্ট জরিমানার প্রভাব। সন্দেহটিকে নিশ্চিত / অস্বীকার করতে, সর্বজনীন স্ট্যাটিক ইন্ট ডামি = 0 যুক্ত করার চেষ্টা করুন; আগেi এর ঘোষণারএটি মেমোরি লেআউটে 4 বাইট দ্বারা নামিয়ে দেবে এবং এটি আরও ভাল পারফরম্যান্সের জন্য সঠিকভাবে প্রান্তিককরণ করতে পারে। নিশ্চিত করা হয়েছে যে সমস্যাটি সৃষ্টি করছে না।

সম্পাদনা: এর পিছনে যুক্তিটি হ'ল ভিএম ক্ষেত্রগুলি পুনরায় অর্ডার করতে পারে না তার অবসর সময়ে অনুকূল প্রান্তিককরণের জন্য প্যাডিং যুক্ত করে, যেহেতু এটি জেএনআইয়ের সাথে হস্তক্ষেপ করতে পারে (ক্ষেত্র না).


VM- র অবশ্যই হয় পুনর্বিন্যাস ক্ষেত্র এবং অ্যাড প্যাডিং অনুমতি দেওয়া।
হট লিক্স

জেএনআই-কে এই বিরক্তিকর, ধীর অ্যাক্সেসর পদ্ধতির মাধ্যমে অ্যাক্সেস করতে হবে যা কিছুটা অস্বচ্ছ হ্যান্ডেলগুলি গ্রহণ করে যেহেতু জিসি ঘটতে পারে যখন নেটিভ কোড চলমান। ক্ষেত্রগুলি পুনরায় অর্ডার করতে এবং প্যাডিং যুক্ত করার জন্য এটি প্রচুর বিনামূল্যে।
tmyklebu

0

এটি সম্ভবত JVM নিরাপদ পয়েন্টগুলির জন্য যখন দীর্ঘক্ষণ ব্যবহার করা হয় (আনকাউন্টযুক্ত লুপ) অনুসন্ধান করে এবং এটি (গণিত লুপ) এর জন্য না করে থাকে।

কিছু তথ্যসূত্র: https://stackoverflow.com/a/62557768/14624235

https://stackoverflow.com/a/58726530/14624235

http://psy-lob-saw.blogspot.com/2016/02/wait-for-it-counteduncounted-loops.html

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.