TrickDiary このページをアンテナに追加 RSSフィード

2010-02-16

[][] C#バグベアード擬き エンジン部

昨日の続きでエンジン部をC#へ移植。まだ詰めが残ってるけど、これでほぼできあがり。

using System;
using System.Collections.Generic;
#if BUG_WITHOUT_LOCATION_INFO
#else
using System.Diagnostics;
#endif

public class bug_puppy
{

    // 省略


    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_message
    //

    public class bug_message
    {
#if BUG_WITHOUT_LOCATION_INFO
#else
        public string file;
        public int line;
#if BUG_FUNCTION_NAME
        public string function_name;
#endif
#endif
        public string message;

        public bug_message()
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            file = null;
            line = 0;
#if BUG_FUNCTION_NAME
            function_name = null;
#endif
#endif
        }
        public bug_message(string a_message)
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            file = null;
            line = 0;
#if BUG_FUNCTION_NAME
            function_name = null;
#endif
#endif
            message = a_message;
        }
#if BUG_WITHOUT_LOCATION_INFO
#else
#if BUG_FUNCTION_NAME
        public bug_message(string a_file, int a_line, string a_function_name)
#else
        public bug_message(string a_file, int a_line)
#endif
        {
            file = a_file;
            line = a_line;
#if BUG_FUNCTION_NAME
            function_name = a_function_name;
#endif
            message = null;
        }
#if BUG_FUNCTION_NAME
        public bug_message(string a_file, int a_line, string a_function_name, string a_message)
#else
        public bug_message(string a_file, int a_line, string a_message)
#endif
        {
            file = a_file;
            line = a_line;
#if BUG_FUNCTION_NAME
            function_name = a_function_name;
#endif
            message = a_message;
        }
#endif
        public bug_message(bug_message a)
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            file = a.file;
            line = a.line;
#if BUG_FUNCTION_NAME
            function_name = a.function_name;
#endif
#endif
            message = a.message;
        }
        public bug_message(bug_message a, string a_message)
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            file = a.file;
            line = a.line;
#if BUG_FUNCTION_NAME
            function_name = a.function_name;
#endif
#endif
            message = a_message;
        }
            
#if BUG_WITHOUT_LOCATION_INFO
#else
        public string get_file()
        {
            if (string.IsNullOrEmpty(file))
            {
                return "<?unknown?>#?";
            }
            else
            {
                return file;
            }
        }
        public int get_line()
        {
            return line;
        }
#if BUG_FUNCTION_NAME
        string get_function_name()
        {
            if (string.IsNullOrEmpty(function_name))
            {
                return "unknown_function";
            }
            else
            {
                return function_name;
            }
        }
#endif
#endif
        public string get_message()
        {
            return message;
        }
#if BUG_WITHOUT_LOCATION_INFO
#else
        public string get_location()
        {
            if (string.IsNullOrEmpty(file))
            {
                return "<?unknown?>#?";
            }
            else
            {
#if BUG_FUNCTION_NAME
                return string.Format("<{0}>#{1}@{2}", file, line.ToString(), get_function_name().c_str());
#else
                return string.Format("<{0}>#{1}", file, line.ToString());
#endif
            }
        }
#endif

        public string get_message_ex()
        {
#if BUG_WITHOUT_LOCATION_INFO
            return message;
#else
            if (string.IsNullOrEmpty(message))
            {
                return get_location();
            }
            else
            {
                return message;
            }
#endif
        }

        public string get_full_message()
        {
#if BUG_WITHOUT_LOCATION_INFO
            return message;
#else
            if (string.IsNullOrEmpty(file))
            {
                return message;
            }
            else
            if (string.IsNullOrEmpty(message))
            {
                return get_location();
            }
            else
            {
                return string.Format("{0} {1}", message, get_location());
            }
#endif
        }

        public bug_message create(string a_message)
        {
            return new bug_message(this, a_message);
        }

        public bug_message assign(bug_message a)
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            file = a.file;
            line = a.line;
#if BUG_FUNCTION_NAME
            function_name = a.function_name;
