আমি কীভাবে পাইথন কোড লাইন বাই লাইনে প্রোফাইল করব?


116

আমি আমার কোড প্রোফাইলে সিপ্রোফিল ব্যবহার করছি এবং এটি দুর্দান্ত কাজ করছে। আমিও ব্যবহার করি ফলাফলগুলি কল্পনা gprof2dot.py করি (এটিকে কিছুটা আরও পরিষ্কার করে তোলে)।

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

আমি কীভাবে একটি লাইন বাই লাইন প্রোফাইলিং করব?

এর পরিবর্তে:

function #12, total time: 2.0s

আমি এরকম কিছু দেখতে চাই:

function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s

সিফ্রোফাইল পিতামাতার কাছে মোট সময় "স্থানান্তর" করার পরিমাণটি দেখায়, তবে আপনার কাছে একগুচ্ছ স্তর এবং আন্তঃসংযুক্ত কল থাকার পরে এই সংযোগটি হারিয়ে যায়।

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

main.py:

a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s

তারপরে আমি "ফানক (এ)" কল থেকে পৃথক হয়ে সেই কলটিতে কী সময় নিচ্ছে তা দেখার জন্য আমি দ্বিতীয় "ফানক (সি)" কলটিতে ক্লিক করতে সক্ষম হব।

যে জানার জন্য? এমন কোন প্রোফাইল লাইব্রেরি আছে যা এই ধরণের তথ্য সংগ্রহ করে? আমি মিস করেছি এমন কি দুর্দান্ত কিছু সরঞ্জাম আছে?


2
আমার অনুমান যে আপনি আগ্রহী হবে pstats.print_callers। একটি উদাহরণ এখানে
মুহাম্মদ আলকারৌরি

মুহাম্মদ, এটা অবশ্যই সহায়ক! কমপক্ষে এটি একটি সমস্যা সমাধান করে: উত্সের উপর নির্ভর করে ফাংশন কলগুলি পৃথক করে। আমি মনে করি জো কিংটনের উত্তর আমার লক্ষ্যের নিকটে, তবে প্রিন্ট_ক্যালাররা () অবশ্যই আমাকে সেখানে পৌঁছে দেবে। ধন্যবাদ!
রকেটমনকিগুলি

উত্তর:


120

আমি বিশ্বাস করি রবার্ট কার্নের লাইন_প্রোফিলারের জন্য এটিই । লিঙ্ক থেকে:

File: pystone.py
Function: Proc2 at line 149
Total time: 0.606656 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   149                                           @profile
   150                                           def Proc2(IntParIO):
   151     50000        82003      1.6     13.5      IntLoc = IntParIO + 10
   152     50000        63162      1.3     10.4      while 1:
   153     50000        69065      1.4     11.4          if Char1Glob == 'A':
   154     50000        66354      1.3     10.9              IntLoc = IntLoc - 1
   155     50000        67263      1.3     11.1              IntParIO = IntLoc - IntGlob
   156     50000        65494      1.3     10.8              EnumLoc = Ident1
   157     50000        68001      1.4     11.2          if EnumLoc == Ident1:
   158     50000        63739      1.3     10.5              break
   159     50000        61575      1.2     10.1      return IntParIO

আশা করি এইটি কাজ করবে!


10
লাইন_পোষক পাইথন 3 নিয়ে কাজ করে? আমি সে সম্পর্কে কোনও তথ্য পেতে পারি না।
ব্যবহারকারী 1251007

3
লাইন_প্রোফেলার আমার জন্য হিট এবং সময় দেখায় না। কেউ আমাকে বলতে পারেন কেন? আর কীভাবে সমাধান করবেন?
I159

6
এখানে আমি লিখেছি এমন ডেকরেটার : gist.github.com/kylegibson/6583590 । যদি আপনি নসেটসেট চালাচ্ছেন তবে স্টাডাউটটি তাত্ক্ষণিকভাবে মুদ্রণ করা হবে তাই -s বিকল্পটি ব্যবহার করতে ভুলবেন না।
কাইল গিবসন

