Changeset 201809 in webkit


Ignore:
Timestamp:
Jun 8, 2016, 10:31:47 AM (9 years ago)
Author:
beidson@apple.com
Message:

Make CrossThreadCopier more efficient (fewer copies!).
https://bugs.webkit.org/show_bug.cgi?id=158456

Reviewed by Alex Christensen.

Source/WTF:

Previously, we'd run all arguments through CrossThreadCopier, then immediately make
an unnecessary copy of the result during lambda capture.

Instead, we should just put the CrossThreadCopier generated objects directly in lambdas,
which are then captured by NoncopyableFunctions.

This reduces the number of constructor calls per argument from 2 copies to 1 move.

  • wtf/CrossThreadTask.h:

(WTF::CrossThreadTask::CrossThreadTask):
(WTF::createCrossThreadTask):

Tools:

  • TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r201783 r201809  
     12016-06-08  Brady Eidson  <beidson@apple.com>
     2
     3        Make CrossThreadCopier more efficient (fewer copies!).
     4        https://bugs.webkit.org/show_bug.cgi?id=158456
     5
     6        Reviewed by Alex Christensen.
     7
     8        Previously, we'd run all arguments through CrossThreadCopier, then immediately make
     9        an unnecessary copy of the result during lambda capture.
     10
     11        Instead, we should just put the CrossThreadCopier generated objects directly in lambdas,
     12        which are then captured by NoncopyableFunctions.
     13
     14        This reduces the number of constructor calls per argument from 2 copies to 1 move.
     15
     16        * wtf/CrossThreadTask.h:
     17        (WTF::CrossThreadTask::CrossThreadTask):
     18        (WTF::createCrossThreadTask):
     19
    1202016-06-07  Filip Pizlo  <fpizlo@apple.com>
    221
  • trunk/Source/WTF/wtf/CrossThreadTask.h

    r201673 r201809  
    3333
    3434class CrossThreadTask {
     35    template<class T>
     36    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)());
     37    template<class T, class P1, class MP1>
     38    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1), const P1&);
     39    template<class T, class P1, class MP1, class P2, class MP2>
     40    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2), const P1&, const P2&);
     41    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3>
     42    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3), const P1&, const P2&, const P3&);
     43    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3, class P4, class MP4>
     44    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3, MP4), const P1&, const P2&, const P3&, const P4&);
     45    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3, class P4, class MP4, class P5, class MP5>
     46    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3, MP4, MP5), const P1&, const P2&, const P3&, const P4&, const P5&);
     47    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3, class P4, class MP4, class P5, class MP5, class P6, class MP6>
     48    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3, MP4, MP5, MP6), const P1&, const P2&, const P3&, const P4&, const P5&, const P6&);
     49    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3, class P4, class MP4, class P5, class MP5, class P6, class MP6, class P7, class MP7>
     50    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3, MP4, MP5, MP6, MP7), const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&);
     51    template<class T, class P1, class MP1, class P2, class MP2, class P3, class MP3, class P4, class MP4, class P5, class MP5, class P6, class MP6, class P7, class MP7, class P8, class MP8>
     52    friend CrossThreadTask createCrossThreadTask(T&, void (T::*)(MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8), const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&, const P8&);
    3553public:
    3654    CrossThreadTask() = default;
     
    3957        : m_taskFunction(WTFMove(taskFunction))
    4058    {
    41         ASSERT(taskFunction);
     59        ASSERT(m_taskFunction);
    4260    }
    4361
     
    5169};
    5270
    53 template <typename T, typename... Arguments>
    54 class CrossThreadTaskImpl final : public CrossThreadTask {
    55 public:
    56     CrossThreadTaskImpl(T* callee, void (T::*method)(Arguments...), Arguments&&... arguments)
    57     {
    58         m_taskFunction = [callee, method, arguments...] {
    59             (callee->*method)(arguments...);
    60         };
    61     }
    62 };
    63 
    64 template <typename... Arguments>
    65 class CrossThreadTaskStaticImpl final : public CrossThreadTask {
    66 public:
    67     CrossThreadTaskStaticImpl(void (*method)(Arguments...), Arguments&&... arguments)
    68     {
    69         m_taskFunction = [method, arguments...] {
    70             method(arguments...);
    71         };
    72     }
    73 };
    74 
    7571template<typename T>
    7672CrossThreadTask createCrossThreadTask(
     
    7874    void (T::*method)())
    7975{
    80     return CrossThreadTaskImpl<T>(&callee, method);
     76    return CrossThreadTask([callee = &callee, method]() mutable {
     77        (callee->*method)();
     78    });
    8179}
    8280
     
    8785    const P1& parameter1)
    8886{
    89     return CrossThreadTaskImpl<T, MP1>(
    90         &callee,
    91         method,
    92         WTF::CrossThreadCopier<P1>::copy(parameter1));
     87    return CrossThreadTask([callee = &callee, method,
     88        p1 = CrossThreadCopier<P1>::copy(parameter1)]() mutable {
     89        (callee->*method)(p1);
     90    });
    9391}
    9492
     
    10098    const P2& parameter2)
    10199{
    102     return CrossThreadTaskImpl<T, MP1, MP2>(
    103         &callee,
    104         method,
    105         WTF::CrossThreadCopier<P1>::copy(parameter1),
    106         WTF::CrossThreadCopier<P2>::copy(parameter2));
    107 
     100    return CrossThreadTask([callee = &callee, method,
     101        p1 = CrossThreadCopier<P1>::copy(parameter1),
     102        p2 = CrossThreadCopier<P2>::copy(parameter2)]() mutable {
     103        (callee->*method)(p1, p2);
     104    });
    108105}
    109106
     
    116113    const P3& parameter3)
    117114{
    118     return CrossThreadTaskImpl<T, MP1, MP2, MP3>(
    119         &callee,
    120         method,
    121         WTF::CrossThreadCopier<P1>::copy(parameter1),
    122         WTF::CrossThreadCopier<P2>::copy(parameter2),
    123         WTF::CrossThreadCopier<P3>::copy(parameter3));
     115    return CrossThreadTask([callee = &callee, method,
     116        p1 = CrossThreadCopier<P1>::copy(parameter1),
     117        p2 = CrossThreadCopier<P2>::copy(parameter2),
     118        p3 = CrossThreadCopier<P3>::copy(parameter3)]() mutable {
     119        (callee->*method)(p1, p2, p3);
     120    });
    124121}
    125122
     
    131128    const P3& parameter3)
    132129{
    133     return CrossThreadTaskStaticImpl<MP1, MP2, MP3>(
    134         method,
    135         WTF::CrossThreadCopier<P1>::copy(parameter1),
    136         WTF::CrossThreadCopier<P2>::copy(parameter2),
    137         WTF::CrossThreadCopier<P3>::copy(parameter3));
     130    return CrossThreadTask([method,
     131        p1 = CrossThreadCopier<P1>::copy(parameter1),
     132        p2 = CrossThreadCopier<P2>::copy(parameter2),
     133        p3 = CrossThreadCopier<P3>::copy(parameter3)]() mutable {
     134        method(p1, p2, p3);
     135    });
    138136}
    139137
     
    147145    const P4& parameter4)
    148146{
    149     return CrossThreadTaskImpl<T, MP1, MP2, MP3, MP4>(
    150         &callee,
    151         method,
    152         WTF::CrossThreadCopier<P1>::copy(parameter1),
    153         WTF::CrossThreadCopier<P2>::copy(parameter2),
    154         WTF::CrossThreadCopier<P3>::copy(parameter3),
    155         WTF::CrossThreadCopier<P4>::copy(parameter4));
     147    return CrossThreadTask([callee = &callee, method,
     148        p1 = CrossThreadCopier<P1>::copy(parameter1),
     149        p2 = CrossThreadCopier<P2>::copy(parameter2),
     150        p3 = CrossThreadCopier<P3>::copy(parameter3),
     151        p4 = CrossThreadCopier<P4>::copy(parameter4)]() mutable {
     152        (callee->*method)(p1, p2, p3, p4);
     153    });
    156154}
    157155
     
    166164    const P5& parameter5)
    167165{
    168     return CrossThreadTaskImpl<T, MP1, MP2, MP3, MP4, MP5>(
    169         &callee,
    170         method,
    171         WTF::CrossThreadCopier<P1>::copy(parameter1),
    172         WTF::CrossThreadCopier<P2>::copy(parameter2),
    173         WTF::CrossThreadCopier<P3>::copy(parameter3),
    174         WTF::CrossThreadCopier<P4>::copy(parameter4),
    175         WTF::CrossThreadCopier<P5>::copy(parameter5));
     166    return CrossThreadTask([callee = &callee, method,
     167        p1 = CrossThreadCopier<P1>::copy(parameter1),
     168        p2 = CrossThreadCopier<P2>::copy(parameter2),
     169        p3 = CrossThreadCopier<P3>::copy(parameter3),
     170        p4 = CrossThreadCopier<P4>::copy(parameter4),
     171        p5 = CrossThreadCopier<P5>::copy(parameter5)]() mutable {
     172        (callee->*method)(p1, p2, p3, p4, p5);
     173    });
    176174}
    177175
     
    187185    const P6& parameter6)
    188186{
    189     return CrossThreadTaskImpl<T, MP1, MP2, MP3, MP4, MP5, MP6>(
    190         &callee,
    191         method,
    192         WTF::CrossThreadCopier<P1>::copy(parameter1),
    193         WTF::CrossThreadCopier<P2>::copy(parameter2),
    194         WTF::CrossThreadCopier<P3>::copy(parameter3),
    195         WTF::CrossThreadCopier<P4>::copy(parameter4),
    196         WTF::CrossThreadCopier<P5>::copy(parameter5),
    197         WTF::CrossThreadCopier<P6>::copy(parameter6));
     187    return CrossThreadTask([callee = &callee, method,
     188        p1 = CrossThreadCopier<P1>::copy(parameter1),
     189        p2 = CrossThreadCopier<P2>::copy(parameter2),
     190        p3 = CrossThreadCopier<P3>::copy(parameter3),
     191        p4 = CrossThreadCopier<P4>::copy(parameter4),
     192        p5 = CrossThreadCopier<P5>::copy(parameter5),
     193        p6 = CrossThreadCopier<P6>::copy(parameter6)]() mutable {
     194        (callee->*method)(p1, p2, p3, p4, p5, p6);
     195    });
    198196}
    199197
     
    210208    const P7& parameter7)
    211209{
    212     return CrossThreadTaskImpl<T, MP1, MP2, MP3, MP4, MP5, MP6, MP7>(
    213         &callee,
    214         method,
    215         WTF::CrossThreadCopier<P1>::copy(parameter1),
    216         WTF::CrossThreadCopier<P2>::copy(parameter2),
    217         WTF::CrossThreadCopier<P3>::copy(parameter3),
    218         WTF::CrossThreadCopier<P4>::copy(parameter4),
    219         WTF::CrossThreadCopier<P5>::copy(parameter5),
    220         WTF::CrossThreadCopier<P6>::copy(parameter6),
    221         WTF::CrossThreadCopier<P7>::copy(parameter7));
     210    return CrossThreadTask([callee = &callee, method,
     211        p1 = CrossThreadCopier<P1>::copy(parameter1),
     212        p2 = CrossThreadCopier<P2>::copy(parameter2),
     213        p3 = CrossThreadCopier<P3>::copy(parameter3),
     214        p4 = CrossThreadCopier<P4>::copy(parameter4),
     215        p5 = CrossThreadCopier<P5>::copy(parameter5),
     216        p6 = CrossThreadCopier<P6>::copy(parameter6),
     217        p7 = CrossThreadCopier<P7>::copy(parameter7)]() mutable {
     218        (callee->*method)(p1, p2, p3, p4, p5, p6, p7);
     219    });
    222220}
    223221
     
    235233    const P8& parameter8)
    236234{
    237     return CrossThreadTaskImpl<T, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8>(
    238         &callee,
    239         method,
    240         WTF::CrossThreadCopier<P1>::copy(parameter1),
    241         WTF::CrossThreadCopier<P2>::copy(parameter2),
    242         WTF::CrossThreadCopier<P3>::copy(parameter3),
    243         WTF::CrossThreadCopier<P4>::copy(parameter4),
    244         WTF::CrossThreadCopier<P5>::copy(parameter5),
    245         WTF::CrossThreadCopier<P6>::copy(parameter6),
    246         WTF::CrossThreadCopier<P7>::copy(parameter7),
    247         WTF::CrossThreadCopier<P8>::copy(parameter8));
     235    return CrossThreadTask([callee = &callee, method,
     236        p1 = CrossThreadCopier<P1>::copy(parameter1),
     237        p2 = CrossThreadCopier<P2>::copy(parameter2),
     238        p3 = CrossThreadCopier<P3>::copy(parameter3),
     239        p4 = CrossThreadCopier<P4>::copy(parameter4),
     240        p5 = CrossThreadCopier<P5>::copy(parameter5),
     241        p6 = CrossThreadCopier<P6>::copy(parameter6),
     242        p7 = CrossThreadCopier<P7>::copy(parameter7),
     243        p8 = CrossThreadCopier<P8>::copy(parameter8)]() mutable {
     244        (callee->*method)(p1, p2, p3, p4, p5, p6, p7, p8);
     245    });
    248246}
    249247
  • trunk/Tools/ChangeLog

    r201807 r201809  
     12016-06-08  Brady Eidson  <beidson@apple.com>
     2
     3        Make CrossThreadCopier more efficient (fewer copies!).
     4        https://bugs.webkit.org/show_bug.cgi?id=158456
     5
     6        Reviewed by Alex Christensen.
     7
     8        * TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp:
     9        (TestWebKitAPI::TEST):
     10
    1112016-06-07  Filip Pizlo  <fpizlo@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp

    r201806 r201809  
    103103        task.performTask();
    104104    }
    105     ASSERT_STREQ("default_constructor(<default>-0-0) copy_constructor(<default>-1-0) name_constructor(logger-0-0) isolatedCopy() copy_constructor(<default>-1-0) isolatedCopy() copy_constructor(<default>-2-0) isolatedCopy() copy_constructor(logger-1-0) copy_constructor(<default>-2-0) copy_constructor(<default>-3-0) copy_constructor(logger-2-0) copy_constructor(<default>-3-0) copy_constructor(<default>-4-0) copy_constructor(logger-3-0) destructor(logger-2-0) destructor(<default>-3-0) destructor(<default>-2-0) destructor(logger-1-0) destructor(<default>-2-0) destructor(<default>-1-0) testFunction called destructor(logger-3-0) destructor(<default>-4-0) destructor(<default>-3-0) destructor(logger-0-0) destructor(<default>-1-0) destructor(<default>-0-0) ", takeLogStr().c_str());
     105    ASSERT_STREQ("default_constructor(<default>-0-0) copy_constructor(<default>-1-0) name_constructor(logger-0-0) isolatedCopy() copy_constructor(<default>-1-0) isolatedCopy() copy_constructor(<default>-2-0) isolatedCopy() copy_constructor(logger-1-0) move_constructor(<default>-1-1) move_constructor(<default>-2-1) move_constructor(logger-1-1) destructor(logger-1-0) destructor(<default>-2-0) destructor(<default>-1-0) testFunction called destructor(logger-1-1) destructor(<default>-2-1) destructor(<default>-1-1) destructor(logger-0-0) destructor(<default>-1-0) destructor(<default>-0-0) ", takeLogStr().c_str());
    106106}
    107107   
Note: See TracChangeset for help on using the changeset viewer.