#endif
#endif
            message = a.message;
            return this;
        }
        
        public bool Equals (bug_message a)
        {
            return
#if BUG_WITHOUT_LOCATION_INFO
#else
                file == a.file &&
                line == a.line &&
#if BUG_FUNCTION_NAME
                function_name == a.function_name &&
#endif
#endif
                message == a.message;
        }
        public bool less_than(bug_message a)
        {
            return
#if BUG_WITHOUT_LOCATION_INFO
#else
                file.CompareTo(a.file) < 0 ||
                (
                    file == a.file &&
                    (
                        line < a.line ||
                        (
                            line == a.line &&
                            (
#if BUG_FUNCTION_NAME
                                function_name.CompareTo(a.function_name) < 0 ||
                                (
                                    function_name == a.function_name &&
                                    (
#endif
#endif
                                        message.CompareTo(a.message) < 0
#if BUG_WITHOUT_LOCATION_INFO
#else
#if BUG_FUNCTION_NAME
                                    )
                                )
#endif
                            )
                        )
                    )
                )
#endif
                ;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_profiler
    //
    
    public delegate void bug_writer(bug_message text, IEnumerable<string> tags);

    [ThreadStatic] public static bug_writer trace_writer = null;
    [ThreadStatic] public static string last_stamp = null;

    class bug_profiler :IDisposable
    {
        bug_writer profile_writer;
        public int level;
        int bug_scope_count;
        long bug_scope_begin_time;
        Stack<bug_profile_time_score> score_stack = new Stack<bug_profile_time_score>();
        Dictionary<bug_message, bug_profile_time_score_set> profile_db = new Dictionary<bug_message, bug_profile_time_score_set>();
        
        long overall_start_time;
        bug_profile_time_score overall_time_score = new bug_profile_time_score();

        public bug_profiler(bug_writer a_profile_writer)
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();
            begin_bug_time(a_current_tick);

            profile_writer = a_profile_writer;
            level = 0;
            bug_scope_count = 0;
            bug_scope_begin_time = 0;
            overall_start_time = a_current_tick;
            push_time_score(overall_time_score);

            end_bug_time();
        }
        public void Dispose()
        {
        }

        [ThreadStatic] public static bug_profiler instance = null;

        //public static bug_profiler get_instance()
        //{
        //    return instance;
        //}

        public void push_time_score(bug_profile_time_score a_time_score, long a_current_tick)
        {
            if (null != this)
            {
                if (0 < bug_scope_count)
                {
                    if (0 < score_stack.Count)
                    {
                        if (bug_scope_begin_time < a_current_tick)
                        {
                            score_stack.Peek().self_time_set.bug_time += a_current_tick -bug_scope_begin_time;
                            bug_scope_begin_time = a_current_tick;
                        }
                    }
                }
                score_stack.Push(a_time_score);
            }
        }
        public void push_time_score(bug_profile_time_score a_time_score)
        {
            push_time_score(a_time_score, bug_profile_time_type.get_current_tick());
        }
        public void add_time_score(bug_message a_message, string a_start_stamp, bug_profile_time_score a_time_score)
        {
            if (null != this)
            {
                if (0 < score_stack.Count)
                {
                    score_stack.Peek().sub_time_set.add(a_time_score.get_all_time_set());
                }
                profile_db[a_message].add_score(a_start_stamp, a_time_score);
            }
        }
        public void pop_time_score(long a_current_tick)
        {
            if (null != this)
            {
                if (0 < score_stack.Count)
                {
                    if (0 < bug_scope_count)
                    {
                        if (bug_scope_begin_time < a_current_tick)
                        {
                            score_stack.Peek().self_time_set.bug_time += a_current_tick - bug_scope_begin_time;
                            bug_scope_begin_time = a_current_tick;
                        }
                    }
                    score_stack.Pop();
                }
            }
        }
        public void pop_time_score()
        {
            pop_time_score(bug_profile_time_type.get_current_tick());
        }

        public void begin_bug_time(long a_current_tick)
        {
            if (null != this)
            {
                if (0 == bug_scope_count++)
                {
                    bug_scope_begin_time = a_current_tick;
                }
            }
        }
        public void end_bug_time()
        {
            if (null != this)
            {
                if (0 == --bug_scope_count)
                {
                    if (0 < score_stack.Count)
                    {
                        score_stack.Peek().self_time_set.bug_time += bug_profile_time_type.get_current_tick() -bug_scope_begin_time;
                    }
                }
            }
        }
        
        protected void overall_scope_end()
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();

            begin_bug_time(a_current_tick);
            pop_time_score();
            overall_time_score.self_time_set.whole_time = bug_profile_time_type.get_current_tick() -overall_start_time;
            var overall_message = new bug_message
            (
#if BUG_WITHOUT_LOCATION_INFO
#else
                "overall_scope_label", 0,
#if BUG_FUNCTION_NAME
                "overall_scope_label",
#endif
#endif
                "overall_scope_label"
            );
            add_time_score(overall_message, "overall_scope_label", overall_time_score);
            end_bug_time();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_bug_time_scope
    //

    class bug_bug_time_scope :IDisposable
    {
        bug_profiler profiler;
        public bug_bug_time_scope()
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();
            profiler = bug_profiler.instance;
            if (null != profiler)
            {
                profiler.begin_bug_time(a_current_tick);
            }
        }
        public bug_bug_time_scope(long a_current_tick)
        {
            profiler = bug_profiler.instance;
            if (null != profiler)
            {
                profiler.begin_bug_time(a_current_tick);
            }
        }
        public void Dispose()
        {
            if (null != profiler)
            {
                profiler.end_bug_time();
            }
        }
    };
    
    
    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_profile_scope
    //
    
    class bug_profile_scope :IDisposable
    {
        public bug_profiler profiler;
        public string start_stamp;
        public long start_time;
        public bug_profile_time_score time_score;
        public bug_message message;
        
        public bug_profile_scope(string a_message_value)
        {
#if BUG_WITHOUT_LOCATION_INFO
#else
            var call_stack = new StackFrame(1, true);
#endif
            bug_message a_message = new bug_message
            (
#if BUG_WITHOUT_LOCATION_INFO
#else
                call_stack.GetFileName(),
                call_stack.GetFileLineNumber(),
#if BUG_FUNCTION_NAME
                call_stack.GetMethod().Name,
#endif
#endif
                a_message_value
            );
            long a_current_tick = bug_profile_time_type.get_current_tick();
            using(var bug_time_scope = new bug_bug_time_scope(a_current_tick))
            {
                profiler = bug_profiler.instance;

                start_stamp = last_stamp;
                start_time = a_current_tick;
                time_score = new bug_profile_time_score();
                message = new bug_message(a_message);

                profiler.push_time_score(time_score, a_current_tick);
            }
        }
        public bug_profile_scope(bug_message a_message)
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();
            using(var bug_time_scope = new bug_bug_time_scope(a_current_tick))
            {
                profiler = bug_profiler.instance;

                start_stamp = last_stamp;
                start_time = a_current_tick;
                time_score = new bug_profile_time_score();
                message = new bug_message(a_message);

                profiler.push_time_score(time_score, a_current_tick);
            }
        }
        public void Dispose()
        {
            long current_tick = bug_profile_time_type.get_current_tick();
            using(var bug_time_scope = new bug_bug_time_scope(current_tick))
            {
                if (null != profiler)
                {
                    profiler.pop_time_score(current_tick);
                }
                time_score.self_time_set.whole_time = current_tick -start_time -time_score.get_sub_time_set().get_whole_time().value;
                time_score.self_time_set.work_time = time_score.get_self_time_set().get_whole_time().value -time_score.get_self_time_set().get_bug_time().value;
                if (null != profiler)
                {
                    profiler.add_time_score(message, start_stamp, time_score);
                }
            }
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  write
    //

    public static void write(bug_message text, IEnumerable<string> tags)
    {
        long a_current_tick = bug_profile_time_type.get_current_tick();
        using (var bug_time_scope = new bug_bug_time_scope(a_current_tick))
        {
            if (null != trace_writer)
            {
                trace_writer(text, tags);
            }
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_scope
    //

    class bug_scope : bug_profile_scope, IDisposable
    {
        public IEnumerable<string> tags;

        public bug_scope(bug_message a_message, IEnumerable<string> a_tags)
            :base(a_message)
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();
            using(var bug_time_scope = new bug_bug_time_scope(a_current_tick)
            {
                tags = a_tags;
                write(message.create(string.Format("▽{0}", message.get_message())), a_tags);
                if (null != profiler)
                {
                    ++profiler.level;
                }
            }
        }
        public new void Dispose()
        {
            long a_current_tick = bug_profile_time_type.get_current_tick();
            using(var bug_time_scope = new bug_bug_time_scope(a_current_tick)
            {
                write(message.create(string.Format("△{0}", message.get_message())), tags);
                if (null != profiler)
                {
                    --profiler.level;
                }
            }
            base.Dispose();
        }
    }

}

2010-02-15

[][] C#バグベアード擬き プロファイルデータ構造部

とりあえずオリジナルのプロファイルデータ構造部をC#へ移植。

using System;
using System.Collections.Generic;
#if BUG_WITHOUT_LOCATION_INFO
#else
using System.Diagnostics;
#endif

public class bug_puppy
{
    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_profile_time_type
    //
    
    class bug_profile_time_type
    {
        public long value;
        
        public bug_profile_time_type(long a_value)
        {
            value = a_value;
        }
        public bug_profile_time_type(bug_profile_time_type a)
        {
            value = a.value;
        }
        
        public static long get_current_tick()
        {
            return DateTime.Now.Ticks;
        }
        
        public static long get_tick_resolution()
        {
            return 1000000;
        }
        public long get_sec()
        {
            //return value /get_tick_resolution();
            return value / 1000000;
        }
        public long get_usec()
        {
            //const long tick_resolution = get_tick_resolution();
            //const long scale = 1000000;
            //return ((value %tick_resolution) *scale) /tick_resolution;
            return value % 1000000;
        }
        
        public string get_string(string a)
        {
            if (0 <= value)
            {
                return string.Format
                (
                    "{0}.{1:D6}",
                    get_sec().ToString(),
                    get_usec().ToString()
                );
            }
            else
            {
                return string.Format("-{0}", new bug_profile_time_type(-value).get_string(a));
            }
        }
        public bool less_than(bug_profile_time_type a)
        {
            return value < a.value;
        }
    }
    
    
    ///////////////////////////////////////////////////////////////////////////
    //
    //  bug_profile_time_set, bug_profile_time_score, bug_profile_time_score_set
    //
    
    class bug_profile_time_set
    {
    
        public long whole_time;
        public long bug_time;
        public long work_time;
        
        public bug_profile_time_set()
        {
            whole_time = 0;
            bug_time = 0;
            work_time = 0;
        }
        public bug_profile_time_set(bug_profile_time_set a)
        {
            assign(a);
        }
        
        public bug_profile_time_type get_whole_time()
        {
            return new bug_profile_time_type(whole_time);
        }
        public bug_profile_time_type get_bug_time()
        {
            return new bug_profile_time_type(bug_time);
        }
        public bug_profile_time_type get_work_time()
        {
            return new bug_profile_time_type(work_time);
        }
        
        public string get_string(string separator)
        {
            return
                get_whole_time().get_string(separator) + separator
                + get_bug_time().get_string(separator) + separator
                + get_work_time().get_string(separator);
        }
        
        public bug_profile_time_type get_core_value()
        {
            return get_work_time();
        }
        public bool less_than(bug_profile_time_set a)
        {
            return get_core_value().less_than(a.get_core_value());
        }

        public bug_profile_time_set assign(bug_profile_time_set a)
        {
            whole_time = a.whole_time;
            bug_time = a.bug_time;
            work_time = a.work_time;
            return this;
        }
        public bug_profile_time_set add(bug_profile_time_set a)
        {
            whole_time += a.whole_time;
            bug_time += a.bug_time;
            work_time += a.work_time;
            return this;
        }
        public bug_profile_time_set div(long a)
        {
            whole_time /= a;
            bug_time /= a;
            work_time /= a;
            return this;
        }
    }

    class bug_profile_time_score
    {
    
        public bug_profile_time_set self_time_set;
        public bug_profile_time_set sub_time_set;
        
        public bug_profile_time_score()
        {
            self_time_set = new bug_profile_time_set();
            sub_time_set = new bug_profile_time_set();
        }
        public bug_profile_time_score(bug_profile_time_score a)
        {
            self_time_set = new bug_profile_time_set(a.self_time_set);
            sub_time_set = new bug_profile_time_set(a.sub_time_set);
        }
        
        public bug_profile_time_set get_all_time_set()
        {
            var result = new bug_profile_time_set(self_time_set);
            result.bug_time += sub_time_set.bug_time;
            result.work_time += sub_time_set.work_time;
            return result;
        }
        public bug_profile_time_set get_self_time_set()
        {
            return self_time_set;
        }
        public bug_profile_time_set get_sub_time_set()
        {
            return sub_time_set;
        }

        public string get_string(string separator)
        {
            return
                get_all_time_set().get_string(separator) + separator
                + get_self_time_set().get_string(separator) + separator
                + get_sub_time_set().get_string(separator);
        }

        public bug_profile_time_set get_core_value()
        {
            return get_all_time_set();
        }
        public bool less_than(bug_profile_time_score a)
        {
            return get_core_value().less_than(a.get_core_value());
        }

        public bug_profile_time_score assign(bug_profile_time_score a)
        {
            self_time_set.assign(a.self_time_set);
            sub_time_set.assign(a.sub_time_set);
            return this;
        }
        public bug_profile_time_score add(bug_profile_time_score a)
        {
            self_time_set.add(a.self_time_set);
            sub_time_set.add(a.sub_time_set);
            return this;
        }
        public bug_profile_time_score div(long a)
        {
            self_time_set.div(a);
            sub_time_set.div(a);
            return this;
        }
    };

    class bug_profile_time_score_set
    {
        public bug_profile_time_score total_score;
        public string min_begin_stamp;
        public bug_profile_time_score min_score;
        public string max_begin_stamp;
        public bug_profile_time_score max_score;
        public long count;
        
        public bug_profile_time_score_set()
        {
            total_score = new bug_profile_time_score();
            min_score = new bug_profile_time_score();
            max_score = new bug_profile_time_score();
            count = 0;
        }
        public bug_profile_time_score_set(bug_profile_time_score_set a)
        {
            total_score = new bug_profile_time_score(a.total_score);
            min_score = new bug_profile_time_score(a.min_score);
            max_score = new bug_profile_time_score(a.max_score);
            count = a.count;
        }

        public bug_profile_time_score get_total_score()
        {
            return total_score;
        }
        public bug_profile_time_score get_min_score()
        {
            return min_score;
        }
        public bug_profile_time_score get_max_score()
        {
            return max_score;
        }
        public bug_profile_time_score get_average_score()
        {
            if (0 != count)
            {
                return new bug_profile_time_score(get_total_score()).div(get_count());
            }
            else
            {
                return get_total_score();
            }
        }
        public long get_count()
        {
            return count;
        }

        public string get_string(string separator)
        {
            return
                get_total_score().get_string(separator) + separator
                + get_count().ToString() + separator
                + get_average_score().get_string(separator) + separator
                + min_begin_stamp + separator
                + get_min_score().get_string(separator) + separator
                + max_begin_stamp + separator
                + get_max_score().get_string(separator);
        }
        
        public void add_score(string a_begin_stamp, bug_profile_time_score a_time_score)
        {
            if (0 == get_count())
            {
                total_score.assign(a_time_score);
                set_min_score(a_begin_stamp, a_time_score);
                set_max_score(a_begin_stamp, a_time_score);
            }
            else
            {
                total_score.add(a_time_score);

                if (a_time_score.less_than(min_score))
                {
                    set_min_score(a_begin_stamp, a_time_score);
                }
                if (max_score.less_than(a_time_score))
                {
                    set_max_score(a_begin_stamp, a_time_score);
                }
            }
            ++count;
        }
        
        private void set_min_score(string a_begin_stamp, bug_profile_time_score a_time_score)
        {
            min_begin_stamp = a_begin_stamp;
            min_score.assign(a_time_score);
        }
        private void set_max_score(string a_begin_stamp, bug_profile_time_score a_time_score)
        {
            max_begin_stamp = a_begin_stamp;
            max_score.assign(a_time_score);
        }
    }

    // 省略

}