
Hi all,
Over the past year, or maybe even longer, I've been annoyed at how long it takes for Inkscape to start. Admittedly, I get easily annoyed because it takes only about 10 seconds for the main window to be drawn, but still.... After that it takes another 10 to 15 seconds before the CPU gets idle again, but during that second period Inkscape can already be used.
On launchpad I've seen reports that this could be related to the number of fonts installed, which could indeed be part of the problem. But I also noticed this across many systems, even when not that many fonts were installed. So I figured that the only way to find out was to do some profiling. I've attached only a part of the profiling output below (If you want all of it then I'll gladly send you the 18 MB file). Roughly the first 10 seconds have been profiled, because I immediately quit Inkscape as soon as the main window was drawn. (Actually the first phase takes a lot longer than 10 seconds when profiling; those 10 seconds have been measured with all debugging and profiling flags disabled)
What I found out was that it is prerender_icon() that causes the biggest part of the delay during those first 10 seconds. Maybe this is a public secret, but I just wanted to share this with you. I have no intention currently of improving this, but this at least allows us to respond accurately to some bug reports.
Regards,
Diederik
Flat profile:
Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 13.69 0.72 0.72 356031 0.00 0.01 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) 6.65 1.07 0.35 435568 0.00 0.00 Inkscape::Preferences::_getNode(Glib::ustring const&, bool) 5.51 1.36 0.29 28329840 0.00 0.00 Inkscape::XML::SimpleNode::attribute(char const*) const 4.85 1.62 0.26 57980026 0.00 0.00 Inkscape::Util::List<Inkscape::XML::AttributeRecord const>::operator->() const 4.18 1.84 0.22 28131371 0.00 0.00 _ZNK8Inkscape4Util10ptr_sharedIcEcvPKT_IcEEv 3.80 2.04 0.20 26795143 0.00 0.00 Inkscape::XML::SimpleNode::next() 3.42 2.22 0.18 32836208 0.00 0.00 Geom::Matrix::operator[](unsigned int) const 2.28 2.34 0.12 1236181 0.00 0.00 nr_object_check_instance_type(void const*, unsigned int) 2.28 2.46 0.12 797442 0.00 0.00 Geom::operator*(Geom::Matrix const&, Geom::Matrix const&) 1.81 2.55 0.10 30331635 0.00 0.00 Inkscape::Util::List<Inkscape::XML::AttributeRecord const>::operator bool() const 1.81 2.65 0.10 virtual thunk to Inkscape::XML::SimpleNode::attribute(char const*) const 1.71 2.74 0.09 1898740 0.00 0.00 Geom::operator*(Geom::Point const&, Geom::Matrix const&) 1.52 2.82 0.08 1661332 0.00 0.00 Geom::Bezier::at1() const 1.52 2.90 0.08 203312 0.00 0.01 nr_arena_shape_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) 1.24 2.96 0.07 9319609 0.00 0.00 Geom::Point::operator[](Geom::Dim2) const 0.95 3.01 0.05 813223 0.00 0.00 boost::shared_ptr<Geom::Curve const>::operator*() const 0.95 3.06 0.05 152487 0.00 0.00 nr_arena_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) 0.76 3.10 0.04 2750545 0.00 0.00 std::vector<Shape::dg_arete, std::allocatorShape::dg_arete
::operator[](unsigned long) const
0.76 3.14 0.04 2036510 0.00 0.00 cr_utils_read_char_from_utf8_buf 0.76 3.18 0.04 1558360 0.00 0.00 Geom::Matrix::operator=(Geom::Matrix const&) 0.76 3.22 0.04 1165706 0.00 0.00 NRArenaShape::Paint::type() const
% the percentage of the total running time of the time program used by this function.
cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it.
self the number of seconds accounted for by this seconds function alone. This is the major sort for this listing.
calls the number of times this function was invoked, if this function is profiled, else blank.
self the average number of milliseconds spent in this ms/call function per call, if this function is profiled, else blank.
total the average number of milliseconds spent in this ms/call function and its descendents per call, if this function is profiled, else blank.
name the name of the function. This is the minor sort for this listing. The index shows the location of the function in the gprof listing. If the index is in parenthesis it shows where it would appear in the gprof listing if it were to be printed.
Call graph (explanation follows)
granularity: each sample hit covers 2 byte(s) for 0.19% of 5.26 seconds
index % time self children called name 0.00 0.27 6/102 Inkscape::queueIconPrerender(Glib::ustring const&, Inkscape::IconSize) [33] 0.00 1.18 26/102 icon_prerender_task(void*) [15] 0.00 3.19 70/102 imageMapNamedCB(_GtkWidget*, void*) [5] [1] 88.3 0.00 4.64 102 prerender_icon(char const*, GtkIconSize, unsigned int) [1] 0.00 4.64 87/87 load_svg_pixels(char const*, unsigned int, unsigned int) [2] 0.00 0.00 182/186 std::set<Glib::ustring, std::lessGlib::ustring, std::allocatorGlib::ustring >::find(Glib::ustring const&) [545] 0.00 0.00 78/82 std::set<Glib::ustring, std::lessGlib::ustring, std::allocatorGlib::ustring >::insert(Glib::ustring const&) [640] 0.00 0.00 87/87 std::map<Glib::ustring, _GdkPixbuf*, std::lessGlib::ustring, std::allocator<std::pair<Glib::ustring const, _GdkPixbuf*> >
::operator[](Glib::ustring const&) [1199]
0.00 0.00 102/102 get_cached_pixbuf(Glib::ustring const&) [1229] 0.00 0.00 87/87 addToIconSet(_GdkPixbuf*, char const*, GtkIconSize, unsigned int) [1466] 0.00 0.00 1/663464 Inkscape::Preferences::get() <cycle 1> [340] 0.00 0.00 1/663464 Inkscape::Preferences::getBool(Glib::ustring const&, bool) <cycle 1> [271] 0.00 0.00 182/186 std::set<Glib::ustring, std::lessGlib::ustring, std::allocatorGlib::ustring >::end() const [6073] 0.00 0.00 102/102 icon_cache_key(char const*, unsigned int) [6298] 0.00 0.00 95/99 std::_Rb_tree_const_iteratorGlib::ustring::operator!=(std::_Rb_tree_const_iteratorGlib::ustring const&) const [6311] 0.00 0.00 87/87 std::_Rb_tree_const_iteratorGlib::ustring::operator==(std::_Rb_tree_const_iteratorGlib::ustring const&) const [6385] ----------------------------------------------- 0.00 4.64 87/87 prerender_icon(char const*, GtkIconSize, unsigned int) [1] [2] 88.2 0.00 4.64 87 load_svg_pixels(char const*, unsigned int, unsigned int) [2] 0.00 4.51 87/87 sp_icon_doc_icon [3] 0.02 0.11 1/2 sp_item_invoke_show(SPItem*, NRArena*, unsigned int, unsigned int) <cycle 5> [46] 0.00 0.01 1/13 sp_document_ensure_up_to_date(SPDocument*) [59] 0.00 0.00 1/2 sp_document_new(char const*, unsigned int, bool) [695] 0.00 0.00 174/174 std::map<Glib::ustring, svg_doc_cache_t*, std::lessGlib::ustring, std::allocator<std::pair<Glib::ustring const, svg_doc_cache_t*> >
::find(Glib::ustring const&) [1328]
0.00 0.00 1/1 std::map<Glib::ustring, svg_doc_cache_t*, std::lessGlib::ustring, std::allocator<std::pair<Glib::ustring const, svg_doc_cache_t*> >
::operator[](Glib::ustring const&) [1797]
0.00 0.00 1/2 NRArena::create() [1862] 0.00 0.00 261/276 std::list<char*, std::allocator<char*> >::end() [5914] 0.00 0.00 261/267 std::_List_iterator<char*>::operator!=(std::_List_iterator<char*> const&) const [5930] 0.00 0.00 174/183 std::_List_iterator<char*>::operator*() const [6076] 0.00 0.00 174/175 std::map<Glib::ustring, svg_doc_cache_t*, std::lessGlib::ustring, std::allocator<std::pair<Glib::ustring const, svg_doc_cache_t*> >
::end() [6084]
0.00 0.00 174/174 std::_Rb_tree_iterator<std::pair<Glib::ustring const, svg_doc_cache_t*>
::operator!=(std::_Rb_tree_iterator<std::pair<Glib::ustring const,
svg_doc_cache_t*> > const&) const [6087] 0.00 0.00 174/178 std::_List_iterator<char*>::operator++() [6080] 0.00 0.00 88/256 Inkscape::IO::file_test(char const*, GFileTest) [5942] 0.00 0.00 87/87 icons_svg_paths() [6378] 0.00 0.00 87/99 std::list<char*, std::allocator<char*> >::begin() [6313] 0.00 0.00 86/86 std::_Rb_tree_iterator<std::pair<Glib::ustring const, svg_doc_cache_t*>
::operator->() const [6395]
0.00 0.00 1/8 sp_item_display_key_new(unsigned int) [7822] 0.00 0.00 1/95963 sp_item_get_type() [2923] ----------------------------------------------- 0.00 4.51 87/87 load_svg_pixels(char const*, unsigned int, unsigned int) [2] [3] 85.7 0.00 4.51 87 sp_icon_doc_icon [3] 0.84 3.29 135/136 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] 0.00 0.37 87/87 nr_arena_item_invoke_render(_cairo*, NRArenaItem*, NRRectL const*, NRPixBlock*, unsigned int) <cycle 11> [26] 0.00 0.00 87/4399 SPItem::getBounds(Geom::Matrix const&, SPItem::BBoxType, unsigned int) const [84] 0.00 0.00 135/3802 nr_arena_item_set_transform(NRArenaItem*, Geom::Matrix const&) [210] 0.00 0.00 174/663464 Inkscape::Preferences::get() <cycle 1> [340] 0.00 0.00 174/663464 Inkscape::Preferences::getBool(Glib::ustring const&, bool) <cycle 1> [271] 0.00 0.00 87/89 sp_item_i2doc_affine(SPItem const*) [1110] 0.00 0.00 135/142 Geom::Scale::operator Geom::Matrix() const [1396] 0.00 0.00 540/225255 boost::optional<Geom::D2Geom::Interval >::operator->() [538] 0.00 0.00 87/684872 Geom::OptRect::~OptRect() [113] 0.00 0.00 87/428739 boost::optional<Geom::D2Geom::Interval >::operator bool (boost::optional_detail::optional_base<Geom::D2Geom::Interval >::*)() const() const [382] 0.00 0.00 270/9489 Geom::D2Geom::Interval::min() const [1164] 0.00 0.00 270/9505 Geom::D2Geom::Interval::max() const [1163] 0.00 0.00 135/1010 Geom::Scale::Scale(double, double) [1517] 0.00 0.00 540/1789678 Geom::Point::operator[](Geom::Dim2) [2831] 0.00 0.00 261/95963 sp_item_get_type() [2923] 0.00 0.00 135/8015 Geom::Matrix::setIdentity() [3556] 0.00 0.00 87/5269 SPDocument::getObjectById(char const*) [3796] 0.00 0.00 87/712709 NRGC::NRGC(NRGC const*) [2849] 0.00 0.00 87/103582 int const& std::max<int>(int const&, int const&) [2919] 0.00 0.00 87/453 nr_pixblock_setup_extern(NRPixBlock*, NR_PIXBLOCK_MODE, int, int, int, int, unsigned char*, int, bool, bool) [5696] 0.00 0.00 87/1997 nr_pixblock_release(NRPixBlock*) [4561] ----------------------------------------------- [4] 79.2 0.85 3.31 136+711791 <cycle 10 as a whole> [4] 0.72 1.95 356031+291 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] 0.08 1.21 203312 nr_arena_shape_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [14] 0.05 0.15 152487 nr_arena_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [40] 0.00 0.00 97 nr_arena_glyphs_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [1516] ----------------------------------------------- <spontaneous> [5] 60.6 0.00 3.19 imageMapNamedCB(_GtkWidget*, void*) [5] 0.00 3.19 70/102 prerender_icon(char const*, GtkIconSize, unsigned int) [1] 0.00 0.00 70/103 sp_icon_get_phys_size(int) [1462] 0.00 0.00 10554/10554 __gnu_cxx::__normal_iterator<preRenderItem*, std::vector<preRenderItem, std::allocator<preRenderItem> > >::operator->() const [3445] 0.00 0.00 10458/10778 Glib::operator==(Glib::ustring const&, char const*) [3438] 0.00 0.00 10458/10659 std::vector<preRenderItem, std::allocator<preRenderItem> >::end() [3442] 0.00 0.00 10458/10554 bool __gnu_cxx::operator!=<preRenderItem*, std::vector<preRenderItem, std::allocator<preRenderItem> >
(__gnu_cxx::__normal_iterator<preRenderItem*,
std::vector<preRenderItem, std::allocator<preRenderItem> > > const&, __gnu_cxx::__normal_iterator<preRenderItem*, std::vector<preRenderItem, std::allocator<preRenderItem> > > const&) [3444] 0.00 0.00 10388/10388 __gnu_cxx::__normal_iterator<preRenderItem*, std::vector<preRenderItem, std::allocator<preRenderItem> > >::operator++() [3452] 0.00 0.00 70/132 std::vector<preRenderItem, std::allocator<preRenderItem> >::begin() [6218] 0.00 0.00 70/96 std::vector<preRenderItem, std::allocator<preRenderItem>
::erase(__gnu_cxx::__normal_iterator<preRenderItem*,
std::vector<preRenderItem, std::allocator<preRenderItem> > >) [6348] ----------------------------------------------- 291 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] 291 nr_arena_shape_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [14] 355604 nr_arena_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [40] 0.01 0.02 1/136 sp_canvas_arena_update(SPCanvasItem*, Geom::Matrix const&, unsigned int) [122] 0.84 3.29 135/136 sp_icon_doc_icon [3] [6] 50.8 0.72 1.95 356031+291 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] 0.00 1.79 203797/215263 nr_arena_item_request_render(NRArenaItem*) [7] 0.07 0.00 712606/1236181 nr_object_check_instance_type(void const*, unsigned int) [53] 0.03 0.03 178043/797442 Geom::operator*(Geom::Matrix const&, Geom::Matrix const&) [35] 0.01 0.00 534327/1558360 Geom::Matrix::operator=(Geom::Matrix const&) [103] 0.00 0.01 356284/356284 NRGC::operator=(NRGC const&) [437] 0.01 0.00 356284/521878 nr_arena_group_get_type() [379] 0.00 0.00 97/97 nr_arena_image_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) [689] 0.00 0.00 388/388 nr_arena_glyphs_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) [744] 0.00 0.00 291/30393 nr_rect_l_intersect(NRRectL*, NRRectL const*, NRRectL const*) [393] 0.00 0.00 356322/712709 NRGC::NRGC(NRGC const*) [2849] 0.00 0.00 356322/863943 nr_arena_item_get_type() [2845] 203312 nr_arena_shape_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [14] 152390 nr_arena_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [40] 97 nr_arena_glyphs_group_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [1516] 291 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] ----------------------------------------------- 0.00 0.00 2/215263 nr_arena_item_unparent(NRArenaItem*) [1319] 0.00 0.00 3/215263 nr_arena_item_set_clip(NRArenaItem*, NRArenaItem*) [1253] 0.00 0.00 4/215263 nr_arena_glyphs_set_path(NRArenaGlyphs*, SPCurve*, unsigned int, font_instance*, int, Geom::Matrix const*) [1214] 0.00 0.00 4/215263 nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup*, font_instance*, int, Geom::Matrix const&) [1092] 0.00 0.00 97/215263 nr_arena_image_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) [689] 0.00 0.02 1932/215263 nr_arena_item_set_transform(NRArenaItem*, Geom::Matrix const*) [212] 0.00 0.02 2096/215263 nr_arena_shape_set_path(NRArenaShape*, SPCurve*, bool) [166] 0.00 0.03 3664/215263 nr_arena_item_set_opacity(NRArenaItem*, double) [116] 0.00 0.03 3664/215263 nr_arena_item_set_visible(NRArenaItem*, unsigned int) [117] 0.00 1.79 203797/215263 nr_arena_item_invoke_update(NRArenaItem*, NRRectL*, NRGC*, unsigned int, unsigned int) <cycle 10> [6] [7] 35.9 0.00 1.89 215263 nr_arena_item_request_render(NRArenaItem*) [7] 0.02 1.85 215263/215263 nr_arena_request_render_rect(NRArena*, NRRectL*) [9] 0.02 0.00 215263/1236181 nr_object_check_instance_type(void const*, unsigned int) [53] 0.00 0.00 215263/863943 nr_arena_item_get_type() [2845] ----------------------------------------------- [8] 35.7 0.08 1.80 663464+1538951 <cycle 1 as a whole> [8] 0.01 1.45 431095 Inkscape::Preferences::getInt(Glib::ustring const&, int) <cycle 1> [12] 0.00 0.14 2482 sp_style_merge_from_style_string(SPStyle*, char const*) <cycle 1> [49] 0.01 0.05 25012 sp_path_set(SPObject*, unsigned int, char const*) <cycle 1> [80] 0.01 0.04 459+28821 sp_repr_svg_read_node(Inkscape::XML::Document*, _xmlNode*, char const*, _GHashTable*) <cycle 1> [85] 0.00 0.03 35384+37576 Inkscape::XML::CompositeNodeObserver::notifyAttributeChanged(Inkscape::XML::Node&, unsigned int, Inkscape::Util::ptr_shared<char>, Inkscape::Util::ptr_shared<char>) <cycle 1> [125] 0.01 0.01 36965 Inkscape::XML::SimpleNode::setAttribute(char const*, char const*, bool) <cycle 1> [180] 0.00 0.02 2272 sigc::internal::signal_emit2<void, SPObject*, SPObject*, sigc::nil>::emit(sigc::internal::signal_impl*, SPObject* const&, SPObject* const&) <cycle 1> [230] 0.01 0.00 81742 sp_object_read_attr(SPObject*, char const*) <cycle 1> [260] 0.00 0.01 3622 Inkscape::Preferences::getBool(Glib::ustring const&, bool) <cycle 1> [271] 0.00 0.01 1739 sp_path_update_patheffect(SPLPEItem*, bool) <cycle 1> [297] 0.00 0.01 135 sp_svg_write_path(std::vector<Geom::Path, std::allocatorGeom::Path > const&) <cycle 1> [303] 0.01 0.00 650246 Inkscape::Preferences::get() <cycle 1> [340] 0.01 0.00 20173 sp_style_merge_style_from_decl(SPStyle*, _CRDeclaration const*) <cycle 1> [348] 0.01 0.00 5361 sp_arc_set(SPObject*, unsigned int, char const*) <cycle 1> [349] 0.00 0.01 20+518 Inkscape::XML::SimpleNode::mergeFrom(Inkscape::XML::Node const*, char const*) <cycle 1> [474] 0.00 0.00 3666 sp_style_read(SPStyle*, SPObject*, Inkscape::XML::Node*) <cycle 1> [526] 0.00 0.00 130 sp_genericellipse_update_patheffect(SPLPEItem*, bool) <cycle 1> [532] 0.00 0.00 4330 sp_object_invoke_build(SPObject*, SPDocument*, Inkscape::XML::Node*, unsigned int) <cycle 1> [569] 0.00 0.00 2270 Inkscape::URIReference::attach(Inkscape::URI const&) <cycle 1> [593] 0.00 0.00 11780 Inkscape::URIReference::_setObject(SPObject*) <cycle 1> [594] 0.00 0.00 457 sp_repr_do_read(_xmlDoc*, char const*) <cycle 1> [662] 0.00 0.00 47873 sp_item_set(SPObject*, unsigned int, char const*) <cycle 1> [674] 0.00 0.00 73 sigc::internal::signal_emit1<void, SPObject*, sigc::nil>::emit(sigc::internal::signal_impl*, SPObject* const&) <cycle 1> [800] 0.00 0.00 4330 sp_object_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [901] 0.00 0.00 3976 SPGradientImpl::setGradientAttr(SPObject*, unsigned int, char const*) <cycle 1> [925] 0.00 0.00 12196 sp_style_merge_ipaint(SPStyle*, SPIPaint*, SPIPaint const*) <cycle 1> [993] 0.00 0.00 4 LivePathEffectObject::livepatheffect_set(SPObject*, unsigned int, char const*) <cycle 1> [1003] 0.00 0.00 965 sp_use_href_changed(SPObject*, SPObject*, SPUse*) <cycle 1> [1089] 0.00 0.00 6 sp_string_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1113] 0.00 0.00 2 sp_star_update_patheffect(SPLPEItem*, bool) <cycle 1> [1148] 0.00 0.00 861 sp_style_set_ipaint_to_uri(SPStyle*, SPIPaint*, Inkscape::URI const*, SPDocument*) <cycle 1> [1170] 0.00 0.00 962 sp_path_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1243] 0.00 0.00 497 SPGradientImpl::build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1245] 0.00 0.00 882 sp_stop_set(SPObject*, unsigned int, char const*) <cycle 1> [1338] 0.00 0.00 58799 SPIPaint::clear() <cycle 1> [1543] 0.00 0.00 245 Inkscape::XML::(anonymous namespace)::VectorNodeObserver::notifyAttributeChanged(Inkscape::XML::Node&, unsigned int, Inkscape::Util::ptr_shared<char>, Inkscape::Util::ptr_shared<char>) <cycle 1> [1545] 0.00 0.00 962 sp_path_set_original_curve(SPPath*, SPCurve*, unsigned int, bool) <cycle 1> [1610] 0.00 0.00 135 Inkscape::SVG::PathString::PathString() <cycle 1> [1635] 0.00 0.00 252 SPStop::readStopColor(Glib::ustring const&, unsigned int) <cycle 1> [1664] 0.00 0.00 2+27 (anonymous namespace)::strip_ids_recursively(Inkscape::XML::Node*) <cycle 1> [1681] 0.00 0.00 1 LivePathEffectObject::livepatheffect_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1686] 0.00 0.00 2 sp_namedview_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1692] 0.00 0.00 10 sp_guide_set(SPObject*, unsigned int, char const*) <cycle 1> [1714] 0.00 0.00 2 Inkscape::Preferences::_load() <cycle 1> [1734] 0.00 0.00 2 sp_root_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1740] 0.00 0.00 20 sp_image_set(SPObject*, unsigned int, char const*) <cycle 1> [1756] 0.00 0.00 2 Inkscape::loadImpl(std::string const&, Glib::ustring&) <cycle 1> [1758] 0.00 0.00 9000 sp_group_set(SPObject*, unsigned int, char const*) <cycle 1> [1760] 0.00 0.00 8267 sp_style_clear(SPStyle*) <cycle 1> [1771] 0.00 0.00 23 sp_marker_set(SPObject*, unsigned int, char const*) <cycle 1> [1776] 0.00 0.00 3 sp_clippath_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1778] 0.00 0.00 2 sp_metadata_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1800] 0.00 0.00 1 sp_image_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [1807] 0.00 0.00 1 Inkscape::DocumentSubset::Relations::remove(SPObject*, bool) <cycle 1> [1808] 0.00 0.00 281 sp_style_unref(SPStyle*) <cycle 1> [1847] 0.00 0.00 431095 Inkscape::Preferences::Entry::getInt(int) const <cycle 1> [2869] 0.00 0.00 81741 sp_object_set(SPObject*, unsigned int, char const*) <cycle 1> [2938] 0.00 0.00 37957 sp_lpe_item_set(SPObject*, unsigned int, char const*) <cycle 1> [3015] 0.00 0.00 29557 sp_shape_set(SPObject*, unsigned int, char const*) <cycle 1> [3073] 0.00 0.00 20560 sp_object_private_set(SPObject*, unsigned int, char const*) <cycle 1> [3174] 0.00 0.00 2482+17691 sp_style_merge_from_decl_list(SPStyle*, _CRDeclaration const*) <cycle 1> [4360] 0.00 0.00 20173 sp_style_merge_property(SPStyle*, int, char const*) <cycle 1> [3178] 0.00 0.00 17680 sp_rect_set(SPObject*, unsigned int, char const*) <cycle 1> [3222] 0.00 0.00 17406 sp_use_set(SPObject*, unsigned int, char const*) <cycle 1> [3224] 0.00 0.00 9381 Inkscape::URIReference::detach() <cycle 1> [3498] 0.00 0.00 7832 sp_style_merge_from_parent(SPStyle*, SPStyle const*) <cycle 1> [3567] 0.00 0.00 5772 SPConnEndPair::setAttr(unsigned int, char const*) <cycle 1> [3748] 0.00 0.00 5748 sp_lineargradient_set(SPObject*, unsigned int, char const*) <cycle 1> [3752] 0.00 0.00 4710 SPIPaint::read(char const*, SPStyle&, SPDocument*) <cycle 1> [3864] 0.00 0.00 4601 sp_style_new(SPDocument*) <cycle 1> [3890] 0.00 0.00 3664 sp_style_read_from_object(SPStyle*, SPObject*) <cycle 1> [4083] 0.00 0.00 3664 sp_item_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [4084] 0.00 0.00 3639 Inkscape::Preferences::Entry::getBool(bool) const <cycle 1> [4113] 0.00 0.00 2907 SPDocument::bindObjectToId(char const*, SPObject*) <cycle 1> [4277] 0.00 0.00 2694 sp_lpe_item_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [4332] 0.00 0.00 2272 sigc::signal2<void, SPObject*, SPObject*, sigc::nil>::emit(SPObject* const&, SPObject* const&) const <cycle 1> [4403] 0.00 0.00 2094 sp_shape_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [4547] 0.00 0.00 1924 SPConnEnd::setAttacherHref(char const*, SPPath*) <cycle 1> [4625] 0.00 0.00 1518 sp_lpe_item_update_patheffect(SPLPEItem*, bool, bool) <cycle 1> [4797] 0.00 0.00 967 sp_use_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [5025] 0.00 0.00 965 sigc::internal::slot_call2<sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void>, SPUse*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>, void, SPObject*, SPObject*>::call_it(sigc::internal::slot_rep*, SPObject* const&, SPObject* const&) <cycle 1> [5081] 0.00 0.00 965 sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void>, SPUse*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>::deduce_result_type<SPObject* const&, SPObject* const&, void, void, void, void, void>::type sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void>, SPUse*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>::operator()<SPObject* const&, SPObject* const&>(SPObject* const&, SPObject* const&) <cycle 1> [5056] 0.00 0.00 965 sigc::adaptor_functor<sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void> >::deduce_result_type<SPObject* const&, SPObject* const&, SPUse*&, void, void, void, void>::type sigc::adaptor_functor<sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void> >::operator()<SPObject* const&, SPObject* const&, SPUse*&>(SPObject* const&, SPObject* const&, SPUse*&) const <cycle 1> [5092] 0.00 0.00 965 sigc::pointer_functor3<SPObject*, SPObject*, SPUse*, void>::operator()(SPObject* const&, SPObject* const&, SPUse* const&) const <cycle 1> [5093] 0.00 0.00 962 sp_conn_end_pair_build(SPObject*) <cycle 1> [5101] 0.00 0.00 884 sp_rect_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [5189] 0.00 0.00 857 sp_style_set_ipaint_to_uri_string(SPStyle*, SPIPaint*, char const*) <cycle 1> [5236] 0.00 0.00 555+144 sp_group_update_patheffect(SPLPEItem*, bool) <cycle 1> [5495] 0.00 0.00 600 sp_group_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [5470] 0.00 0.00 479 sp_lineargradient_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [5608] 0.00 0.00 339 sp_repr_read_mem(char const*, int, char const*) <cycle 1> [5848] 0.00 0.00 245 sp_object_repr_attr_changed(Inkscape::XML::Node*, char const*, char const*, char const*, bool, void*) <cycle 1> [5982] 0.00 0.00 244 sp_arc_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [5983] 0.00 0.00 234 sp_radialgradient_set(SPObject*, unsigned int, char const*) <cycle 1> [6007] 0.00 0.00 129 sigc::internal::slot_call1<sigc::bound_mem_functor1<void, Inkscape::URIReference, SPObject*>, void, SPObject*>::call_it(sigc::internal::slot_rep*, SPObject* const&) <cycle 1> [6225] 0.00 0.00 129 sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::URIReference, SPObject*> >::deduce_result_type<SPObject* const&, void, void, void, void, void, void>::type sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::URIReference, SPObject*> >::operator()<SPObject* const&>(SPObject* const&) const <cycle 1> [6226] 0.00 0.00 129 sigc::bound_mem_functor1<void, Inkscape::URIReference, SPObject*>::operator()(SPObject* const&) const <cycle 1> [6228] 0.00 0.00 126 sp_stop_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [6232] 0.00 0.00 101 sp_namedview_set(SPObject*, unsigned int, char const*) <cycle 1> [6301] 0.00 0.00 100 sp_star_set(SPObject*, unsigned int, char const*) <cycle 1> [6304] 0.00 0.00 73 sigc::signal1<void, SPObject*, sigc::nil>::emit(SPObject* const&) const <cycle 1> [6444] 0.00 0.00 67 Inkscape::URIReference::~URIReference() <cycle 1> [6521] 0.00 0.00 50 sp_root_set(SPObject*, unsigned int, char const*) <cycle 1> [6616] 0.00 0.00 42 SPPaintServerReference::~SPPaintServerReference() <cycle 1> [6663] 0.00 0.00 42 SPPaintServerReference::~SPPaintServerReference() <cycle 1> [6664] 0.00 0.00 21 SPFilterReference::~SPFilterReference() <cycle 1> [7119] 0.00 0.00 21 SPFilterReference::~SPFilterReference() <cycle 1> [7120] 0.00 0.00 19 sp_tspan_set(SPObject*, unsigned int, char const*) <cycle 1> [7182] 0.00 0.00 19 sp_text_set(SPObject*, unsigned int, char const*) <cycle 1> [7181] 0.00 0.00 18 sp_radialgradient_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [7221] 0.00 0.00 12 sp_clippath_set(SPObject*, unsigned int, char const*) <cycle 1> [7450] 0.00 0.00 6 sp_metadata_set(SPObject*, unsigned int, char const*) <cycle 1> [8073] 0.00 0.00 4 sp_star_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [8631] 0.00 0.00 2 Inkscape::Preferences::Preferences() <cycle 1> [10292] 0.00 0.00 2 sp_guide_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [9769] 0.00 0.00 1+1 Inkscape::DocumentSubset::Relations::_doRemoveSubtree(SPObject*) <cycle 1> [13194] 0.00 0.00 2 Inkscape::DocumentSubset::Relations::_doRemove(SPObject*) <cycle 1> [10302] 0.00 0.00 2 sigc::internal::slot_call2<sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void>, SPDesktop*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>, void, SPObject*, SPObject*>::call_it(sigc::internal::slot_rep*, SPObject* const&, SPObject* const&) <cycle 1> [10229] 0.00 0.00 2 sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void>, SPDesktop*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>::deduce_result_type<SPObject* const&, SPObject* const&, void, void, void, void, void>::type sigc::bind_functor<-1, sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void>, SPDesktop*, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil, sigc::nil>::operator()<SPObject* const&, SPObject* const&>(SPObject* const&, SPObject* const&) <cycle 1> [10002] 0.00 0.00 2 sigc::adaptor_functor<sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void> >::deduce_result_type<SPObject* const&, SPObject* const&, SPDesktop*&, void, void, void, void>::type sigc::adaptor_functor<sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void> >::operator()<SPObject* const&, SPObject* const&, SPDesktop*&>(SPObject* const&, SPObject* const&, SPDesktop*&) const <cycle 1> [10526] 0.00 0.00 2 sigc::pointer_functor3<SPObject*, SPObject*, SPDesktop*, void>::operator()(SPObject* const&, SPObject* const&, SPDesktop* const&) const <cycle 1> [10530] 0.00 0.00 2 _layer_hierarchy_changed(SPObject*, SPObject*, SPDesktop*) <cycle 1> [9775] 0.00 0.00 2 Inkscape::Preferences::_loadDefaults() <cycle 1> [10291] 0.00 0.00 1 sp_marker_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [12398] 0.00 0.00 1 sp_text_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [12392] 0.00 0.00 1 sp_tspan_build(SPObject*, SPDocument*, Inkscape::XML::Node*) <cycle 1> [12394] 0.00 0.00 1 sigc::internal::slot_call1<sigc::bound_mem_functor1<void, Inkscape::LayerManager, SPObject*>, void, SPObject*>::call_it(sigc::internal::slot_rep*, SPObject* const&) <cycle 1> [13018] 0.00 0.00 1 sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::LayerManager, SPObject*> >::deduce_result_type<SPObject* const&, void, void, void, void, void, void>::type sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::LayerManager, SPObject*> >::operator()<SPObject* const&>(SPObject* const&) const <cycle 1> [13666] 0.00 0.00 1 sigc::bound_mem_functor1<void, Inkscape::LayerManager, SPObject*>::operator()(SPObject* const&) const <cycle 1> [13680] 0.00 0.00 1 Inkscape::LayerManager::_selectedLayerChanged(SPObject*) <cycle 1> [13181] 0.00 0.00 1 sigc::internal::slot_call1<sigc::bound_mem_functor1<void, Inkscape::DocumentSubset::Relations, SPObject*>, void, SPObject*>::call_it(sigc::internal::slot_rep*, SPObject* const&) <cycle 1> [13019] 0.00 0.00 1 sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::DocumentSubset::Relations, SPObject*>
::deduce_result_type<SPObject* const&, void, void, void, void, void,
void>::type sigc::adaptor_functor<sigc::bound_mem_functor1<void, Inkscape::DocumentSubset::Relations, SPObject*> >::operator()<SPObject* const&>(SPObject* const&) const <cycle 1> [13667] 0.00 0.00 1 sigc::bound_mem_functor1<void, Inkscape::DocumentSubset::Relations, SPObject*>::operator()(SPObject* const&) const <cycle 1> [13681] 0.00 0.00 1 Inkscape::DocumentSubset::Relations::_release_object(SPObject*) <cycle 1> [13193] 0.00 0.00 1 Inkscape::LivePathEffect::LPEObjectReference::link(char const*) <cycle 1> [13201] ----------------------------------------------- 0.02 1.85 215263/215263 nr_arena_item_request_render(NRArenaItem*) [7] [9] 35.5 0.02 1.85 215263 nr_arena_request_render_rect(NRArena*, NRRectL*) [9] 0.05 1.17 430526/663464 Inkscape::Preferences::getInt(Glib::ustring const&, int) <cycle 1> [12] 0.02 0.58 215263/663464 Inkscape::Preferences::get() <cycle 1> [340] 0.02 0.00 215263/1236181 nr_object_check_instance_type(void const*, unsigned int) [53] 0.00 0.00 215263/219029 nr_arena_get_type() [2885] ----------------------------------------------- 0.00 1.46 435423/435423 Inkscape::Preferences::getEntry(Glib::ustring const&) [11] [10] 27.8 0.00 1.46 435423 Inkscape::Preferences::_getRawValue(Glib::ustring const&, char const*&) [10] 0.35 1.10 435423/435568 Inkscape::Preferences::_getNode(Glib::ustring const&, bool) [13] 0.00 0.01 432741/28329840 Inkscape::XML::SimpleNode::attribute(char const*) const [16] 0.00 0.00 435423/435530 Inkscape::Preferences::_keySplit(Glib::ustring const&, Glib::ustring&, Glib::ustring&) [2863] -----------------------------------------------
This table describes the call tree of the program, and was sorted by the total amount of time spent in each function and its children.
Each entry in this table consists of several lines. The line with the index number at the left hand margin lists the current function. The lines above it list the functions that called this function, and the lines below it list the functions this one called. This line lists: index A unique number given to each element of the table. Index numbers are sorted numerically. The index number is printed next to every function name so it is easier to look up where the function in the table.
% time This is the percentage of the `total' time that was spent in this function and its children. Note that due to different viewpoints, functions excluded by options, etc, these numbers will NOT add up to 100%.
self This is the total amount of time spent in this function.
children This is the total amount of time propagated into this function by its children.
called This is the number of times the function was called. If the function called itself recursively, the number only includes non-recursive calls, and is followed by a `+' and the number of recursive calls.
name The name of the current function. The index number is printed after it. If the function is a member of a cycle, the cycle number is printed between the function's name and the index number.
For the function's parents, the fields have the following meanings:
self This is the amount of time that was propagated directly from the function into this parent.
children This is the amount of time that was propagated from the function's children into this parent.
called This is the number of times this parent called the function `/' the total number of times the function was called. Recursive calls to the function are not included in the number after the `/'.
name This is the name of the parent. The parent's index number is printed after it. If the parent is a member of a cycle, the cycle number is printed between the name and the index number.
If the parents of the function cannot be determined, the word `<spontaneous>' is printed in the `name' field, and all the other fields are blank.
For the function's children, the fields have the following meanings:
self This is the amount of time that was propagated directly from the child into the function.
children This is the amount of time that was propagated from the child's children to the function.
called This is the number of times the function called this child `/' the total number of times the child was called. Recursive calls by the child are not listed in the number after the `/'.
name This is the name of the child. The child's index number is printed after it. If the child is a member of a cycle, the cycle number is printed between the name and the index number.
If there are any cycles (circles) in the call graph, there is an entry for the cycle-as-a-whole. This entry shows who called the cycle (as parents) and the members of the cycle (as children.) The `+' recursive calls entry shows the number of function calls that were internal to the cycle, and the calls entry for each member shows, for that member, how many times it was called from other members of the cycle.

2010/7/21 Diederik van Lierop <mail@...1689...>:
What I found out was that it is prerender_icon() that causes the biggest part of the delay during those first 10 seconds. Maybe this is a public secret, but I just wanted to share this with you. I have no intention currently of improving this, but this at least allows us to respond accurately to some bug reports.
I noticed a big speedup during startup when I made the big mess with Tango icons. I attempted to deprecate icons.svg and use "discrete" icons (PNG files), like all other applications do. I still think this is the way to go, but not everyone likes this approach.
Some time could also be saved by caching reads from preferences in a map, but I'm not sure whether I know how to read this profile.
Regards, Krzysztof

On Wed, 2010-07-21 at 23:10 +0200, Krzysztof Kosiński wrote:
2010/7/21 Diederik van Lierop <mail@...1689...>:
What I found out was that it is prerender_icon() that causes the biggest part of the delay during those first 10 seconds. Maybe this is a public secret, but I just wanted to share this with you. I have no intention currently of improving this, but this at least allows us to respond accurately to some bug reports.
I noticed a big speedup during startup when I made the big mess with Tango icons. I attempted to deprecate icons.svg and use "discrete" icons (PNG files), like all other applications do. I still think this is the way to go, but not everyone likes this approach.
Well... I did say that the icons discussion was off the table for 0.48. Given that 0.49 is a refactoring cycle, we may want to revisit the topic of pre-rendered icons (not necessarily Tango).
I think it simply boils down to the question of "Is rendering icons when Inkscape starts worth frustrating our users?". My answer is no, because as a user it irks me to no end to wait so long for inkscape to show up. Note, it also really irks me that it presents UI when it's still pegging my processor.
By no means am I implying that it's the only reason for slower startup, but, if startup time would be reduced by ~20% it's worth doing imho. If people are still opposed to a splash screen saying Inkscape is loading, we must doing everything possible to improve the startup time substantially.
Cheers, Josh

On 7/22/10, Joshua A. Andler wrote:
If people are still opposed to a splash screen saying Inkscape is loading,
As long as Inkscape doesn't render it from an SVG with lots of filters :)
Alexandre Prokoudine http://libregraphicsworld.org

On Thu, 2010-07-22 at 02:41 +0400, Alexandre Prokoudine wrote:
On 7/22/10, Joshua A. Andler wrote:
If people are still opposed to a splash screen saying Inkscape is loading,
As long as Inkscape doesn't render it from an SVG with lots of filters :)
If we went that route I vote a PNG... we need showing something up ASAP.
Cheers, Josh

2010/7/22 Joshua A. Andler <scislac@...400...>:
If we went that route I vote a PNG... we need showing something up ASAP.
Cheers, Josh
The splash screen only papers over the problem. I'd rather have an application that starts quick enough that it doesn't require a splash screen.
Regards, Krzysztof

On 7/22/10, Krzysztof Kosiński wrote:
2010/7/22 Joshua A. Andler:
If we went that route I vote a PNG... we need showing something up ASAP.
The splash screen only papers over the problem. I'd rather have an application that starts quick enough that it doesn't require a splash screen.
Indeed.
Alexandre Prokoudine http://libregraphicsworld.org

On Thu, 2010-07-22 at 02:59 +0400, Alexandre Prokoudine wrote:
On 7/22/10, Krzysztof Kosiński wrote:
2010/7/22 Joshua A. Andler:
If we went that route I vote a PNG... we need showing something up ASAP.
The splash screen only papers over the problem. I'd rather have an application that starts quick enough that it doesn't require a splash screen.
Indeed.
I completely agree... but if big enough gains can't be made, it serves as "I'm doing something" feedback until such gains *can* be made. I really am hopeful that during 0.49 we can see startup time seriously cut down to not need to go that route.
Cheers, Josh

One of the reasons to keep single-file SVG icons was that it tested our renderer. Now that we're switching to Cairo anyway, this reason is gone, so indeed we could switch to something faster.

One of the reasons to keep single-file SVG icons was that it tested our renderer. Now that we're switching to Cairo anyway, this reason is gone, so indeed we could switch to something faster.
In general, if that was the main reason, shouldn't something like that be put into a test suite somewhere, so the user isn't forced to wait for a "test" to run every time the program starts up? How many other "tests" are slowing down Inkscape in various parts of the code? Maybe I don't understand the intent of what you're saying.
It would be very nice to see quicker startup times!
- Bryan

On Wed, 2010-07-21 at 21:52 -0300, bulia byak wrote:
One of the reasons to keep single-file SVG icons was that it tested our renderer. Now that we're switching to Cairo anyway, this reason is gone, so indeed we could switch to something faster.
I did understand that reason during dev cycles, but didn't understand for actual releases. I do think that Bryan was right though about a test suite being a more proper place for such a test.
Cheers, Josh

On Jul 21, 2010, at 2:34 PM, Joshua A. Andler wrote:
I think it simply boils down to the question of "Is rendering icons when Inkscape starts worth frustrating our users?". My answer is no, because as a user it irks me to no end to wait so long for inkscape to show up. Note, it also really irks me that it presents UI when it's still pegging my processor.
Oh, yes. There are many ways to speed up the icons. However, shipping with pre-rendered ones is not really the solution. With the last attempt we ended up with literally hundreds and hundreds of icons, yet did not even cover the sizes I needed from just running the default Ubuntu theme.
I'd pointed this out a few times, and tried to get help in the past. Basically all we need to do is leverage existing approaches and standards to get the good combination of flexibility, smaller distribution sizes, easier theming and faster startups. One of the standard directories covered by the XDG Base Directory Specification is a 'cache' directory
$XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored. If $XDG_CACHE_HOME is either not set or empty, a default equal to $HOME/.cache should be used
Given that usability is a main consideration, adding perhaps 10 seconds to the very first time you run a newly installed program sounds like a very reasonable trade-off. We just need to store the details used to generate the current set of icons so that we can regenerate them as needed. Each time the user switches themes, changes displays, or other such pertinent events occur, we can flag it as invalid and recalc. We can even leave the last few in place to avoid regenerating too often.
BTW, this can be especially important for upcoming GNOME themes and stuff with GTK 3, etc.
It's all very simple. We just need to be sure the proper testing is done to make sure people don't accidentally break themeability as has happened in the past. (I'd prefer to spend my time writing new code, not repeatedly unbreaking existing code)

On Wed, 2010-07-21 at 22:33 -0700, Jon Cruz wrote:
$XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored. If $XDG_CACHE_HOME is either not set or empty, a default equal to $HOME/.cache should be used
Given that usability is a main consideration, adding perhaps 10 seconds to the very first time you run a newly installed program sounds like a very reasonable trade-off. We just need to store the details used to generate the current set of icons so that we can regenerate them as needed. Each time the user switches themes, changes displays, or other such pertinent events occur, we can flag it as invalid and recalc. We can even leave the last few in place to avoid regenerating too often.
BTW, this can be especially important for upcoming GNOME themes and stuff with GTK 3, etc.
It's all very simple. We just need to be sure the proper testing is done to make sure people don't accidentally break themeability as has happened in the past. (I'd prefer to spend my time writing new code, not repeatedly unbreaking existing code)
This definitely sounds like a smart approach. It will allow people to still use custom themes and whatever size they choose and they only get the initial punishment while retaining freedom. Is a check also included for the first time the version is bumped (since it's the most likely time icons will actually change)?
Cheers, Josh

On Wed, 2010-07-21 at 22:45 +0200, Diederik van Lierop wrote:
On launchpad I've seen reports that this could be related to the number of fonts installed, which could indeed be part of the problem.
When I had about 1700 fonts installed on my previous setup, I could go and fetch a cup of coffee in the time it took Inkscape to start up.
So then I started to keep an Inkscape instance open, to open files via its menu instantly. Opening files via file manager meant the same startup delay every time!?

On Jul 22, 2010, at 12:59 AM, Thorsten Wilms wrote:
On Wed, 2010-07-21 at 22:45 +0200, Diederik van Lierop wrote:
On launchpad I've seen reports that this could be related to the number of fonts installed, which could indeed be part of the problem.
When I had about 1700 fonts installed on my previous setup, I could go and fetch a cup of coffee in the time it took Inkscape to start up.
So then I started to keep an Inkscape instance open, to open files via its menu instantly. Opening files via file manager meant the same startup delay every time!?
The Scribus guys have some font caching code that might reduce or solve the problem. Now that we have 0.48 pretty much set, it would probably be good for anyone interested in that aspect to check it out.

On 7/22/10, Thorsten Wilms wrote:
When I had about 1700 fonts installed on my previous setup, I could go and fetch a cup of coffee in the time it took Inkscape to start up.
You mean you didn't use fonts management software?
Alexandre Prokoudine http://libregraphicsworld.org

On Thu, 2010-07-22 at 12:28 +0400, Alexandre Prokoudine wrote:
On 7/22/10, Thorsten Wilms wrote:
When I had about 1700 fonts installed on my previous setup, I could go and fetch a cup of coffee in the time it took Inkscape to start up.
You mean you didn't use fonts management software?
I did for other reasons, but found enabling/disabling fonts too much of a hassle. Currently I try to have only the good stuff installed :)

On Thu, 22 Jul 2010, Thorsten Wilms wrote:
On Thu, 2010-07-22 at 12:28 +0400, Alexandre Prokoudine wrote:
On 7/22/10, Thorsten Wilms wrote:
When I had about 1700 fonts installed on my previous setup, I could go and fetch a cup of coffee in the time it took Inkscape to start up.
You mean you didn't use fonts management software?
I did for other reasons, but found enabling/disabling fonts too much of a hassle. Currently I try to have only the good stuff installed :)
Why not generate a preview of the font (one time) for the selection list. And load them on demand?
Stefan

On Jul 22, 2010, at 2:19 AM, Stefan de Konink wrote:
Why not generate a preview of the font (one time) for the selection list. And load them on demand?
I was actually looking into this.
The selection list is not causing the slow startup. However, it does cause a slowdown each time it is first accessed from a new window/view. The problem there is that we are using a 'markup' data column for the list, so GTK+ doesn't know how big to make each entry until it has walked through and rendered each and every one. So the fix there will be to switch from a markup data column to a pixmap one and then render and cache them as needed on the fly.

2010/7/22 Thorsten Wilms <t_w_@...123...>:
So then I started to keep an Inkscape instance open, to open files via its menu instantly. Opening files via file manager meant the same startup delay every time!?
When you open a new file from the file manager, a new instance is started. When you do it from the menu, a new window is created in the existing instance.
010/7/22 Jon Cruz <jon@...18...>:
I'd pointed this out a few times, and tried to get help in the past. Basically all we need to do is leverage existing approaches and standards to get the good combination of flexibility, smaller distribution sizes, easier theming and faster startups. One of the standard directories covered by the XDG Base Directory Specification is a 'cache' directory
By using the librsvg loader we still halve our startup time (IIRC) and only need to include discrete SVG icons.
Regards, Krzysztof

On Jul 22, 2010, at 2:32 PM, Krzysztof Kosiński wrote:
010/7/22 Jon Cruz <jon@...18...>:
I'd pointed this out a few times, and tried to get help in the past. Basically all we need to do is leverage existing approaches and standards to get the good combination of flexibility, smaller distribution sizes, easier theming and faster startups. One of the standard directories covered by the XDG Base Directory Specification is a 'cache' directory
By using the librsvg loader we still halve our startup time (IIRC) and only need to include discrete SVG icons.
But don't you remember? librsvg is not a fully viable option, which is why we ended up having to include hundreds and hundreds of individually pre-rendered png files in the past attempt. Things are ok if one sticks to requiring users to always install the latest cutting edge versions of libs on their OS, but that's not practical. Also by *design* librsvg only supports a partial subset of SVG, and as Inkscape and SVG itself both move forwards, we diverge even more.

W dniu 23 lipca 2010 03:06 użytkownik Jon Cruz <jon@...18...> napisał:
But don't you remember? librsvg is not a fully viable option, which is why we ended up having to include hundreds and hundreds of individually pre-rendered png files in the past attempt.
The PNG files were included because I could not add the librsvg loader to Windows devlibs. Now this is no longer a problem, so they are not strictly necessary. They could be generated on first startup or during the build.
Things are ok if one sticks to requiring users to always install the latest cutting edge versions of libs on their OS, but that's not practical. Also by *design* librsvg only supports a partial subset of SVG, and as Inkscape and SVG itself both move forwards, we diverge even more.
Even old versions of librsvg can handle our icons. Furthermore, all other icons on the Gnome desktop are rendered with librsvg, so its limitations would not be unique to Inkscape.
Regards, Krzysztof

On Fri, 2010-07-23 at 18:05 +0200, Krzysztof Kosiński wrote:
Even old versions of librsvg can handle our icons. Furthermore, all other icons on the Gnome desktop are rendered with librsvg, so its limitations would not be unique to Inkscape.
I just have to ask. Are you against the idea Jon had about implementing XDG support and us doing the caching on first launch of any given icon theme or size? I am mainly asking because he expressed interest in working on it and if you're not opposed to it, why not let him? :)
Cheers, Josh

W dniu 23 lipca 2010 20:44 użytkownik Joshua A. Andler <scislac@...400...> napisał:
I just have to ask. Are you against the idea Jon had about implementing XDG support and us doing the caching on first launch of any given icon theme or size? I am mainly asking because he expressed interest in working on it and if you're not opposed to it, why not let him? :)
The best solution is to combine both ideas. At first run, a directory "icons" should be created under the XDG cache directory. Icons would be prerendered there in a structure that matches a freedesktop.org icon theme. Then this directory would be added to the list of directories searched by GtkIconTheme using gtk_icon_theme_append_search_path.
This would allow us to replace the SPIcon widget with standard GtkImage, and InkAction with GtkAction. The only reason those classes exist is to support the monolithic icon file.
Regards, Krzysztof

On Jul 23, 2010, at 12:41 PM, Krzysztof Kosiński wrote:
The best solution is to combine both ideas. At first run, a directory "icons" should be created under the XDG cache directory. Icons would be prerendered there in a structure that matches a freedesktop.org icon theme. Then this directory would be added to the list of directories searched by GtkIconTheme using gtk_icon_theme_append_search_path.
This would allow us to replace the SPIcon widget with standard GtkImage, and InkAction with GtkAction. The only reason those classes exist is to support the monolithic icon file.
No, that is not correct, and has not been for some time. There are some subtle mechanisms in play with our code, including the fact that Inkscape now has successfully been integrated as one of those icon theme sources.
So many years ago the SPIcon and InkAction were needed, but that is outdated information. I think that when you first started looking into the inkscape code you may have hit a bug or two in those areas, but fixing those bugs unblocked things.
Yes, we should try to use standard widgets and approaches as much as possible. The good news is that a while back the Inkscape icon code was fixed to support the standards more than most applications do. We just need to leverage that.
Oh, and there are some very subtle and tricky interactions with exactly where in the loading system icons are encountered, rendered, cached, etc. Static system caching of gtk_icon_theme_append_search_path() is just one of those factors. So it is not as simple an issue as one might first assume. Of course anyone who is interested is still very welcome to just drop into our chat room and talk things over whenever a bit more understanding is needed. That's usually the best way to get such information figured out.

On Jul 23, 2010, at 9:05 AM, Krzysztof Kosiński wrote:
W dniu 23 lipca 2010 03:06 użytkownik Jon Cruz <jon@...18...> napisał:
But don't you remember? librsvg is not a fully viable option, which is why we ended up having to include hundreds and hundreds of individually pre-rendered png files in the past attempt.
The PNG files were included because I could not add the librsvg loader to Windows devlibs. Now this is no longer a problem, so they are not strictly necessary. They could be generated on first startup or during the build.
No, you seem to have forgotten. We discussed this on the mailing list April before last, and you said you would do the PNG versions in response to the note that some icons were coming up blank for different users.
Things are ok if one sticks to requiring users to always install the latest cutting edge versions of libs on their OS, but that's not practical. Also by *design* librsvg only supports a partial subset of SVG, and as Inkscape and SVG itself both move forwards, we diverge even more.
Even old versions of librsvg can handle our icons. Furthermore, all other icons on the Gnome desktop are rendered with librsvg, so its limitations would not be unique to Inkscape.
No, this is not true. That is a source of many problems. In the past we've definitely seen core Inkscape users have librsvg not handle certain icons and result in mis-rendered or completely blank results. Just because you had seen no problems does not mean *others* are not seeing such problems. Additionally you have to keep in mind that not everyone runs a GNOME desktop or GNOME applications. KDE is actually quite a popular desktop and application framework, and KDE has *two* main SVG renderers, neither of which are librsvg.
Then we also have mentioned quite a few times that Inkscape intends to *innovate* SVG use, not follow lagging SVG adoption. Among other things we are in the process of implementing multi-res image/icon support. In discussions at SVG Open 2008 many of the W3C WG members suggested that instead of the proposed SVG <multiImage> element, that one could achieve that via CSS3 Media Queries. At SVG 2009 some of the Opera team showed implementation of such behavior.
(this article contains links and a good summary http://nimbupani.com/svg-is-coming.html )
So the bottom line there is that we should keep in mind that Inkscape is *not* like other applications. It *is* a high-quality SVG renderer, and we should not slave ourselves to the limitations of just one of the main Linux desktop environments out there. We should help Inkscape promote SVG and lead the pack, not follow the least common denominator of the more restricted use cases.

W dniu 24 lipca 2010 22:31 użytkownik Jon Cruz <jon@...18...> napisał:
No, you seem to have forgotten. We discussed this on the mailing list April before last, and you said you would do the PNG versions in response to the note that some icons were coming up blank for different users.
The reason that some icons were coming up blank was that the librsvg loader was not present in Windows devlibs.
No, this is not true. That is a source of many problems. In the past we've definitely seen core Inkscape users have librsvg not handle certain icons and result in mis-rendered or completely blank results. Just because you had seen no problems does not mean *others* are not seeing such problems.
What "certain icons"? If you mean icons created by users for other applications / icon themes, this is irrelevant. If you mean Inkscape icons, see above. When I made the big mess I tweaked all the discrete icons to display correctly with librsvg. In a few cases they contained incorrect SVG that happened to render correctly in Inkscape.
Additionally you have to keep in mind that not everyone runs a GNOME desktop or GNOME applications. KDE is actually quite a popular desktop and application framework, and KDE has *two* main SVG renderers, neither of which are librsvg.
Our application is GTK based so we will not be using KDE's loader. The only icon displayed by KDE's loader when running on KDE would be Inkscape's application icon.
Then we also have mentioned quite a few times that Inkscape intends to *innovate* SVG use, not follow lagging SVG adoption. Among other things we are in the process of implementing multi-res image/icon support. (...)
Application icons are not the best place for introducing experimental SVG features.
So the bottom line there is that we should keep in mind that Inkscape is *not* like other applications. It *is* a high-quality SVG renderer, and we should not slave ourselves to the limitations of just one of the main Linux desktop environments out there. We should help Inkscape promote SVG and lead the pack, not follow the least common denominator of the more restricted use cases.
The fact that the application we're working on happens to include a rich featured SVG renderer designed for interactive editing and high resolution rendering does not mean we can't use a different, more limited renderer for a task that is fundamentally different: quick static rendering of simple vector images at low resolutions. There is no compelling advantage to using Inkscape's renderer to render the icons. Do not give in to NIH syndrome.
No, that is not correct, and has not been for some time. There are some subtle mechanisms in play with our code, including the fact that Inkscape now has successfully been integrated as one of those icon theme sources.
It hasn't. When I call gtk_image_new_from_icon_name, it returns a missing icon image for icons that are only found in icons.svg. sp_icon_new still returns the broken SPIcon widget when rendering from icons.svg, and a GtkImage when fetching from the icon theme, which is a major WTF in itself.
Static system caching of gtk_icon_theme_append_search_path() is just one of those factors.
I have no idea what you're talking about. The effect of this call does not persist when the application is closed.
Regards, Krzysztof

On Jul 24, 2010, at 2:48 PM, Krzysztof Kosiński wrote:
I have no idea what you're talking about. The effect of this call does not persist when the application is closed.
yes, and this is *exactly* why devs are *strongly* encouraged to participate in our chat room. It is much easier to discuss such subtle issues in a chat.

On Thu, 2010-07-22 at 23:32 +0200, Krzysztof Kosiński wrote:
When you open a new file from the file manager, a new instance is started. When you do it from the menu, a new window is created in the existing instance.
I wasn't aware of that before I had the problem with the delay, noticed the difference by chance and then knew it could only be because of new vs same instance.
But why would I want to open files in new instances? opening files via file manager is often more comfortable for me. Is there a way to not have this create new instances? If so, could/should it be made default?

Thorsten Wilms wrote:
On Thu, 2010-07-22 at 23:32 +0200, Krzysztof Kosiński wrote:
When you open a new file from the file manager, a new instance is started. When you do it from the menu, a new window is created in the existing instance.
I wasn't aware of that before I had the problem with the delay, noticed the difference by chance and then knew it could only be because of new vs same instance.
But why would I want to open files in new instances? opening files via file manager is often more comfortable for me. Is there a way to not have this create new instances? If so, could/should it be made default?
Yes, when starting Inkscape we could check right away whether Inkscape is already open, and if so we could just make the other instance open the file and exit ASAP. Here is a discussion on some methods to do this (and how to avoid race conditions): http://www.flounder.com/nomultiples.htm
Unfortunately it's just windows based. Anyone familiar enough with pthreads/GTK/Glib or whatever we need to do this in a cross-platform manner? (Well, I have some experience with pthreads, so I could probably get the mutex stuff to work, but I have no idea about the rest.)

2010/7/23 Jasper van de Gronde <th.v.d.gronde@...528...>:
Unfortunately it's just windows based. Anyone familiar enough with pthreads/GTK/Glib or whatever we need to do this in a cross-platform manner? (Well, I have some experience with pthreads, so I could probably get the mutex stuff to work, but I have no idea about the rest.)
No need to reinvent the wheel. http://live.gnome.org/LibUnique
Regards, Krzysztof

Krzysztof Kosiński wrote:
2010/7/23 Jasper van de Gronde <th.v.d.gronde@...528...>:
Unfortunately it's just windows based. Anyone familiar enough with pthreads/GTK/Glib or whatever we need to do this in a cross-platform manner? (Well, I have some experience with pthreads, so I could probably get the mutex stuff to work, but I have no idea about the rest.)
No need to reinvent the wheel. http://live.gnome.org/LibUnique
Sounds excellent, do you have any experience with it? Would it need any new dependencies or can we more or less just plug it in?

W dniu 23 lipca 2010 22:36 użytkownik Jasper van de Gronde <th.v.d.gronde@...528...> napisał:
No need to reinvent the wheel. http://live.gnome.org/LibUnique
Sounds excellent, do you have any experience with it? Would it need any new dependencies or can we more or less just plug it in?
The only new dependency would be the libunique library itself. No experience with it, but the library is rather simple. I looked at the code and at first glance it seems like this library is Unix-only. However, it has a "backend" mechanism that can be used to add Windows support using the method described in the article you've mentioned. Additionally, gedit is using it, and there is a Windows version of gedit, so it could in fact work on Windows.
Regards, Krzysztof

mentioned. Additionally, gedit is using it, and there is a Windows version of gedit, so it could in fact work on Windows.
Incidentally, I've noticed that when I open a file relative to my home directory in gedit (eg "~/project/main.c"), and then re-open that same file with an absolute path (eg "/home/bryan/project/main.c"), gedit thinks it's a different file & opens 2 copies.
Fortunately, the code that detects whether I've modified the file elsewhere still works fine, so it's never caused any major issues, just a slight annoyance every now and then. Might be different with Inkscape, though!
It's not the most common situation in the world, and probably not worth worrying about, but it does happen. In gedit, it usually happens because I open the file first via Nautilus, and then later on via the gedit command line extension.
Just thought I'd mention that!
- Bryan

Incidentally, I've noticed that when I open a file relative to my home directory in gedit (eg "~/project/main.c"), and then re-open that same file with an absolute path (eg "/home/bryan/project/main.c"), gedit thinks it's a different file & opens 2 copies.
P.S. That's using gedit version 2.28.0, libunique 1.0 installed, on Ubuntu 9.10.
- Bryan

Although not an Inkscape developer, I'm not entirely in favour of "merging instances" of Inkscape.
1. I've heard of people running the last stable build and a dev build concurrently when they run into an issue to try to pinpoint it. 2. The functionality of Inkscape Portable would be reduced slightly as it would no longer be able to run if inkscape.exe is already running. 3. Version compatibility in particular - it would need to be implemented carefully so that it doesn't break anything with running different versions, at least back to 0.48. 4. Stability: if Inkscape crashes, all windows from that process die. At times I have intentionally run multiple instances of the same version of Inkscape, because I'm doing something which I know to be a sensitive crash-causing issue and I don't really want to pull down my other document at the same time. (Don't worry, I've reported the bug each time :P)
I think the best solution would be to query the already-running instance(s) and see if the path matches on any to the current path; that way you can get a single instance per path. So you could run 0.49 and 0.49+devel-r12345 in different directories, and starting a new instance of r12345 would open a new window in that instance, and using the file manager which happens to associate .svg with 0.49 will open that in 0.49. Or even another instance of 0.49 in another directory - and that way Inkscape Portable wouldn't be affected. (That's partlywhy I think a path check would be better than a (more complex anyway) version check.)
Reason 4 is not addressed by the single-instance-by-path approach above. The others are. I think it would not be too difficult to have a preferences option for it, if people thought it important (even if there was no UI for it); LibUnique looks to me like it should be able to cope with all this: process detection would be done first, I think, unless LibUnique supports that sort of same-path thing directly? then the process management and inter-process communication would be left to LibUnique.
I'm not sure if this is how you'd go about implementing it, so that's why I've spoken up. Does it sound reasonable?
Chris Morgan

On Fri, Jul 23, 2010 at 10:01 PM, Chris Morgan <chris.morganiser@...400...> wrote:
Although not an Inkscape developer, I'm not entirely in favour of "merging instances" of Inkscape.
Agreed. In addition to all the reasons you listed, I think it's simply not the business of the application to fuss about instances. If needed, it should be an optional service by the OS (although with some support from the program perhaps). I think that if we cut down startup time enough, this issue will be moot anyway.

Rewrite windows, GNU/linux, MacOS, and BSD and I'm your man! Having the option to allow only one setting is quite interesting. Why not making it accessible through the preferences?
2010/7/24 bulia byak <buliabyak@...400...>:
On Fri, Jul 23, 2010 at 10:01 PM, Chris Morgan <chris.morganiser@...400...> wrote:
Although not an Inkscape developer, I'm not entirely in favour of "merging instances" of Inkscape.
Agreed. In addition to all the reasons you listed, I think it's simply not the business of the application to fuss about instances. If needed, it should be an optional service by the OS (although with some support from the program perhaps).

Chris Morgan wrote:
Although not an Inkscape developer, I'm not entirely in favour of "merging instances" of Inkscape.
- I've heard of people running the last stable build and a dev build
concurrently when they run into an issue to try to pinpoint it.
Don't worry, I do that all the time as well, this ability will not go away if I can help it.
- The functionality of Inkscape Portable would be reduced slightly as
it would no longer be able to run if inkscape.exe is already running. 3. Version compatibility in particular - it would need to be implemented carefully so that it doesn't break anything with running different versions, at least back to 0.48.
Again this depends on how exactly this functionality would be implemented. Specifically, in the case of Inkscape I would be inclined to go with a model where it only avoids launching duplicates of the exact same executable.
- Stability: if Inkscape crashes, all windows from that process die.
At times I have intentionally run multiple instances of the same version of Inkscape, because I'm doing something which I know to be a sensitive crash-causing issue and I don't really want to pull down my other document at the same time. (Don't worry, I've reported the bug each time :P)
This is indeed a fair point, and I would prefer an even better model, perhaps a bit like what Chrome uses (and I'm also not totally sold on the "avoid multiple instances" idea, I just feel that it might warrant some looking into). But given that that probably isn't going to happen in the near future it may still be interesting to see what benefits can be gained from avoiding multiple instances.
If Inkscape does crash it's obviously annoying that you loose some time (note that we do have an emergency save, which should now work again, not as convenient as not crashing, but still), but hopefully it won't crash that often that it would outweigh any speed increase in opening files.
... I'm not sure if this is how you'd go about implementing it, so that's why I've spoken up. Does it sound reasonable?
I agree that if we do have a check like this in Inkscape that it should probably be based on the specific executable. As for a preference setting, I'd rather not add it and see how it goes. If it turns out to such a big gain that it's okay if on occasion people have to reopen (not loose work!) a few more files because of a crash then that's fine. If it isn't, then I think we'd better not bother anyway.
With regards to the OS needing to handle this: Yes, I can definitely see Bulia's point, in an ideal world the OS would take care of this kind of thing. But we don't live in that world (unfortunately). So if (and I emphasize IF) we can greatly enhance our user experience by taking care of this ourself (in a relatively easy and lightweight manner) then I would like to do so.

On Sat, Jul 24, 2010 at 3:52 AM, Jasper van de Gronde <th.v.d.gronde@...528...> wrote:
With regards to the OS needing to handle this: Yes, I can definitely see Bulia's point, in an ideal world the OS would take care of this kind of thing. But we don't live in that world (unfortunately).
Sure, I'm not proposing to go patch OSes right now :) I'm just saying that adding this complexity into the application is unnatural and thus should be avoided _if possible_. Historically there were two reasons to push for single-instance: copy/paste not working between instances and slow start. We've fixed the first one, and if we can tackle the second one the single-instance stuff becomes simply unneeded.

On Jul 23, 2010, at 11:52 PM, Jasper van de Gronde wrote:
With regards to the OS needing to handle this: Yes, I can definitely see Bulia's point, in an ideal world the OS would take care of this kind of thing. But we don't live in that world (unfortunately). So if (and I emphasize IF) we can greatly enhance our user experience by taking care of this ourself (in a relatively easy and lightweight manner) then I would like to do so.
Actually... we do live in such a world. Or at least in that each target OS has its own means of running 'single instance'. Problem is.... the mechanisms are very different on each OS.

W dniu 24 lipca 2010 03:01 użytkownik Chris Morgan <chris.morganiser@...400...> napisał:
- Stability: if Inkscape crashes, all windows from that process die.
At times I have intentionally run multiple instances of the same version of Inkscape, because I'm doing something which I know to be a sensitive crash-causing issue and I don't really want to pull down my other document at the same time. (Don't worry, I've reported the bug each time :P)
There are only two sane approaches: 1. Open every document in the existing instance. 2. Open each document in a separate instance.
Advantages of #1: - faster opening of documents - sharing of common data = lower memory use - libunique simplifies the implementation Disadvantages of #1: - crash in one window destroys the unsaved work in all other windows - needs extra care to ensure that different versions of the executable can be run side by side - libunique might not work on Windows
Advantages of #2: - better stability: crash will only destroy unsaved work in the window that crashed - different versions of the executable can be run side by side naturally - easy to implement Disadvantages of #2: - slower start - higher memory use - no data can be shared; if we use shared memory, the crashed instance could have corrupted it and the stability guarantee goes away; possible solution: read-only shared memory, but hard to implement in a portable manner - needs a way to synchronize the preferences between instances, otherwise the last instance to quit will overwrite changes from other instances - might interfere with DBus extension API (?)
Commercial vector editors usually go for #1. IMO the preferences issue is the largest obstacle to #2. It means we have to use IPC in both cases, but in #1 we only use it to tell the running instance what to open. In #2 we have to synchronize a lot of settings over the lifetime of the application and propagate change notifications to all instances.
2010/7/24 bulia byak <buliabyak@...400...>:
Agreed. In addition to all the reasons you listed, I think it's simply not the business of the application to fuss about instances.
It is not the business of the user, because most users do not know what an application instance is and how it's different from a window. But the application cannot ignore this issue. Otherwise we get really weird behavior.
W dniu 24 lipca 2010 08:52 użytkownik Jasper van de Gronde <th.v.d.gronde@...528...> napisał:
Again this depends on how exactly this functionality would be implemented. Specifically, in the case of Inkscape I would be inclined to go with a model where it only avoids launching duplicates of the exact same executable.
On each build we can generate an UUID to be stored in inkscape-version.cpp and start a new instance if there's no instance with this UUID already running. There's a little more complexity in it, because we need to generate a different exclusion ID for every user session, so if you log in locally, start Inkscape, then lock the screen and log in remotely via SSH, you can start a distinct instance of Inkscape.
Regards, Krzysztof

On Jul 24, 2010, at 3:46 PM, Krzysztof Kosiński wrote:
There are only two sane approaches:
- Open every document in the existing instance.
- Open each document in a separate instance.
[SNIP]
Advantages of #2:
- better stability: crash will only destroy unsaved work in the window
that crashed
- different versions of the executable can be run side by side naturally
- easy to implement
Another advantage is leveraging multiple cores on a single box. For modern systems, it's slightly frustrating for end users to see their CPU use max out at only 50% or 25% and have to keep waiting two or four times as long for Inkscape to do something. Of course, this is a short-term advantage, but one many people have been leveraging for some time.
Commercial vector editors usually go for #1.
There are many strong reasons to look at this. However... in the past year or so applications have started doing "process per document", even if they are presenting inside the same GUI. We might want to look and weigh/evaluate some of the same reasons web browsers are switching to this approach.
IMO the preferences issue is the largest obstacle to #2. It means we have to use IPC in both cases, but in #1 we only use it to tell the running instance what to open. In #2 we have to synchronize a lot of settings over the lifetime of the application and propagate change notifications to all instances.
There are actually some very simple ways to address this. And we do have two separate areas to work on: 1 - Inkscape code needs to be changed to update the UI in response to preference changes. 2 - Inkscape needs to sync changes between instances
For problem number 1, we have to address things anyway. There are several bugs that currently are happening due to preference changes not being reflected properly in the UI (there are many widget-bound workarounds, but we did see a slew of these types of bugs in winding up 0.48). So that's a "we need to code this regardless" point.
For problem number 2 a very simple mechanism would be to watch the preferences file and reload it when it changes. Then instance A writes out a change and instance B, C and D see and pick this up. This may not be as elegant as a DBus based solution, but it does have the advantage of being doable with existing code in Inkscape.
It is not the business of the user, because most users do not know what an application instance is and how it's different from a window. But the application cannot ignore this issue. Otherwise we get really weird behavior.
This is a *very* good point. We definitely need to keep that as a prime concern.
On each build we can generate an UUID to be stored in inkscape-version.cpp and start a new instance if there's no instance with this UUID already running. There's a little more complexity in it, because we need to generate a different exclusion ID for every user session, so if you log in locally, start Inkscape, then lock the screen and log in remotely via SSH, you can start a distinct instance of Inkscape.
We also would need to tie things to different environment variables, etc. If one launches an instance of inkscape with different XDG variables from a current instance of the same version, things still should treat that as 'different'. And there are a few other such factors to consider. So it does look as if UUID itself does not solve the problem.

2010/7/25 Jon Cruz <jon@...18...>:
For problem number 2 a very simple mechanism would be to watch the preferences file and reload it when it changes. Then instance A writes out a change and instance B, C and D see and pick this up. This may not be as elegant as a DBus based solution, but it does have the advantage of being doable with existing code in Inkscape.
Some preferences change rather rapidly, for example when toggling a button, so this might kill responsiveness.
GSettings looks like the best future solution. You can even bind a configuration value to a GObject property and it updates with zero intervention. I'm not sure how well it would work with C++ objects, but probably a nice template-based wrapper can be made.
Regards, Krzysztof

On 7/24/10, Jasper van de Gronde wrote:
No need to reinvent the wheel. http://live.gnome.org/LibUnique
Sounds excellent, do you have any experience with it? Would it need any new dependencies or can we more or less just plug it in?
Why not use D-BUS for opened instance check like GIMP already does? We already use D-BUS anyway.
Alexandre Prokoudine http://libregraphicsworld.org
participants (12)
-
Alexandre Prokoudine
-
Bryan Hoyt | Brush Technology
-
bulia byak
-
Chris Morgan
-
Diederik van Lierop
-
Jasper van de Gronde
-
Jon Cruz
-
Joshua A. Andler
-
Kris De Gussem
-
Krzysztof Kosiński
-
Stefan de Konink
-
Thorsten Wilms