জাভার তুলনায় স্কালার পারফরম্যান্স


41

সবার আগে আমি এটা পরিষ্কার করে বলতে চাই যে এটি কোন ভাষা-এক্স-বনাম-ভাষা-ওয়াই প্রশ্ন নয় এটি কোনটি ভাল তা নির্ধারণ করার জন্য।

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

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

তবে স্ক্যালায় আমার বর্তমান অভিজ্ঞতা 50 টি লাইনের কোডের নীচে ছোট উদাহরণগুলিতে সীমাবদ্ধ এবং আমি এখন পর্যন্ত কোনও মানদণ্ড চালাচ্ছি না। সুতরাং, আমার কোন বাস্তব তথ্য নেই।

যদি এটি পরিণত Scala যে আছে জাভা wrt কিছু ওভারহেড, এটা জ্ঞান মিশ্র Scala / জাভা প্রকল্প আছে করতে না, যেখানে একটা কোড Scala আরও জটিল অংশ এবং জাভা কর্মক্ষমতা-সমালোচনামূলক অংশ? এটি কি সাধারণ অনুশীলন?

সম্পাদনা 1

আমি একটি ছোট মানদণ্ড চালিয়েছি: পূর্ণসংখ্যার একটি তালিকা তৈরি করুন, প্রতিটি পূর্ণসংখ্যাকে দুটি দ্বারা গুণিত করুন এবং এটি একটি নতুন তালিকায় রাখুন, ফলাফলটি মুদ্রণ করুন। আমি একটি জাভা বাস্তবায়ন (জাভা 6) এবং একটি স্কালা বাস্তবায়ন (স্কালা 2.9) লিখেছি। আমি উভয়ই উবুন্টু 10.04 এর অধীনে এক্লিপস ইন্ডিগোর উপর চালিয়েছি।

ফলাফলগুলি তুলনামূলক: জাভা জন্য 480 এমএস এবং স্কালার জন্য 493 এমএস (গড় গড় 100 টি পুনরাবৃত্তি)। আমি ব্যবহার করেছি স্নিপেটগুলি এখানে।

// Java
public static void main(String[] args)
{
    long total = 0;
    final int maxCount = 100;
    for (int count = 0; count < maxCount; count++)
    {
        final long t1 = System.currentTimeMillis();

        final int max = 20000;
        final List<Integer> list = new ArrayList<Integer>();
        for (int index = 1; index <= max; index++)
        {
            list.add(index);
        }

        final List<Integer> doub = new ArrayList<Integer>();
        for (Integer value : list)
        {
            doub.add(value * 2);
        }

        for (Integer value : doub)
        {
            System.out.println(value);
        }

        final long t2 = System.currentTimeMillis();

        System.out.println("Elapsed milliseconds: " + (t2 - t1));
        total += t2 - t1;
    }

    System.out.println("Average milliseconds: " + (total / maxCount));
}

// Scala
def main(args: Array[String])
{
    var total: Long = 0
    val maxCount    = 100
    for (i <- 1 to maxCount)
    {
        val t1   = System.currentTimeMillis()
        val list = (1 to 20000) toList
        val doub = list map { n: Int => 2 * n }

        doub foreach ( println )

        val t2 = System.currentTimeMillis()

        println("Elapsed milliseconds: " + (t2 - t1))
        total = total + (t2 - t1)
    }

    println("Average milliseconds: " + (total / maxCount))
}

সুতরাং, এক্ষেত্রে মনে হয় স্কালার ওভারহেড (পরিসর, মানচিত্র, ল্যাম্বদা ব্যবহার করে) সত্যই ন্যূনতম, যা ওয়ার্ল্ড ইঞ্জিনিয়ারের দেওয়া তথ্য থেকে খুব দূরে নয়।

হতে পারে এমন অন্যান্য স্কালা কনস্ট্রাকশন রয়েছে যা যত্নের সাথে ব্যবহার করা উচিত কারণ এগুলি সম্পাদন করতে বিশেষত ভারী ?

সম্পাদনা 2

আপনারা কেউ কেউ উল্লেখ করেছেন যে অভ্যন্তরীণ লুপগুলিতে থাকা প্রিন্টলনগুলি বেশিরভাগ কার্যকরের সময় নেয়। আমি সেগুলি সরিয়েছি এবং 20000 এর পরিবর্তে তালিকার আকার 100000 এ সেট করেছি resulting ফলস্বরূপ গড়টি জাভার জন্য 88 এমএস এবং স্কালার জন্য 49 এমএস ছিল।