5
এই আউটপুট উত্পাদন করে যে পাইথন স্ক্রিপ্টটি দেখতে কেমন? import line_profiler;এবং তারপর ?
ঝুবার্ব

10
এই লাইব্রেরিটি কীভাবে ব্যবহার করা যায় তা কী কেউ দেখিয়ে দিতে পারেন? রিডমি কীভাবে ইনস্টল করবেন এবং বিভিন্ন
एफ একিউ

47

আপনি প্রফোফিল ( পিপিআই ) ব্যবহার করতে পারেন । আপনি যদি পুরো সম্পাদনাকে প্রোফাইল করতে চান তবে এটিতে সোর্স কোড পরিবর্তন করার প্রয়োজন নেই। আপনি দুটি উপায়ে বৃহত্তর প্রোগ্রামের উপসেটটিও প্রোফাইল করতে পারেন:

  • কোডের একটি নির্দিষ্ট পয়েন্টে পৌঁছানোর সময় প্রোফাইল টগল করুন, যেমন:

    import pprofile
    profiler = pprofile.Profile()
    with profiler:
        some_code
    # Process profile content: generate a cachegrind file and send it to user.
    
    # You can also write the result to the console:
    profiler.print_stats()
    
    # Or to a file:
    profiler.dump_stats("/tmp/profiler_stats.txt")
  • স্ট্যাকস্টিকাল প্রোফাইল ব্যবহার করে কল স্ট্যাক (এই কোডটি বিবেচিত অ্যাপ্লিকেশন হিসাবে উদাহরণস্বরূপ, উদাহরণস্বরূপ একটি সিগন্যাল হ্যান্ডলার বা কোনও উপলব্ধ কর্মী থ্রেড) থেকে অবিচ্ছিন্নভাবে প্রোফাইলিং টগল করুন:

    import pprofile
    profiler = pprofile.StatisticalProfile()
    statistical_profiler_thread = pprofile.StatisticalThread(
        profiler=profiler,
    )
    with statistical_profiler_thread:
        sleep(n)
    # Likewise, process profile content

কোড এনোটেশন আউটপুট ফর্ম্যাট অনেকটা লাইন প্রোফাইলারের মতো:

$ pprofile --threads 0 demo/threads.py
Command line: ['demo/threads.py']
Total duration: 1.00573s
File: demo/threads.py
File duration: 1.00168s (99.60%)
Line #|      Hits|         Time| Time per hit|      %|Source code
------+----------+-------------+-------------+-------+-----------
     1|         2|  3.21865e-05|  1.60933e-05|  0.00%|import threading
     2|         1|  5.96046e-06|  5.96046e-06|  0.00%|import time
     3|         0|            0|            0|  0.00%|
     4|         2|   1.5974e-05|  7.98702e-06|  0.00%|def func():
     5|         1|      1.00111|      1.00111| 99.54%|  time.sleep(1)
     6|         0|            0|            0|  0.00%|
     7|         2|  2.00272e-05|  1.00136e-05|  0.00%|def func2():
     8|         1|  1.69277e-05|  1.69277e-05|  0.00%|  pass
     9|         0|            0|            0|  0.00%|
    10|         1|  1.81198e-05|  1.81198e-05|  0.00%|t1 = threading.Thread(target=func)
(call)|         1|  0.000610828|  0.000610828|  0.06%|# /usr/lib/python2.7/threading.py:436 __init__
    11|         1|  1.52588e-05|  1.52588e-05|  0.00%|t2 = threading.Thread(target=func)
(call)|         1|  0.000438929|  0.000438929|  0.04%|# /usr/lib/python2.7/threading.py:436 __init__
    12|         1|  4.79221e-05|  4.79221e-05|  0.00%|t1.start()
