কোনও উপায়ে কোনও উপায়েই উপকার হয় নাকি অন্যভাবে? এটি কি সংকলক / ভিএম নির্দিষ্ট? আমি হটস্পট ব্যবহার করছি।
কোনও উপায়ে কোনও উপায়েই উপকার হয় নাকি অন্যভাবে? এটি কি সংকলক / ভিএম নির্দিষ্ট? আমি হটস্পট ব্যবহার করছি।
উত্তর:
প্রথম: আপনার পারফরম্যান্সের ভিত্তিতে স্থির বনাম অ স্থির নির্বাচন করা উচিত নয়।
দ্বিতীয়: অনুশীলনে, এটি কোনও পার্থক্য করবে না। হটস্পট এমন পদ্ধতিতে অনুকূলিতকরণ চয়ন করতে পারে যেগুলি একটি পদ্ধতির জন্য স্থির কলগুলি দ্রুত করে তোলে, অন্যের জন্য অ স্থিত কলগুলি দ্রুত faster
তৃতীয়: স্ট্যাটিক বনাম অ স্ট্যাটিক পার্শ্ববর্তী mythos অনেক অন খুব পুরানো JVMs (যা অপ্টিমাইজেশান যে হটস্পট করে কাছাকাছি কোনো জায়গায় না) ভিত্তিক হয়, অথবা সি সম্পর্কে কিছু স্মরণ ট্রিভিয়ার ++, (যা একটি গতিশীল কল ব্যবহারের মধ্যে এক আরো মেমরি অ্যাক্সেস স্থির কলের চেয়ে)।
চার বছর পরে...
ঠিক আছে, এই প্রশ্নটি একবার এবং চিরতরে নিষ্পত্তি করার আশায় আমি একটি মাপকাঠি লিখেছি যা দেখায় যে কীভাবে বিভিন্ন ধরণের কল (ভার্চুয়াল, নন-ভার্চুয়াল, স্ট্যাটিক) একে অপরের সাথে তুলনা করে।
আমি এটি আদর্শের উপর চালিয়েছি , এবং এটি আমি পেয়েছি:
(পুনরাবৃত্তির বৃহত সংখ্যা ভাল)
Success time: 3.12 memory: 320576 signal:0
Name | Iterations
VirtualTest | 128009996
NonVirtualTest | 301765679
StaticTest | 352298601
Done.
প্রত্যাশিত হিসাবে, ভার্চুয়াল পদ্ধতি কলগুলি সবচেয়ে ধীর, অ-ভার্চুয়াল পদ্ধতি কলগুলি দ্রুত এবং স্থির পদ্ধতি কলগুলি আরও দ্রুত।
পার্থক্যগুলি এতটা উচ্চারণের জন্য আমি যা প্রত্যাশা করি নি: ভার্চুয়াল পদ্ধতি কলগুলি অ-ভার্চুয়াল পদ্ধতি কলগুলির অর্ধেকেরও কম গতিতে চালিত হয় , যা স্থির কলগুলির চেয়ে পুরো 15% ধীরে চালিত হয় । এই পরিমাপগুলি এটাই দেখায়; প্রকৃত পার্থক্যগুলি অবশ্যই প্রকৃতপক্ষে আরও স্পষ্ট হওয়া উচিত, যেহেতু প্রতিটি ভার্চুয়াল, নন ভার্চুয়াল এবং স্ট্যাটিক পদ্ধতি কলের জন্য, আমার বেঞ্চমার্কিং কোডটির একটি অতিরিক্ত ধরণের ওভারহেড থাকে একটি পূর্ণসংখ্য পরিবর্তনশীল, বুলিয়ান ভেরিয়েবল পরীক্ষা করে এবং লুপিং সত্য না হলে।
আমি মনে করি ফলাফলগুলি সিপিইউ থেকে সিপিইউতে এবং জেভিএম থেকে জেভিএম-এ পরিবর্তিত হবে, তাই এটি চেষ্টা করে দেখুন কী পাবেন:
import java.io.*;
class StaticVsInstanceBenchmark
{
public static void main( String[] args ) throws Exception
{
StaticVsInstanceBenchmark program = new StaticVsInstanceBenchmark();
program.run();
}
static final int DURATION = 1000;
public void run() throws Exception
{
doBenchmark( new VirtualTest( new ClassWithVirtualMethod() ),
new NonVirtualTest( new ClassWithNonVirtualMethod() ),
new StaticTest() );
}
void doBenchmark( Test... tests ) throws Exception
{
System.out.println( " Name | Iterations" );
doBenchmark2( devNull, 1, tests ); //warmup
doBenchmark2( System.out, DURATION, tests );
System.out.println( "Done." );
}
void doBenchmark2( PrintStream printStream, int duration, Test[] tests ) throws Exception
{
for( Test test : tests )
{
long iterations = runTest( duration, test );
printStream.printf( "%15s | %10d\n", test.getClass().getSimpleName(), iterations );
}
}
long runTest( int duration, Test test ) throws Exception
{
test.terminate = false;
test.count = 0;
Thread thread = new Thread( test );
thread.start();
Thread.sleep( duration );
test.terminate = true;
thread.join();
return test.count;
}
static abstract class Test implements Runnable
{
boolean terminate = false;
long count = 0;
}
static class ClassWithStaticStuff
{
static int staticDummy;
static void staticMethod() { staticDummy++; }
}
static class StaticTest extends Test
{
@Override
public void run()
{
for( count = 0; !terminate; count++ )
{
ClassWithStaticStuff.staticMethod();
}
}
}
static class ClassWithVirtualMethod implements Runnable
{
int instanceDummy;
@Override public void run() { instanceDummy++; }
}
static class VirtualTest extends Test
{
final Runnable runnable;
VirtualTest( Runnable runnable )
{
this.runnable = runnable;
}
@Override
public void run()
{
for( count = 0; !terminate; count++ )
{
runnable.run();
}
}
}
static class ClassWithNonVirtualMethod
{
int instanceDummy;
final void nonVirtualMethod() { instanceDummy++; }
}
static class NonVirtualTest extends Test
{
final ClassWithNonVirtualMethod objectWithNonVirtualMethod;
NonVirtualTest( ClassWithNonVirtualMethod objectWithNonVirtualMethod )
{
this.objectWithNonVirtualMethod = objectWithNonVirtualMethod;
}
@Override
public void run()
{
for( count = 0; !terminate; count++ )
{
objectWithNonVirtualMethod.nonVirtualMethod();
}
}
}
static final PrintStream devNull = new PrintStream( new OutputStream()
{
public void write(int b) {}
} );
}
এটি লক্ষণীয় যে এই পারফরম্যান্স পার্থক্যটি কেবলমাত্র কোডের ক্ষেত্রে প্রযোজ্য যা প্যারামিটারলেস পদ্ধতি ছাড়া অন্য কিছুই করে না। আমন্ত্রণগুলির মধ্যে আপনার কাছে অন্য যে কোনও কোড রয়েছে তা পার্থক্যগুলিকে হ্রাস করবে এবং এর মধ্যে প্যারামিটার পাসিং অন্তর্ভুক্ত রয়েছে। প্রকৃতপক্ষে, স্ট্যাটিক এবং নন ভার্চুয়াল কলগুলির মধ্যে 15% পার্থক্যটি সম্ভবত পুরো বিষয়টি ব্যাখ্যা করে ব্যাখ্যা করে যে this
পয়েন্টারটিকে স্থির পদ্ধতিতে পাস করতে হয় না। সুতরাং, এটি কেবলমাত্র কোনও ধরণের প্রভাব ফেলবে না এমন বিন্দুতে কল করার জন্য বিভিন্ন ধরণের কলের মধ্যে পার্থক্যের জন্য তুচ্ছ বিষয়গুলির মধ্যে কেবলমাত্র সামান্য পরিমাণের কোড লাগবে।
এছাড়াও, ভার্চুয়াল পদ্ধতি কলগুলি একটি কারণে উপস্থিত রয়েছে; তাদের সেবা করার একটি উদ্দেশ্য আছে এবং এগুলি অন্তর্নিহিত হার্ডওয়্যার দ্বারা সরবরাহ করা সবচেয়ে কার্যকর উপায় ব্যবহার করে প্রয়োগ করা হয়। (সিপিইউ নির্দেশিকা সেট।) যদি, অ-ভার্চুয়াল বা স্ট্যাটিক কলগুলি প্রতিস্থাপন করে সেগুলি মুছে ফেলার জন্য আপনার ইচ্ছাতে তাদের কার্যকারিতা অনুকরণের জন্য অতিরিক্ত কোডের একটি আইওটা যোগ করতে হবে তবে আপনার ফলস্বরূপ নেট ওভারহেড আবদ্ধ কম না, কিন্তু আরও। বেশ সম্ভবত, অনেক, অনেক বেশি, নিরপেক্ষভাবে অনেক বেশি, আরও।
VirtualTest | 488846733 -- NonVirtualTest | 480530022 -- StaticTest | 484353198
, আমার ওপেনজেডিকে ইনস্টলেশনতে গতিতে কোনও পার্থক্য নেই । এফটিআর: আমি যদি final
মডিফায়ারটি সরিয়ে ফেলি তবে এটি এমনকি সত্য । বিটিডব্লিউ আমাকে terminate
ক্ষেত্র তৈরি করতে হবে volatile
, অন্যথায় পরীক্ষা শেষ হয়নি।
VirtualTest | 12451872 -- NonVirtualTest | 12089542 -- StaticTest | 8181170
। আমার নোটবুকের ওপেনজেডিকে কেবল 40x আরও পুনরুক্তি পরিচালনার পক্ষে নয়, স্থির পরীক্ষায় সর্বদা 30% কম থ্রুপুট থাকে put এটি একটি এআরটি নির্দিষ্ট ঘটনা হতে পারে, কারণ আমি একটি অ্যান্ড্রয়েড ৪.৪ ট্যাবলেটে প্রত্যাশিত ফলাফল পেয়েছি:VirtualTest | 138183740 -- NonVirtualTest | 142268636 -- StaticTest | 161388933
ঠিক আছে, স্ট্যাটিক কলগুলি ওভাররাইড করা যায় না (তাই সর্বদা ইনলাইনের প্রার্থী হয়), এবং কোনও নালিকা পরীক্ষা করার প্রয়োজন নেই। হটস্পট উদাহরণস্বরূপ পদ্ধতিগুলির জন্য শীতল অপ্টিমাইজেশানগুলির একটি গোছা করে যা এই সুবিধাগুলি ভালভাবে প্রত্যাখ্যান করতে পারে তবে স্থির কলটি দ্রুততর হওয়ার কারণেই তারা সম্ভাব্য কারণ।
তবে, এটি আপনার নকশায় প্রভাব ফেলবে না - সর্বাধিক পঠনযোগ্য, প্রাকৃতিক উপায়ে কোড - এবং কেবলমাত্র এই ধরণের মাইক্রো-অপ্টিমাইজেশান সম্পর্কে উদ্বিগ্ন হওয়া যদি আপনার কেবল কারণ হয় (যা আপনি প্রায়শই চান না )।
এটি সংকলক / ভিএম নির্দিষ্ট।
সুতরাং আপনি এটি আপনার আবেদনটিতে সত্যিকারের সমালোচনামূলক পারফরম্যান্স সমস্যা হিসাবে চিহ্নিত না করে অবহেলা করার জন্য সম্ভবত এটি মাথা ঘামানোর মতো নয়। অকালীন অপটিমাইজেশন হ'ল সমস্ত মন্দ ইত্যাদির মূল ...
তবে আছে দেখা এই অপ্টিমাইজেশান নিম্নলিখিত অবস্থায় সুত্রে কর্মক্ষমতা বৃদ্ধি করা উচিত:
যদি উপরেরটি আপনার ক্ষেত্রে প্রযোজ্য হয় তবে এটি পরীক্ষার পক্ষে মূল্যবান হতে পারে।
স্থিতিশীল পদ্ধতি ব্যবহারের জন্য আরও একটি ভাল (এবং সম্ভাব্যতর আরও গুরুত্বপূর্ণ!) কারণ রয়েছে - যদি পদ্ধতিটিতে বাস্তবে স্থির শব্দার্থ থাকে (যেমন যৌক্তিকভাবে শ্রেণীর কোনও নির্দিষ্ট উদাহরণের সাথে সংযুক্ত না হয়) তবে এটি স্থিতিশীল করার জন্য এটি বোধগম্য হয় এই সত্য প্রতিফলিত। অভিজ্ঞ জাভা প্রোগ্রামাররা তখন স্ট্যাটিক মডিফায়ারটি লক্ষ্য করবেন এবং তাত্ক্ষণিকভাবে মনে করবেন "আহা! এই পদ্ধতিটি স্থিতিশীল তাই এটির উদাহরণ প্রয়োজন হয় না এবং সম্ভবত উদাহরণ সুনির্দিষ্ট রাজ্যে কারসাজি করা হয় না"। সুতরাং আপনি পদ্ধতিটির স্থির প্রকৃতি কার্যকরভাবে জানাতে পারবেন ....
অবিশ্বাস্যভাবেই অসম্ভাব্য যে স্ট্যাটিক বনাম অ স্থিত কলগুলির কার্য সম্পাদনে যে কোনও পার্থক্য আপনার আবেদনে একটি পার্থক্য আনছে। মনে রাখবেন যে "অকালীন অপটিমাইজেশন হ'ল সমস্ত মন্দের মূল"।
আগের পোস্টারগুলি যেমন বলেছে: এটি অকাল অপটিমাইজেশনের মতো বলে মনে হচ্ছে।
তবে, এর মধ্যে একটি পার্থক্য রয়েছে (এই অংশের একটি অংশ যে অ স্থিতিক দাওয়াতগুলির জন্য অপারেন্ড স্ট্যাকের উপরে একটি ক্যালি-অবজেক্টের অতিরিক্ত ধাক্কা প্রয়োজন):
যেহেতু স্ট্যাটিক পদ্ধতিগুলি ওভাররাইড করা যায় না, তাই স্ট্যাটিক পদ্ধতি কলের জন্য রানটাইমে কোনও ভার্চুয়াল লুকআপ হবে না । এর ফলে কিছু পরিস্থিতিতে পর্যবেক্ষণযোগ্য পার্থক্য হতে পারে।
একটি বাইট-কোড স্তরের উপর পার্থক্য হল যে একটি অ-স্ট্যাটিক পদ্ধতি কল মাধ্যমে সম্পন্ন করা হয় INVOKEVIRTUAL
, INVOKEINTERFACE
বা INVOKESPECIAL
যখন একটি স্ট্যাটিক পদ্ধতি কল মাধ্যমে সম্পন্ন করা হয় INVOKESTATIC
।
invokespecial
এটি একটি ভার্চুয়াল নয় বলে একটি ব্যক্তিগত উদাহরণ পদ্ধতিটি ব্যবহার করা হচ্ছে (কমপক্ষে সাধারণত) inv
7 বছর পরে ...
মাইকের নকিস যে ফলাফলগুলি পেয়েছিল তাতে আমার কাছে বিশাল আস্থা নেই কারণ তারা হটস্পট অপটিমাইজেশন সম্পর্কিত কিছু সাধারণ সমস্যা সমাধান করে না। আমি জেএমএইচ ব্যবহার করে বেঞ্চমার্কগুলি চালিত করেছি এবং একটি স্ট্যাটিক কল বনাম আমার মেশিনে একটি উদাহরণ পদ্ধতির ওভারহেড প্রায় 0.75% বলে খুঁজে পেয়েছি। নীচের ওভারহেড প্রদত্ত আমি মনে করি সর্বাধিক বিলম্বিত সংবেদনশীল অপারেশনগুলি বাদে এটি যুক্তিযুক্তভাবে কোনও অ্যাপ্লিকেশন ডিজাইনের বৃহত্তম উদ্বেগ নয়। আমার জেএমএইচ বেঞ্চমার্ক থেকে সংক্ষিপ্ত ফলাফলগুলি নীচে রয়েছে;
java -jar target/benchmark.jar
# -- snip --
Benchmark Mode Cnt Score Error Units
MyBenchmark.testInstanceMethod thrpt 200 414036562.933 ± 2198178.163 ops/s
MyBenchmark.testStaticMethod thrpt 200 417194553.496 ± 1055872.594 ops/s
আপনি এখানে গিথুবে কোডটি দেখতে পারেন;
https://github.com/nfisher/svsi
মাপদণ্ডটি নিজেই বেশ সহজ তবে মৃত কোড বিলোপ এবং ধ্রুবক ভাঁজকে হ্রাস করার লক্ষ্য। সম্ভবত অন্যান্য অপটিমাইজেশন রয়েছে যা আমি মিস করেছি / উপেক্ষা করেছি এবং এই ফলাফলগুলি JVM রিলিজ এবং ওএস প্রতি পরিবর্তিত হতে পারে।
package ca.junctionbox.svsi;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
class InstanceSum {
public int sum(final int a, final int b) {
return a + b;
}
}
class StaticSum {
public static int sum(final int a, final int b) {
return a + b;
}
}
public class MyBenchmark {
private static final InstanceSum impl = new InstanceSum();
@State(Scope.Thread)
public static class Input {
public int a = 1;
public int b = 2;
}
@Benchmark
public void testStaticMethod(Input i, Blackhole blackhole) {
int sum = StaticSum.sum(i.a, i.b);
blackhole.consume(sum);
}
@Benchmark
public void testInstanceMethod(Input i, Blackhole blackhole) {
int sum = impl.sum(i.a, i.b);
blackhole.consume(sum);
}
}
ops/s
মূলত কোনও এআরটি পরিবেশে (যেমন মেমরির ব্যবহার, হট ফাইলের আকার হ্রাস করা ইত্যাদি) ছাড়া অন্য মেট্রিকগুলিতে যে কোনও সম্ভাব্য সুবিধা থাকতে পারে সে সম্পর্কে আমি আগ্রহী । আপনি কি অপেক্ষাকৃত সহজ সরঞ্জাম / উপায়গুলি সম্পর্কে জানেন যে কেউ এই অন্যান্য মেট্রিকগুলিকে বেনমার্ক করার চেষ্টা করতে পারে?
সিদ্ধান্তের জন্য যদি কোনও পদ্ধতি স্থিতিশীল হওয়া উচিত তবে পারফরম্যান্সের দিকটি অপ্রাসঙ্গিক হওয়া উচিত। আপনার যদি পারফরম্যান্স সমস্যা হয় তবে প্রচুর পদ্ধতি স্থিতিশীল করা দিনটি বাঁচবে না। এটি বলেছিল, স্থির পদ্ধতিগুলি অবশ্যই কোনও উদাহরণ পদ্ধতির চেয়ে ধীর নয় , বেশিরভাগ ক্ষেত্রে প্রান্তিক দ্রুত :
1.) স্থিতিশীল পদ্ধতিগুলি বহুবিধ নয়, সুতরাং বাস্তবায়নের কোডটি কার্যকর করার জন্য জেভিএমের কম সিদ্ধান্ত নেই। এটি হটস্পটের যুগে একটি মূল বিন্দু, যেহেতু হটস্পট উদাহরণস্বরূপ পদ্ধতি কলগুলি কেবলমাত্র একটি প্রয়োগকারী সাইট রয়েছে তা অনুকূল করবে, সুতরাং তারা একই সম্পাদন করবে।
২) আর একটি সূক্ষ্ম পার্থক্য হ'ল স্থির পদ্ধতিগুলির স্পষ্টতই "এই" উল্লেখ নেই। একই স্বাক্ষর এবং বডি সহ একটি উদাহরণ পদ্ধতির চেয়ে একটি স্ট্যাক ফ্রেমের ফলস্বরূপ ("এটি" বাইটকোড স্তরের স্থানীয় ভেরিয়েবলের স্লট 0-এ রাখা হয়, তবে স্থির পদ্ধতির জন্য স্লট 0 প্রথমটির জন্য ব্যবহৃত হয়) পদ্ধতির পরামিতি)।
কোনও পার্থক্য থাকতে পারে এবং এটি কোনও নির্দিষ্ট কোডের কোনও অংশেই যেতে পারে এবং এটি জেভিএমের এমনকি একটি সামান্য প্রকাশের সাথেও পরিবর্তন হতে পারে।
এটি আপনার স্পষ্টতই ভুলে যাওয়া উচিত 97% ক্ষুদ্র কার্যকারিতার একটি অংশ ।
TableView
কয়েক মিলিয়ন রেকর্ড অনুসন্ধান করুন।
তত্ত্বগতভাবে, কম ব্যয়বহুল।
আপনি যদি কোনও অবজেক্টের উদাহরণ তৈরি করেন তবে স্ট্যাটিক ইনিশিয়ালাইজেশনও সম্পন্ন হতে চলেছে, অন্যদিকে স্থির পদ্ধতিগুলি কোনও কনস্ট্রাক্টরে সাধারণত কোনও সূচনা করা হবে না।
তবে আমি এটি পরীক্ষা করিনি।
জন নোট হিসাবে, স্থিতিশীল পদ্ধতি ওভাররাইড করা যাবে না, সুতরাং একটি স্ট্যাটিক পদ্ধতি সহজভাবে প্রয়োগ করা হতে পারে - পর্যাপ্ত নিরীহ জাভা রানটাইমের সময় - উদাহরণ পদ্ধতি প্রয়োগের চেয়ে দ্রুততর ।
তবে, এমনকি ধরে নেওয়াও যে আপনি কয়েকটি ন্যানোসেকেন্ডগুলি সংরক্ষণ করার জন্য আপনার নকশাকে বিশৃঙ্খলা করার বিষয়ে যত্নশীল সেই মুহুর্তে আপনি আরও একটি প্রশ্ন এনেছেন: আপনার নিজের ওভাররাইড করার পদ্ধতিটির কি দরকার হবে? আপনি যদি এখানে আপনার নানোসেকেন্ডটি সংরক্ষণ করার জন্য একটি উদাহরণ পদ্ধতিটিকে স্থিতিশীল পদ্ধতিতে পরিণত করার জন্য আপনার কোডটি পরিবর্তন করেন এবং তারপরে ঘুরিয়ে ঘুরিয়ে আপনার নিজের প্রেরণার প্রয়োগ করেন, তবে আপনার তৈরির চেয়ে অবশ্যই আপনার দক্ষতা কম হবে আপনার জাভা রানটাইমের মধ্যে ইতিমধ্যে।
আমি এখানে অন্যান্য দুর্দান্ত উত্তরগুলি যুক্ত করতে চাই যে এটি আপনার প্রবাহের উপরও নির্ভর করে, উদাহরণস্বরূপ:
Public class MyDao {
private String sql = "select * from MY_ITEM";
public List<MyItem> getAllItems() {
springJdbcTemplate.query(sql, new MyRowMapper());
};
};
মনোযোগ দিন যে আপনি প্রতিটি কল প্রতি একটি নতুন MyRowMapper অবজেক্ট তৈরি।
পরিবর্তে, আমি এখানে একটি স্থির ক্ষেত্র ব্যবহার করার পরামর্শ দিই।
Public class MyDao {
private static RowMapper myRowMapper = new MyRowMapper();
private String sql = "select * from MY_ITEM";
public List<MyItem> getAllItems() {
springJdbcTemplate.query(sql, myRowMapper);
};
};