5
আমি কল্পনা করি যেহেতু স্কালালটি JVM বাইট কোডটি সংকলন করে, তত্ক্ষণিকভাবে পারফরম্যান্স তাত্ত্বিকভাবে জাভা সমান হতে পারে অন্য একই জিনিস অন্য JVM এর অধীনে চলছে running আমি মনে করি পার্থক্যটি কীভাবে স্কালা সংকলক বাইট কোড তৈরি করে এবং যদি এটি এত দক্ষতার সাথে করে।
maple_shaft

2
@ ম্যাপেল_শ্যাফ্ট: বা স্কেল সংকলনের সময়টিতে ওভারহেড থাকতে পারে?
হতাশ

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

2
@ ম্যাপেল_শ্যাফ্ট: আমি লক্ষ্য করছি ঠিক এটাই: আমি উপরের স্কাল কোডটি সংশ্লিষ্ট জাভা কোডের চেয়ে অনেক বেশি সংক্ষিপ্ত এবং পাঠযোগ্য able আমি কেবল ভাবছিলাম যে পারফরম্যান্সের কারণে জাভাতে কোনও স্কালা প্রকল্পের অংশগুলি লেখার অর্থ কী হবে এবং সেই অংশগুলি কী হবে।
জর্জিও

2
রানটাইমটি মূলত প্রিন্টলন কল দ্বারা দখল করা হবে। আপনার আরও একটি গণন-নিবিড় পরীক্ষা দরকার।
কেভিন

উত্তর:


39

জাভাতে আপনি সংক্ষিপ্ত এবং দক্ষতার সাথে এমন একটি জিনিস করতে পারেন যা আপনি স্কালায় করতে পারবেন না: গণনাগুলি। অন্য সব কিছুর জন্য, এমনকি স্কালার লাইব্রেরিতে ধীর গতির নির্মাণগুলির জন্যও, আপনি স্কালায় দক্ষ সংস্করণগুলি পেতে পারেন।

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

কি জন্য নজর রাখা উচিত, এখানে কিছু জিনিস।

  • আপনি যদি আমার লাইব্রেরি প্যাটার্ন সমৃদ্ধ করেন তবে সর্বদা একটি শ্রেণিতে রূপান্তর করুন। উদাহরণ স্বরূপ:

    // WRONG -- the implementation uses reflection when calling "isWord"
    implicit def toIsWord(s: String) = new { def isWord = s matches "[A-Za-z]+" }
    
    // RIGHT
    class IsWord(s: String) { def isWord = s matches "[A-Za-z]+" }
    implicit def toIsWord(s: String): IsWord = new IsWord(s)
  • সংগ্রহের পদ্ধতিগুলি সম্পর্কে সতর্ক থাকুন - কারণ তারা বেশিরভাগ অংশের জন্য বহুত্বপূর্ণ, জেভিএম সেগুলি অনুকূল করে না। আপনার এগুলি এড়াতে হবে না, তবে এটি গুরুত্বপূর্ণ বিষয়গুলিতে মনোযোগ দিন। সচেতন হন যে forস্কালায় পদ্ধতি কল এবং বেনাম শ্রেণীর মাধ্যমে প্রয়োগ করা হয়।

  • যদি জাভা ক্লাস ব্যবহার করা হয় String, যেমন , Arrayবা AnyValক্লাসগুলি যা জাভা আদিমগুলির সাথে সঙ্গতিপূর্ণ হয়, জাভা সরবরাহিত পদ্ধতিগুলি পছন্দ করে যখন বিকল্প বিদ্যমান থাকে। উদাহরণস্বরূপ, এর পরিবর্তে এবং ব্যবহার lengthকরুন ।StringArraysize

  • অন্তর্নিহিত রূপান্তরগুলির অযত্ন ব্যবহার এড়িয়ে চলুন, কারণ আপনি নিজেকে ডিজাইনের পরিবর্তে ভুল করে রূপান্তরগুলি ব্যবহার করতে পারেন।

  • বৈশিষ্ট্যের পরিবর্তে ক্লাসগুলি প্রসারিত করুন। উদাহরণস্বরূপ, আপনি যদি Function1প্রসারিত করছেন তবে AbstractFunction1পরিবর্তে প্রসারিত করুন।

  • -optimiseস্কালার বেশিরভাগ অংশ পেতে ব্যবহার এবং বিশেষত্ব।

  • কী ঘটছে তা বুঝুন: javapআপনার বন্ধু এবং তাই কী চলছে তা দেখায় এমন একগুচ্ছ স্কালা পতাকা রয়েছে।

  • স্কালা আইডিয়ামগুলি সংশোধন করার জন্য এবং কোডটি আরও সংক্ষিপ্ত এবং বজায় রাখার জন্য ডিজাইন করা হয়েছে। তারা গতির জন্য ডিজাইন করা হয় না, আপনি ব্যবহার করতে হবে তাই যদি nullএর পরিবর্তে Optionএকটি জটিল পথ, তাই না! স্কালা বহু-দৃষ্টিকোণ হওয়ার কারণ রয়েছে।

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