(call)|         1|  0.000843048|  0.000843048|  0.08%|# /usr/lib/python2.7/threading.py:485 start
    13|         1|  6.48499e-05|  6.48499e-05|  0.01%|t2.start()
(call)|         1|   0.00115609|   0.00115609|  0.11%|# /usr/lib/python2.7/threading.py:485 start
    14|         1|  0.000205994|  0.000205994|  0.02%|(func(), func2())
(call)|         1|      1.00112|      1.00112| 99.54%|# demo/threads.py:4 func
(call)|         1|  3.09944e-05|  3.09944e-05|  0.00%|# demo/threads.py:7 func2
    15|         1|  7.62939e-05|  7.62939e-05|  0.01%|t1.join()
(call)|         1|  0.000423908|  0.000423908|  0.04%|# /usr/lib/python2.7/threading.py:653 join
    16|         1|  5.26905e-05|  5.26905e-05|  0.01%|t2.join()
(call)|         1|  0.000320196|  0.000320196|  0.03%|# /usr/lib/python2.7/threading.py:653 join

মনে রাখবেন যে প্রফাইফেল কোড পরিবর্তনের উপর নির্ভর করে না কারণ এটি শীর্ষ স্তরের মডিউল স্টেটমেন্টগুলিকে প্রোফাইল প্রোগ্রামের সূচনাকালীন সময় (মডিউলগুলি আমদানি করতে, গ্লোবালগুলি আরম্ভ করতে, কতক্ষণ সময় লাগে ...) অনুমতি দেয় profile

এটি ক্যাশেগ্রিন্ড-ফর্ম্যাটযুক্ত আউটপুট উত্পন্ন করতে পারে, যাতে আপনি সহজেই বৃহত ফলাফলগুলি ব্রাউজ করতে কেচেকেগ্রিন্ড ব্যবহার করতে পারেন।

প্রকাশ: আমি প্রোফাইলে লেখক।


1
+1 আপনার অবদানের জন্য আপনাকে ধন্যবাদ। এটি বেশ ভাল দেখায়। আমার কিছুটা ভিন্ন দৃষ্টিভঙ্গি রয়েছে - বিবৃতি এবং ফাংশন দ্বারা নেওয়া অন্তর্ভুক্তিমূলক সময় পরিমাপ করা একটি উদ্দেশ্য। কোডটি দ্রুততর করার জন্য কী করা যায় তা সন্ধান করা একটি ভিন্ন উদ্দেশ্য। কোডটি বড় হওয়ার সাথে সাথে পার্থক্যটি বেদনাদায়ক স্পষ্ট হয়ে ওঠে - কোডের 10 ^ 6 লাইনের মতো। কোডটি বড় পরিমাণে সময় নষ্ট করতে পারে। আমি যেভাবে এটি খুঁজে পাচ্ছি তা হল খুব অল্প সংখ্যক খুব বিশদ নমুনা নিয়ে, এবং মানব চোখে সেগুলি পরীক্ষা করা - সংক্ষিপ্তসার নয়। সময় নষ্ট হওয়ার ভগ্নাংশ দ্বারা সমস্যাটি প্রকাশিত হয়।
মাইক ডুনলাভে

1
আপনি ঠিক বলেছেন, যখন কেউ একটি ছোট উপসেটটি প্রোফাইল করতে চায় তখন আমি প্রোফাইলে ব্যবহারের কথা উল্লেখ করি নি। এর উদাহরণ যুক্ত করতে আমি আমার পোস্ট সম্পাদনা করেছি।
vpelletier

3
এটি হ'ল আমি যা খুঁজছিলাম: হস্তক্ষেপহীন এবং বিস্তৃত।
egpbos

1
দুর্দান্ত সরঞ্জাম, তবে এটি মূল কোডের চেয়ে কয়েকগুণ ধীর গতিতে চলে।
রোমানফ

4

