diff options
author | Corentin Noël <tintou@noel.tf> | 2023-01-04 18:54:57 +0100 |
---|---|---|
committer | Niels De Graef <nielsdegraef@gmail.com> | 2023-01-15 18:07:15 +0000 |
commit | bc03cbab8498de1583f6489665234edc819aa8fd (patch) | |
tree | 58978351b69415df04e58eb00362606472eab4e8 | |
parent | a49d1e8950d6ff26e19da7f28be6e2d80406b05b (diff) | |
download | folks-bc03cbab8498de1583f6489665234edc819aa8fd.tar.gz |
profiling: Use sysprof as the profiling library
Instead of abusing the posix access function.
-rw-r--r-- | backends/bluez/bluez-backend.vala | 4 | ||||
-rw-r--r-- | backends/bluez/bluez-persona-store.vala | 34 | ||||
-rw-r--r-- | backends/dummy/lib/dummy-backend.vala | 4 | ||||
-rw-r--r-- | backends/dummy/lib/dummy-persona-store.vala | 4 | ||||
-rw-r--r-- | backends/eds/eds-backend.vala | 4 | ||||
-rw-r--r-- | backends/eds/lib/edsf-persona-store.vala | 4 | ||||
-rw-r--r-- | backends/key-file/kf-backend.vala | 4 | ||||
-rw-r--r-- | backends/key-file/kf-persona-store.vala | 4 | ||||
-rw-r--r-- | backends/ofono/ofono-backend.vala | 4 | ||||
-rw-r--r-- | backends/ofono/ofono-persona-store.vala | 4 | ||||
-rw-r--r-- | backends/telepathy/lib/tpf-persona-store.vala | 15 | ||||
-rw-r--r-- | backends/telepathy/tp-backend.vala | 4 | ||||
-rw-r--r-- | folks/backend-store.vala | 8 | ||||
-rw-r--r-- | folks/individual-aggregator.vala | 4 | ||||
-rw-r--r-- | folks/internal.vala | 49 | ||||
-rw-r--r-- | folks/meson.build | 3 | ||||
-rw-r--r-- | meson.build | 5 | ||||
-rw-r--r-- | meson_options.txt | 2 | ||||
-rw-r--r-- | vapi/sysprof-capture-4.vapi | 322 |
19 files changed, 405 insertions, 77 deletions
diff --git a/backends/bluez/bluez-backend.vala b/backends/bluez/bluez-backend.vala index 5d659ba1..7c9744aa 100644 --- a/backends/bluez/bluez-backend.vala +++ b/backends/bluez/bluez-backend.vala @@ -658,7 +658,7 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend */ public override async void prepare () throws DBusError { - Internal.profiling_start ("preparing BlueZ.Backend"); + var profiling = Internal.profiling_start ("preparing BlueZ.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -786,7 +786,7 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing BlueZ.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/bluez/bluez-persona-store.vala b/backends/bluez/bluez-persona-store.vala index 7c455c58..5e0a3d13 100644 --- a/backends/bluez/bluez-persona-store.vala +++ b/backends/bluez/bluez-persona-store.vala @@ -752,22 +752,23 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore org.bluez.obex.PhonebookAccess? obex_pbap = null; var success = true; - try + if (this._update_contacts_cancellable != null) { - if (this._update_contacts_cancellable != null) - { - /* There’s an ongoing _update_contacts() call. Since downloading - * the address book takes a long time (tens of seconds), we don’t - * want to cancel the ongoing operation. Just return - * immediately. */ - debug ("Not updating contacts due to ongoing update operation."); - return; - } + /* There’s an ongoing _update_contacts() call. Since downloading + * the address book takes a long time (tens of seconds), we don’t + * want to cancel the ongoing operation. Just return + * immediately. */ + debug ("Not updating contacts due to ongoing update operation."); + return; + } + + var profiling = Internal.profiling_start ("updating BlueZ.PersonaStore (ID: %s) " + + "contacts", this.id); - Internal.profiling_start ("updating BlueZ.PersonaStore (ID: %s) " + - "contacts", this.id); + debug ("Updating contacts."); - debug ("Updating contacts."); + try + { string path; HashTable<string, Variant> props; @@ -889,8 +890,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore success == true && this._photos_up_to_date == false; this._schedule_update_contacts (new_download_photos); - Internal.profiling_end ("updating BlueZ.PersonaStore (ID: %s) " + - "contacts", this.id); + Internal.profiling_end ((owned) profiling); } } @@ -1044,7 +1044,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore */ public override async void prepare () throws PersonaStoreError { - Internal.profiling_start ("preparing BlueZ.PersonaStore (ID: %s)", + var profiling = Internal.profiling_start ("preparing BlueZ.PersonaStore (ID: %s)", this.id); if (this._is_prepared || this._prepare_pending) @@ -1108,7 +1108,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing BlueZ.PersonaStore (ID: %s)", this.id); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/dummy/lib/dummy-backend.vala b/backends/dummy/lib/dummy-backend.vala index 5ba8dafc..bbd5fa89 100644 --- a/backends/dummy/lib/dummy-backend.vala +++ b/backends/dummy/lib/dummy-backend.vala @@ -238,7 +238,7 @@ public class FolksDummy.Backend : Folks.Backend */ public override async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing Dummy.Backend"); + var profiling = Internal.profiling_start ("preparing Dummy.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -262,7 +262,7 @@ public class FolksDummy.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing Dummy.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/dummy/lib/dummy-persona-store.vala b/backends/dummy/lib/dummy-persona-store.vala index 5772160d..7c63430d 100644 --- a/backends/dummy/lib/dummy-persona-store.vala +++ b/backends/dummy/lib/dummy-persona-store.vala @@ -572,7 +572,7 @@ public class FolksDummy.PersonaStore : Folks.PersonaStore */ public override async void prepare () throws PersonaStoreError { - Internal.profiling_start ("preparing Dummy.PersonaStore (ID: %s)", + var profiling = Internal.profiling_start ("preparing Dummy.PersonaStore (ID: %s)", this.id); if (this._is_prepared == true || this._prepare_pending == true) @@ -606,7 +606,7 @@ public class FolksDummy.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing Dummy.PersonaStore"); + Internal.profiling_end ((owned) profiling); } diff --git a/backends/eds/eds-backend.vala b/backends/eds/eds-backend.vala index 5f2c632e..fd008148 100644 --- a/backends/eds/eds-backend.vala +++ b/backends/eds/eds-backend.vala @@ -196,7 +196,7 @@ public class Folks.Backends.Eds.Backend : Folks.Backend */ public override async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing Eds.Backend"); + var profiling = Internal.profiling_start ("preparing Eds.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -231,7 +231,7 @@ public class Folks.Backends.Eds.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing Eds.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala index 2193c0ed..0f4a2086 100644 --- a/backends/eds/lib/edsf-persona-store.vala +++ b/backends/eds/lib/edsf-persona-store.vala @@ -697,7 +697,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore */ public override async void prepare () throws PersonaStoreError { - Internal.profiling_start ("preparing Edsf.PersonaStore (ID: %s)", + var profiling = Internal.profiling_start ("preparing Edsf.PersonaStore (ID: %s)", this.id); if (this._is_prepared == true || this._prepare_pending == true) @@ -1020,7 +1020,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing Edsf.PersonaStore"); + Internal.profiling_end ((owned) profiling); } private PersonaDetail _eds_field_name_to_folks_persona_detail ( diff --git a/backends/key-file/kf-backend.vala b/backends/key-file/kf-backend.vala index 79ac5eda..940003b2 100644 --- a/backends/key-file/kf-backend.vala +++ b/backends/key-file/kf-backend.vala @@ -173,7 +173,7 @@ public class Folks.Backends.Kf.Backend : Folks.Backend */ public override async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing Kf.Backend"); + var profiling = Internal.profiling_start ("preparing Kf.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -221,7 +221,7 @@ public class Folks.Backends.Kf.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing Kf.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/key-file/kf-persona-store.vala b/backends/key-file/kf-persona-store.vala index fd6de12d..d234990a 100644 --- a/backends/key-file/kf-persona-store.vala +++ b/backends/key-file/kf-persona-store.vala @@ -183,7 +183,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore */ public override async void prepare () { - Internal.profiling_start ("preparing Kf.PersonaStore (ID: %s)", this.id); + var profiling = Internal.profiling_start ("preparing Kf.PersonaStore (ID: %s)", this.id); if (this._is_prepared || this._prepare_pending) { @@ -316,7 +316,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing Kf.PersonaStore (ID: %s)", this.id); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/ofono/ofono-backend.vala b/backends/ofono/ofono-backend.vala index 9983b018..f0f374b8 100644 --- a/backends/ofono/ofono-backend.vala +++ b/backends/ofono/ofono-backend.vala @@ -167,7 +167,7 @@ public class Folks.Backends.Ofono.Backend : Folks.Backend */ public override async void prepare () throws DBusError { - Internal.profiling_start ("preparing Ofono.Backend"); + var profiling = Internal.profiling_start ("preparing Ofono.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -213,7 +213,7 @@ public class Folks.Backends.Ofono.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing Ofono.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/ofono/ofono-persona-store.vala b/backends/ofono/ofono-persona-store.vala index 711ec7b2..ae3dd6fb 100644 --- a/backends/ofono/ofono-persona-store.vala +++ b/backends/ofono/ofono-persona-store.vala @@ -192,7 +192,7 @@ public class Folks.Backends.Ofono.PersonaStore : Folks.PersonaStore */ public override async void prepare () throws IOError, DBusError { - Internal.profiling_start ("preparing Ofono.PersonaStore (ID: %s)", + var profiling = Internal.profiling_start ("preparing Ofono.PersonaStore (ID: %s)", this.id); if (this._is_prepared || this._prepare_pending) @@ -252,7 +252,7 @@ public class Folks.Backends.Ofono.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing Ofono.PersonaStore (ID: %s)", this.id); + Internal.profiling_end ((owned) profiling); } /** diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala index 510c0bac..2f390f12 100644 --- a/backends/telepathy/lib/tpf-persona-store.vala +++ b/backends/telepathy/lib/tpf-persona-store.vala @@ -467,7 +467,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore */ public override async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing Tpf.PersonaStore (ID: %s)", this.id); + var profiling_prepare = Internal.profiling_start ("preparing Tpf.PersonaStore (ID: %s)", this.id); if (this._is_prepared || this._prepare_pending) { @@ -542,15 +542,15 @@ public class Tpf.PersonaStore : Folks.PersonaStore this._logger_invalidated_cb); this._logger.favourite_contacts_changed.connect ( this._favourite_contacts_changed_cb); - Internal.profiling_start ("initialising favourite contacts in " + + + var profiling = Internal.profiling_start ("initialising favourite contacts in " + "Tpf.PersonaStore (ID: %s)", this.id); this._initialise_favourite_contacts.begin ((o, r) => { try { this._initialise_favourite_contacts.end (r); - Internal.profiling_end ("initialising favourite " + - "contacts in Tpf.PersonaStore (ID: %s)", this.id); + Internal.profiling_end ((owned) profiling); } catch (GLib.Error e) { @@ -591,7 +591,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore this._prepare_pending = false; } - Internal.profiling_end ("preparing Tpf.PersonaStore (ID: %s)", this.id); + Internal.profiling_end ((owned) profiling_prepare); } private void _account_manager_invalidated_cb (uint domain, int code, @@ -750,7 +750,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore debug ("_notify_connection_cb_async() for Tpf.PersonaStore %p ('%s').", this, this.id); - Internal.profiling_start ("notify connection for Tpf.PersonaStore " + + var profiling = Internal.profiling_start ("notify connection for Tpf.PersonaStore " + "(ID: %s)", this.id); /* Ensure the connection is prepared as necessary. */ @@ -852,8 +852,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore this._self_contact_changed_cb (this._conn, null); this._contact_list_state_changed_cb (this._conn, null); - Internal.profiling_end ("notify connection for Tpf.PersonaStore " + - "(ID: %s)", this.id); + Internal.profiling_end ((owned) profiling); } private void _marshall_supported_fields () diff --git a/backends/telepathy/tp-backend.vala b/backends/telepathy/tp-backend.vala index 7877ca02..71cfc84d 100644 --- a/backends/telepathy/tp-backend.vala +++ b/backends/telepathy/tp-backend.vala @@ -155,7 +155,7 @@ public class Folks.Backends.Tp.Backend : Folks.Backend */ public override async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing Tp.Backend"); + var profiling = Internal.profiling_start ("preparing Tp.Backend"); if (this._is_prepared || this._prepare_pending) { @@ -192,7 +192,7 @@ public class Folks.Backends.Tp.Backend : Folks.Backend this._prepare_pending = false; } - Internal.profiling_end ("preparing Tp.Backend"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/folks/backend-store.vala b/folks/backend-store.vala index e3f97177..11c37ac9 100644 --- a/folks/backend-store.vala +++ b/folks/backend-store.vala @@ -276,7 +276,7 @@ public class Folks.BackendStore : Object { */ public async void prepare () { - Internal.profiling_start ("preparing BackendStore"); + var profiling = Internal.profiling_start ("preparing BackendStore"); /* (re-)load the list of disabled backends */ yield this._load_disabled_backend_names (); @@ -287,7 +287,7 @@ public class Folks.BackendStore : Object { this.notify_property ("is-prepared"); } - Internal.profiling_end ("preparing BackendStore"); + Internal.profiling_end ((owned) profiling); } /** @@ -305,7 +305,7 @@ public class Folks.BackendStore : Object { { assert (Module.supported()); - Internal.profiling_start ("loading backends in BackendStore"); + var profiling = Internal.profiling_start ("loading backends in BackendStore"); yield this.prepare (); @@ -400,7 +400,7 @@ public class Folks.BackendStore : Object { yield; } - Internal.profiling_end ("loading backends in BackendStore"); + Internal.profiling_end ((owned) profiling); } /* This method is not safe to call multiple times concurrently, since there's diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala index fb801001..831507b7 100644 --- a/folks/individual-aggregator.vala +++ b/folks/individual-aggregator.vala @@ -695,7 +695,7 @@ public class Folks.IndividualAggregator : Object */ public async void prepare () throws GLib.Error { - Internal.profiling_start ("preparing IndividualAggregator"); + var profiling = Internal.profiling_start ("preparing IndividualAggregator"); /* Once this async function returns, all the {@link Backend}s will have * been prepared (though no {@link PersonaStore}s are guaranteed to be @@ -751,7 +751,7 @@ public class Folks.IndividualAggregator : Object this._prepare_pending = false; } - Internal.profiling_end ("preparing IndividualAggregator"); + Internal.profiling_end ((owned) profiling); } /** diff --git a/folks/internal.vala b/folks/internal.vala index 1d4030f2..35ec807a 100644 --- a/folks/internal.vala +++ b/folks/internal.vala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Collabora Ltd. + * Copyright 2011,2023 Collabora Ltd. * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -16,6 +16,7 @@ * * Authors: * Raul Gutierrez Segales <raul.gutierrez.segales@collabora.co.uk> + * Corentin Noël <corentin.noel@collabora.com> */ using GLib; @@ -38,17 +39,6 @@ namespace Folks.Internal return true; } -#if ENABLE_PROFILING - /* See: http://people.gnome.org/~federico/news-2006-03.html#timeline-tools */ - [PrintfFormat] - private static void profiling_markv (string format, va_list args) - { - var formatted = format.vprintf (args); - var str = "MARK: %s-%p: %s".printf (Environment.get_prgname (), Thread.self<void> (), formatted); - access (str, F_OK); - } -#endif - /** * Emit a profiling point. * @@ -57,14 +47,27 @@ namespace Folks.Internal * * @param format printf-style message format * @param ... message arguments - * @since 0.7.2 */ [PrintfFormat] - public static void profiling_point (string format, ...) + public inline void profiling_point (string format, ...) { #if ENABLE_PROFILING var args = va_list (); - Internal.profiling_markv (format, args); + Sysprof.Collector.log (0, "folks", format.vprintf(args)); +#endif + } + + [Compact] + public class ProfileBlock + { +#if ENABLE_PROFILING + internal string name; + internal int64 start; + + internal ProfileBlock (owned string name) { + this.name = (owned) name; + this.start = Sysprof.CAPTURE_CURRENT_TIME; + } #endif } @@ -79,13 +82,14 @@ namespace Folks.Internal * * @param format printf-style message format * @param ... message arguments - * @since 0.7.2 */ - public static void profiling_start (string format, ...) + public inline ProfileBlock? profiling_start (string format, ...) { #if ENABLE_PROFILING var args = va_list (); - Internal.profiling_markv ("START: " + format, args); + return new ProfileBlock (format.vprintf (args)); +#else + return null; #endif } @@ -98,15 +102,12 @@ namespace Folks.Internal * This is typically used in a pair with {@link Internal.profiling_start} to * delimit blocks of processing which need timing. * - * @param format printf-style message format - * @param ... message arguments - * @since 0.7.2 + * @param block the ProfileBlock given by profiling_start */ - public static void profiling_end (string format, ...) + public inline void profiling_end (owned ProfileBlock? block) { #if ENABLE_PROFILING - var args = va_list (); - Internal.profiling_markv ("END: " + format, args); + Sysprof.Collector.mark (block.start, Sysprof.CAPTURE_CURRENT_TIME - block.start, "folks", block.name); #endif } } diff --git a/folks/meson.build b/folks/meson.build index 821a3099..b86f3cc7 100644 --- a/folks/meson.build +++ b/folks/meson.build @@ -16,7 +16,8 @@ libfolks_internal_deps = [ libfolks_internal_vala_flags = [] if get_option('profiling') - libfolks_internal_vala_flags += '-DENABLE_PROFILING' + libfolks_internal_vala_flags += '--define=ENABLE_PROFILING' + libfolks_internal_deps += sysprof_dep endif libfolks_internal = static_library('folks-internal', diff --git a/meson.build b/meson.build index 9971f7a2..36329572 100644 --- a/meson.build +++ b/meson.build @@ -135,6 +135,11 @@ if inspect_tool_enabled ) endif +if get_option('profiling') + sysprof_dep = dependency('sysprof-capture-4', version: '>= 3.38.0') + add_project_arguments(['--vapidir', meson.current_source_dir() / 'vapi'], language: 'vala') +endif + # Configuration #------------------------------------------------- conf = configuration_data() diff --git a/meson_options.txt b/meson_options.txt index f631e6bd..361f30cf 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,7 +8,7 @@ option('zeitgeist', type: 'boolean', value: false, description: 'build Zeitgeist option('import_tool', type: 'boolean', value: true, description: 'Enable building the meta-contact import tool') option('inspect_tool', type: 'boolean', value: true, description: 'Enable building the data inspection tool') # Profiling -option('profiling', type: 'boolean', value: false, description: 'Enable profiling code') +option('profiling', type: 'boolean', value: false, description: 'Enable profiling using sysprof') # Test options option('tests', type: 'boolean', value: true, description: 'Build tests programs') option('installed_tests', type: 'boolean', value: false, description: 'Install test programs') diff --git a/vapi/sysprof-capture-4.vapi b/vapi/sysprof-capture-4.vapi new file mode 100644 index 00000000..fac018f0 --- /dev/null +++ b/vapi/sysprof-capture-4.vapi @@ -0,0 +1,322 @@ +[CCode (cheader_filename = "sysprof-capture.h")] +namespace Sysprof { + [SimpleType] + public struct Address : uint64 { + public bool is_context_switch (out AddressContext context); + public int compare (Sysprof.Address b); + } + + [SimpleType] + public struct CaptureAddress : uint64 { + public int compare (Sysprof.CaptureAddress b); + } + + namespace Collector { + public void init (); + public bool is_active (); + public void allocate (Sysprof.CaptureAddress alloc_addr, int64 alloc_size, Sysprof.BacktraceFunc backtrace_func); + public void sample (Sysprof.BacktraceFunc backtrace_func); + public void mark (int64 time, int64 duration, string group, string mark, string? message = null); + [ PrintfFormat ] + public void mark_printf (int64 time, int64 duration, string group, string mark, string message_format, ...); + public void mark_vprintf (int64 time, int64 duration, string group, string mark, string message_format, va_list args); + public void log (int severity, string domain, string message); + [ PrintfFormat ] + public void log_printf (int severity, string domain, string message_format, ...); + public uint request_counters (uint n_counters); + public void define_counters (Sysprof.CaptureCounter[] counters); + public void set_counters ([CCode (array_length = false)] uint[] counters_ids, Sysprof.CaptureCounterValue[] values); + } + + [CCode (ref_function = "sysprof_capture_condition_ref", unref_function = "sysprof_capture_condition_unref", has_type_id = false)] + public class CaptureCondition { + public CaptureCondition.and (Sysprof.CaptureCondition left, Sysprof.CaptureCondition right); + public CaptureCondition.or (Sysprof.CaptureCondition left, Sysprof.CaptureCondition right); + public CaptureCondition.where_counter_in (uint[] counters); + public CaptureCondition.where_file (string path); + public CaptureCondition.where_pid_in (int32[] pids); + public CaptureCondition.where_time_between (int64 begin_time, int64 end_time); + public CaptureCondition.where_type_in (Sysprof.CaptureFrameType[] types); + public Sysprof.CaptureCondition copy (); + public bool match (Sysprof.CaptureFrame frame); + } + + [CCode (ref_function = "sysprof_capture_cursor_ref", unref_function = "sysprof_capture_cursor_unref", has_type_id = false)] + public class CaptureCursor { + public CaptureCursor (Sysprof.CaptureReader reader); + public unowned Sysprof.CaptureReader get_reader (); + public void add_condition (Sysprof.CaptureCondition condition); + public void @foreach (Sysprof.CaptureCursorCallback callback); + public void reset (); + public void reverse (); + } + + [CCode (ref_function = "sysprof_capture_reader_ref", unref_function = "sysprof_capture_reader_unref", has_type_id = false)] + public class CaptureReader { + public CaptureReader (string filename); + public CaptureReader.from_fd (int fd); + public bool get_stat (out unowned Sysprof.CaptureStat st_buf); + public bool peek_frame (out Sysprof.CaptureFrame frame); + public bool peek_type (out Sysprof.CaptureFrameType type); + public bool read_file_fd (string path, int fd); + public bool reset (); + public bool save_as (string filename); + public bool skip (); + public bool splice (Sysprof.CaptureWriter dest); + public int64 get_end_time (); + public int64 get_start_time (); + public int get_byte_order (); + public string get_filename (); + public string get_time (); + public string[] list_files (); + public Sysprof.CaptureReader copy (); + public unowned Sysprof.CaptureAllocation read_allocation (); + public unowned Sysprof.CaptureCounterDefine read_counter_define (); + public unowned Sysprof.CaptureCounterSet read_counter_set (); + public unowned Sysprof.CaptureExit read_exit (); + public unowned Sysprof.CaptureFileChunk find_file (string path); + public unowned Sysprof.CaptureFileChunk read_file (); + public unowned Sysprof.CaptureFork read_fork (); + public unowned Sysprof.CaptureJitmap read_jitmap (); + public unowned Sysprof.CaptureLog read_log (); + public unowned Sysprof.CaptureMap read_map (); + public unowned Sysprof.CaptureMark read_mark (); + public unowned Sysprof.CaptureMetadata read_metadata (); + public unowned Sysprof.CaptureProcess read_process (); + public unowned Sysprof.CaptureSample read_sample (); + public unowned Sysprof.CaptureTimestamp read_timestamp (); + public void set_stat (Sysprof.CaptureStat st_buf); + } + + [CCode (ref_function = "sysprof_capture_writer_ref", unref_function = "sysprof_capture_writer_unref", has_type_id = false)] + public class CaptureWriter { + public CaptureWriter (string filename, size_t buffer_size); + public CaptureWriter.from_env (size_t buffer_size); + public CaptureWriter.from_fd (int fd, size_t buffer_size); + public bool add_allocation_copy (int64 time, int cpu, int32 pid, int32 tid, Sysprof.CaptureAddress[] alloc_addr, Sysprof.CaptureAddress[] addrs); + public bool add_allocation (int64 time, int cpu, int32 pid, int32 tid, Sysprof.CaptureAddress[] alloc_addr, Sysprof.BacktraceFunc backtrace_func); + public bool add_exit (int64 time, int cpu, int32 pid); + public bool add_file_fd (int64 time, int cpu, int32 pid, string path, int fd); + public bool add_file (int64 time, int cpu, int32 pid, string path, bool is_last, uint8[] data); + public bool add_fork (int64 time, int cpu, int32 pid, int32 child_pid); + public bool add_jitmap (string name); + public bool add_log (int64 time, int cpu, int32 pid, int severity, string domain, string message); + public bool add_map (int64 time, int cpu, int32 pid, uint64 start, uint64 end, uint64 offset, uint64 inode, string filename); + public bool add_mark (int64 time, int cpu, int32 pid, uint64 duration, string group, string name, string message); + public bool add_metadata (int64 time, int cpu, int32 pid, string id, string metadata, ssize_t metadata_len = -1); + public bool add_process (int64 time, int cpu, int32 pid, string cmdline); + public bool add_sample (int64 time, int cpu, int32 pid, int32 tid, Sysprof.CaptureAddress[] addrs); + public bool add_timestamp (int64 time, int cpu, int32 pid); + public bool cat (Sysprof.CaptureReader reader); + public bool define_counters (int64 time, int cpu, int32 pid, Sysprof.CaptureCounter[] counters); + public bool flush (); + public bool save_as (string filename); + public bool set_counters (int64 time, int cpu, int32 pid, Sysprof.CaptureCounter[] counters, Sysprof.CaptureCounterValue[] values); + public bool splice (Sysprof.CaptureWriter dest); + public size_t get_buffer_size (); + public Sysprof.CaptureReader create_reader (); + public uint request_counter (uint n_counters); + public void stat (out Sysprof.CaptureStat stat); + } + + [Compact] + public class CaptureJitmapIter { + void* p1; + void* p2; + uint u1; + void* p3; + void* p4; + [CCode (cname="sysprof_capture_jitmap_iter_init")] + public CaptureJitmapIter (Sysprof.CaptureJitmap jitmap); + public bool next (ref Sysprof.CaptureAddress addr, out unowned string[] path); + } + + public struct CaptureStat { + size_t frame_count[16]; + } + + public struct CaptureCounterValue { + int64 v64; + double vdbl; + } + + public struct CaptureFileHeader { + uint32 magic; + uint32 version; + uint32 little_endian; + uint32 padding; + char capture_time[64]; + int64 time; + int64 end_time; + char suffix[168]; + } + + public struct CaptureFrame { + uint16 len; + int16 cpu; + int32 pid; + int64 time; + uint32 type; + uint32 padding1; + uint32 padding2; + uint8[] data; + } + + public struct CaptureMap { + Sysprof.CaptureFrame frame; + uint64 start; + uint64 end; + uint64 offset; + uint64 inode; + char[] filename; + } + + public struct CaptureJitmap { + Sysprof.CaptureFrame frame; + uint32 n_jitmaps; + uint8[] data; + } + + public struct CaptureProcess { + Sysprof.CaptureFrame frame; + char[] cmdline; + } + + public struct CaptureSample { + Sysprof.CaptureFrame frame; + uint32 n_addrs; + uint32 padding1; + int32 tid; + Sysprof.CaptureAddress[] addrs; + } + + public struct CaptureFork { + Sysprof.CaptureFrame frame; + int32 child_pid; + } + + public struct CaptureExit { + Sysprof.CaptureFrame frame; + } + + public struct CaptureTimestamp { + Sysprof.CaptureFrame frame; + } + + public struct CaptureCounter { + char category[32]; + char name[32]; + char description[52]; + uint32 id; + uint32 type; + } + + public struct CaptureCounterDefine { + Sysprof.CaptureFrame frame; + uint32 n_counters; + uint32 padding1; + uint32 padding2; + Sysprof.CaptureCounter[] counters; + } + + public struct CaptureCounterValues { + uint32 ids[8]; + Sysprof.CaptureCounterValue values[8]; + } + + public struct CaptureCounterSet { + Sysprof.CaptureFrame frame; + uint32 n_values; + uint32 padding1; + uint32 padding2; + Sysprof.CaptureCounterValues[] values; + } + + public struct CaptureMark { + Sysprof.CaptureFrame frame; + int64 duration; + char group[24]; + char name[40]; + char[] message; + } + + public struct CaptureMetadata { + Sysprof.CaptureFrame frame; + char id[40]; + char[] metadata; + } + + public struct CaptureLog { + Sysprof.CaptureFrame frame; + uint32 severity; + uint32 padding1; + uint32 padding2; + char domain[32]; + char[] message; + } + + public struct CaptureFileChunk { + Sysprof.CaptureFrame frame; + uint32 is_last; + uint32 padding1; + uint32 len; + char path[256]; + uint8[] data; + } + + public struct CaptureAllocation { + Sysprof.CaptureFrame frame; + Sysprof.CaptureAddress alloc_addr; + int64 alloc_size; + int32 tid; + uint32 n_addrs; + uint32 padding1; + Sysprof.CaptureAddress[] addrs; + } + + public enum CaptureFrameType { + TIMESTAMP, + SAMPLE, + MAP, + PROCESS, + FORK, + EXIT, + JITMAP, + CTRDEF, + CTRSET, + MARK, + METADATA, + LOG, + FILE_CHUNK, + ALLOCATION, + } + + public enum AddressContext { + NONE, + HYPERVISOR, + KERNEL, + USER, + GUEST, + GUEST_KERNEL, + GUEST_USER; + public unowned string to_string (); + } + + [CCode (cheader_filename = "sysprof-capture.h", instance_pos = 2.9)] + public delegate int BacktraceFunc (ref Sysprof.CaptureAddress[] addrs); + [CCode (cheader_filename = "sysprof-capture.h", instance_pos = 1.9)] + public delegate bool CaptureCursorCallback (Sysprof.CaptureFrame frame); + [CCode (cname = "SYSPROF_CAPTURE_CURRENT_TIME")] + public const int64 CAPTURE_CURRENT_TIME; + [CCode (cname = "SYSPROF_CAPTURE_COUNTER_INT64")] + public const uint32 CAPTURE_COUNTER_INT64; + [CCode (cname = "SYSPROF_CAPTURE_COUNTER_DOUBLE")] + public const uint32 CAPTURE_COUNTER_DOUBLE; + [CCode (cname = "SYSPROF_CAPTURE_ADDRESS_FORMAT")] + public const string CAPTURE_ADDRESS_FORMAT; + [CCode (cname = "SYSPROF_CAPTURE_JITMAP_MARK")] + public const uint64 CAPTURE_JITMAP_MARK; + public static int memfd_create (string desc); + [CCode (cname = "sysprof_getpagesize")] + public static size_t get_page_size (); +} |