1
+1: এমনকি এখনও যে বিষয়গুলি আমার শিখতে হবে সেগুলি সম্পর্কেও প্রচুর দরকারী তথ্য, তবে সেগুলির দিকে নজর দেওয়ার আগে কিছুটা ইঙ্গিতটি পড়া ভাল।
জর্জিও

কেন প্রথম পদ্ধতির প্রতিবিম্ব ব্যবহার করে? এটি যেভাবেই বেনাম শ্রেণি তৈরি করে, তাই প্রতিবিম্বের পরিবর্তে কেন এটি ব্যবহার করবেন না?
ওলেকসান্দার.বেহান

@ ওলেকসান্দার.বেহান বেনাম শ্রেণি একটি জাভা ধারণা, স্কালার নয়। এটি এক ধরণের পরিশোধন তৈরি করে। একটি বেনাম শ্রেণীর পদ্ধতি যা এর বেস শ্রেণিকে ওভাররাইড করে না বাইরে থেকে অ্যাক্সেস করা যায় না। স্কালার ধরণের সংশোধনগুলির ক্ষেত্রেও এটি একই নয়, সুতরাং সেই পদ্ধতিতে আসার একমাত্র উপায় প্রতিফলনের মাধ্যমে।
ড্যানিয়েল সি সোব্রাল

এটি বেশ ভয়ঙ্কর মনে হচ্ছে। বিশেষত: "সংগ্রহের পদ্ধতিগুলি থেকে সাবধান থাকুন - কারণ তারা বেশিরভাগ অংশের জন্য বহুত্বপূর্ণ, জেভিএম সেগুলি অনুকূল করে না You আপনার এড়াতে হবে না, তবে সমালোচনামূলক বিভাগগুলিতে মনোযোগ দিন" "
ম্যাট

21

একটি একক কোর, 32 বিট সিস্টেমের জন্য বেঞ্চমার্কস গেম অনুসারে , স্কালা জাভা হিসাবে তত দ্রুত গতিতে 80% একটি মাঝারি হয়। কোয়াড কোর x64 কম্পিউটারের জন্য পারফরম্যান্স প্রায় একই। এমনকি মেমরির ব্যবহার এবং কোডের ঘনত্ব বেশিরভাগ ক্ষেত্রেই একই রকম। আমি এগুলির (বরং অবৈজ্ঞানিক) বিশ্লেষণের ভিত্তিতে বলতে পারি যে স্কেল জাভাতে কিছুটা ওভারহেড যুক্ত করেছে তা নিশ্চিত করার ক্ষেত্রে আপনি সঠিক। এটি প্রচুর পরিমাণে ওভারহেড যুক্ত করে দেখা যাচ্ছে না তাই আমি বেশি স্থান / সময় গ্রহণের জন্য উচ্চতর অর্ডার আইটেমগুলির সনাক্তকরণকে সন্দেহ করি most