আপনি এর জন্য লাইন_প্রোফেলার প্যাকেজের সহায়তা নিতে পারেন

1. প্রথম প্যাকেজ ইনস্টল:

    pip install line_profiler

২. আপনার অজগর / নোটবুক পরিবেশে প্যাকেজটি লোড করতে যাদু কমান্ডটি ব্যবহার করুন

    %load_ext line_profiler

৩. যদি আপনি কোনও ফাংশনের জন্য কোডগুলি প্রোফাইল করতে চান তবে নীচে
হিসাবে করুন:

    %lprun -f demo_func demo_func(arg1, arg2)

আপনি যদি এই পদক্ষেপগুলি অনুসরণ করেন তবে আপনি সমস্ত বিবরণ সহ একটি দুর্দান্ত ফর্ম্যাট আউটপুট পাবেন :)

Line #      Hits      Time    Per Hit   % Time  Line Contents
 1                                           def demo_func(a,b):
 2         1        248.0    248.0     64.8      print(a+b)
 3         1         40.0     40.0     10.4      print(a)
 4         1         94.0     94.0     24.5      print(a*b)
 5         1          1.0      1.0      0.3      return a/b

4

কেবলমাত্র জো কিংটনের উপরে উল্লিখিত উত্তরের উন্নতি করতে ।

জন্য পাইথন 3.x , ব্যবহার line_profiler :


স্থাপন:

pip install line_profiler

ব্যবহার:

ধরুন আপনার কাছে প্রোগ্রামটি রয়েছে main.pyএবং এর মধ্যে রয়েছে, কাজ করে fun_a()এবং fun_b()আপনি সময়ের সাথে সম্মতিতে প্রোফাইল তৈরি করতে চান; @profileফাংশন সংজ্ঞাগুলির ঠিক আগে আপনাকে সাজসজ্জার ব্যবহার করতে হবে । যেমন,

@profile
def fun_a():
    #do something

@profile
def fun_b():
    #do something more

if __name__ == '__main__':
    fun_a()
    fun_b()

শেল কমান্ড প্রয়োগ করে প্রোগ্রামটি প্রকাশ করা যেতে পারে:

$ kernprof -l -v main.py

যুক্তিগুলি ব্যবহার করে আনা যায় $ kernprof -h

Usage: kernprof [-s setupfile] [-o output_file_path] scriptfile [arg] ...

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -l, --line-by-line    Use the line-by-line profiler from the line_profiler
                        module instead of Profile. Implies --builtin.
  -b, --builtin         Put 'profile' in the builtins. Use 'profile.enable()'
                        and 'profile.disable()' in your code to turn it on and
                        off, or '@profile' to decorate a single function, or
                        'with profile:' to profile a single section of code.
  -o OUTFILE, --outfile=OUTFILE
                        Save stats to <outfile>
  -s SETUP, --setup=SETUP
                        Code to execute before the code to profile
  -v, --view            View the results of the profile in addition to saving
                        it.

ফলাফলগুলি কনসোলে এমনভাবে মুদ্রিত হবে:

Total time: 17.6699 s
File: main.py
Function: fun_a at line 5

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    5                                           @profile
    6                                           def fun_a():
...

সম্পাদনা: প্রোফাইলারদের ফলাফলগুলি টিএএমপিপিএ প্যাকেজ ব্যবহার করে পার্স করা যায় । এটি ব্যবহার করে আমরা লাইন বাই লাইন পছন্দসই প্লটগুলি পেতে পারি পটভূমি


1

পাইভিএমমনিটরের একটি লাইভ-ভিউ রয়েছে যা আপনাকে সেখানে সহায়তা করতে পারে (আপনি কোনও চলমান প্রোগ্রামের সাথে সংযোগ করতে পারেন এবং এটি থেকে পরিসংখ্যান পেতে পারেন)।

দেখুন: http://www.pyvmmonitor.com/

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