Скрипт для создания списка: <Имя метода> <Количество вызовов> для определенного каталога проекта - PullRequest
1 голос
/ 21 мая 2009

Кто-нибудь знает скрипт для получения списка, который сможет рассказать мне о наиболее часто вызываемых функциях для проекта C?

method1 391
method2 23
method3 12

Еще лучше иметь возможность настраивать запрос ключевого слова в имени метода "get".

Я пытаюсь не изобретать велосипед и написать простой сценарий, чтобы сделать это самому. Вероятно, это простой способ сделать это с помощью grep или awk. Я могу написать регулярное выражение для соответствия имени вызова функции. Eclipse Plugin был бы идеальным.

Я не ищу профилировщика. Причина, по которой мне нужен такой метод, заключается в том, что мне нужно оптимизировать пространство программы для встроенного проекта. Я склонен инкапсулировать мои переменные-члены с помощью геттеров, но, возможно, потребуется использовать внешние элементы и получить доступ к наиболее часто используемым членам напрямую, чтобы сократить пространство.

Ответы [ 3 ]

1 голос
/ 27 мая 2009

Вот простой сценарий Java, который обеспечивает вывод, который я искал. Настраивая два элемента REGEX в верхней части файла, его можно также использовать для получения статистики о появлении других шаблонов.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

public class MethodCallCount {
    // This is the regex which is applied to each line to test if there is a method call on it.
    private static String REGEX_METHODCALL = "(?:\\s*)([a-zA-Z0-9_]+)\\((.*)"; 
    // Only looks in files with .c extention
    private static String REGEX_FILEEXTS = ".*.c";
    private static boolean VERBOSE_OUTPUT = false;
    private static Map<String,Integer> patternMap = new HashMap<String,Integer>();

    // Process all files and directories under dir
    public static void visitAllDirsAndFiles(File dir) {

        if( !dir.isDirectory()) {
            if( dir.getName().matches(REGEX_FILEEXTS) ) {
                if( VERBOSE_OUTPUT ) { System.out.println("Processing File: " + dir.getName() ); }
                processFile(dir);
            }
        }
        else if( !dir.getName().equals(".svn") ) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllDirsAndFiles(new File(dir, children[i]));
            }
        }
    }

    // Process only directories under dir
    public static void visitAllDirs(File dir) {
        if (dir.isDirectory()) {
            processFile(dir);

            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllDirs(new File(dir, children[i]));
            }
        }
    }

    // Process only files under dir
    public static void visitAllFiles(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllFiles(new File(dir, children[i]));
            }
        } else {
            processFile(dir);
        }
    }

    public static void processMethod( String pMethod ) {
        if( VERBOSE_OUTPUT ) { System.out.println("found: " + pMethod); }
        if( patternMap.containsKey( pMethod ) ) {
            Integer cnt = patternMap.get( pMethod );
            cnt = cnt + 1;
            patternMap.put(pMethod, cnt );
        }
        else {
            patternMap.put( pMethod.toString(), 1);
        }       
    }


    public static void processLine( String pLine ) {
        Pattern methodMatcher = Pattern.compile( REGEX_METHODCALL );
        java.util.regex.Matcher matcher = methodMatcher.matcher( pLine );

        if( matcher.matches() ) {
            if( VERBOSE_OUTPUT ) { System.out.println("processing " + matcher.group(1) ); }
            processMethod( matcher.group(1) );                  
            processLine( matcher.group(2) );
        }
    }

    public static void processFile( File pFile ) {
        BufferedReader fin;
        try {
            fin = new BufferedReader( new InputStreamReader( new FileInputStream(pFile) ) );
            String l = null;
            while( (l=fin.readLine()) != null ) {
                processLine( l );
            }
        } 
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }

    /**
     * @param args[0] is the directory to run this on.  Otherwise current directory is used.
     */
    public static void main(String[] args) {

        String searchDirPath = System.getProperty("user.dir");
        if( args.length > 0 ) {
            searchDirPath = args[0];
        }
        else {
            System.out.println("No argument specified... searching for *.map in: " + searchDirPath );
        }

        File searchDir = new File( searchDirPath );
        visitAllDirsAndFiles(searchDir);

        // Print Stats.
        int callCnt = 0;
        Set<String> patternSet = patternMap.keySet();
        for( String p : patternSet ) {
            System.out.println( patternMap.get(p) + "\t" + p );
            callCnt += patternMap.get(p);
        }
        System.out.println("Unique Methods: " + patternMap.size());
        System.out.println("Calls Detected: " + callCnt );
        System.out.println("Copy and paste output above into excel and then sort columns");
        System.out.println("DONE.");
    }
}
1 голос
/ 21 мая 2009

Один из подходов - запустить Doxygen над исходной базой. Вам необходимо настроить его на извлечение всех функций и классов, если вы не используете Doxygen, поскольку по умолчанию он игнорирует недокументированные объекты.

Если у вас также установлена ​​AT & T GraphViz , вы можете получить симпатичные графики вызовов и вызовов для каждой функции. Но я не думаю, что есть таблица, которая суммирует это по количеству вызовов.

Однако существует несколько форматов вывода без документов, которые можно выбрать, включая модуль Perl и XML. Должна существовать возможность разбора одного из них для составления нужного вам списка, и почти наверняка проще разобрать эту информацию, чем собрать достаточно внешнего интерфейса C ++, чтобы получить правильный ответ грубой силой.

Существует также серверная часть XML для GCC, которая где-то где-то выгружает синтаксическое дерево в XML ... Я недавно отключился, но не помню, где именно это было.

0 голосов
/ 22 мая 2009

Если «наиболее часто» означает фактическое количество вызовов при некотором запуске программы, DTrace может быть инструментом, который вы ищете, если у вас есть Solaris, FreeBSD или OSX для разработки. Работа. См. Также Код Spelunking redux для хорошего описания Doxygen и DTrace.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...