2
এই উত্তরের জন্য শুধু সরাসরি তুলনা ব্যবহার করুন সহায়তা পৃষ্ঠা হিসাবে (দাড়ায় shootout.alioth.debian.org/help.php#comparetwo )
igouy

18
  • আপনি যদি স্কালায় কেবল জাভা / সি-এর মতো কোড লিখেন তবে স্কালার পারফরম্যান্স অত্যন্ত শালীন। কম্পাইলার জন্য জেভিএম প্রিমিটিভের ব্যবহার করবে Int, Charইত্যাদি যখন লাগাতে পারেন। লুপগুলি স্কালায় ঠিক তত দক্ষ।
  • মনে রাখবেন যে ল্যাম্বদা এক্সপ্রেশন Functionক্লাসগুলির বেনাম সাবক্লাসগুলির উদাহরণগুলিতে সংকলিত । যদি আপনি কোনও ল্যাম্বডায় পাস করেন তবে বেনাম mapশ্রেণিটি ইনস্ট্যান্ট করা দরকার (এবং কিছু স্থানীয়দের পাস করার প্রয়োজন হতে পারে), এবং তারপরে প্রতিটি পুনরাবৃত্তির কাছে applyকলগুলি থেকে অতিরিক্ত ফাংশন কল ওভারহেড (কিছু প্যারামিটার পাসিং সহ) থাকে ।
  • অনেকগুলি ক্লাস যেমন scala.util.Randomসমতুল্য জেআরই ক্লাসের চারপাশে কেবল মোড়ক। অতিরিক্ত ফাংশন কলটি সামান্য অপচয়যোগ্য।
  • পারফরম্যান্স-সমালোচনামূলক কোডটিতে জড়িতদের জন্য সতর্কতা অবলম্বন করুন। java.lang.Math.signum(x)এর থেকে অনেক বেশি সরাসরি x.signum(), যা রূপান্তরিত করে RichIntপিছনে।
  • জাভাতে স্কালার মূল কার্যকারিতা সুবিধা হ'ল বিশেষত্ব। মনে রাখবেন যে লাইব্রেরি কোডে স্পেশালাইজেশন অল্প ব্যবহার হয়।

5
  • ক) আমার সীমিত জ্ঞান থেকে, আমি মন্তব্য করতে হবে, স্থিতিশীল প্রধান পদ্ধতিতে কোড খুব ভাল অপ্টিমাইজ করা যাবে না। আপনার সমালোচনামূলক কোডটি অন্য কোনও জায়গায় সরিয়ে নেওয়া উচিত।
  • খ) দীর্ঘ পর্যবেক্ষণ থেকে আমি পারফরম্যান্স টেস্টে ভারী আউটপুট না করার পরামর্শ দিই (এটি বাদে আপনি যা পছন্দ করেন ঠিক তেমনই তবে 2 মিলিয়ন মূল্যবোধটি কার পড়া উচিত?) আপনি প্রিন্টলন পরিমাপ করছেন যা খুব আকর্ষণীয় নয়। সর্বাধিক প্রিন্টলন প্রতিস্থাপন:
(1 to 20000).toList.map (_ * 2).max

আমার সিস্টেমে সময়টি 800 এসএস থেকে 20 এ হ্রাস করে।

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

2
আমি লুপ থেকে মুদ্রণটি মুছে ফেলেছি এবং আসলে স্কালা কোডটি জাভা কোডের চেয়ে দ্রুত।
জর্জিও

সি এবং এসেমব্লারের সাথে তুলনাটি নিম্নোক্ত অর্থে বোঝানো হয়েছিল: একটি উচ্চ-স্তরের ভাষায় আরও শক্তিশালী বিমূর্ততা রয়েছে তবে আপনাকে পারফরম্যান্সের জন্য নিম্ন-স্তরের ভাষা ব্যবহার করতে হতে পারে। এই সমান্তরালটি কি স্কালাকে উচ্চ-স্তরের এবং জাভাকে নিম্ন-স্তরের ভাষা হিসাবে বিবেচনা করে? নাও হতে পারে, যেহেতু স্কালার মনে হচ্ছে জাভা সমান পারফরম্যান্স সরবরাহ করা হবে।
জর্জিও

ক্লোজার বা স্কালার পক্ষে এটি খুব বেশি গুরুত্বপূর্ণ মনে হয় না তবে আমি যখন জাআরবি এবং জাইথনের সাথে খেলতাম তখন আমি সম্ভবত জাভাতে আরও কার্য সম্পাদনের সমালোচনা কোডটি লিখতাম। এই দু'জনের সাথে আমি একটি উল্লেখযোগ্য বৈষম্য দেখতে পেয়েছি তবে এখন বছর আগে ছিল ... আরও ভাল হতে পারে।
রিগ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.