diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm
index 1be93286b..97f8b3e63 100644
--- a/lib/Slic3r/GUI/3DScene.pm
+++ b/lib/Slic3r/GUI/3DScene.pm
@@ -1198,6 +1198,7 @@ sub _extrusionentity_to_verts {
         return;
     } elsif ($entity->isa('Slic3r::ExtrusionPath')) {
         my $polyline = $entity->polyline->clone;
+        $polyline->remove_duplicate_points;
         $polyline->translate(@$copy);
         $lines = $polyline->lines;
         $widths = [ map $entity->width, 0..$#$lines ];
@@ -1210,6 +1211,7 @@ sub _extrusionentity_to_verts {
         $closed  = 1;
         foreach my $path (@$entity) {
             my $polyline = $path->polyline->clone;
+            $polyline->remove_duplicate_points;
             $polyline->translate(@$copy);
             my $path_lines = $polyline->lines;
             push @$lines, @$path_lines;
@@ -1217,7 +1219,6 @@ sub _extrusionentity_to_verts {
             push @$heights, map $path->height, 0..$#$path_lines;
         }
     }
-    
     Slic3r::GUI::_3DScene::_extrusionentity_to_verts_do($lines, $widths, $heights,
         $closed, $top_z, $copy, $qverts, $tverts);
 }
diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp
index 38a5b94ae..f4ef37c13 100644
--- a/xs/src/libslic3r/ExtrusionEntity.cpp
+++ b/xs/src/libslic3r/ExtrusionEntity.cpp
@@ -172,13 +172,6 @@ ExtrusionPath::grow() const
     return pp;
 }
 
-ExtrusionLoop::operator Polygon() const
-{
-    Polygon polygon;
-    this->polygon(&polygon);
-    return polygon;
-}
-
 ExtrusionLoop*
 ExtrusionLoop::clone() const
 {
@@ -188,8 +181,7 @@ ExtrusionLoop::clone() const
 bool
 ExtrusionLoop::make_clockwise()
 {
-    Polygon polygon = *this;
-    bool was_ccw = polygon.is_counter_clockwise();
+    bool was_ccw = this->polygon().is_counter_clockwise();
     if (was_ccw) this->reverse();
     return was_ccw;
 }
@@ -197,8 +189,7 @@ ExtrusionLoop::make_clockwise()
 bool
 ExtrusionLoop::make_counter_clockwise()
 {
-    Polygon polygon = *this;
-    bool was_cw = polygon.is_clockwise();
+    bool was_cw = this->polygon().is_clockwise();
     if (was_cw) this->reverse();
     return was_cw;
 }
@@ -223,13 +214,15 @@ ExtrusionLoop::last_point() const
     return this->paths.back().polyline.points.back();  // which coincides with first_point(), by the way
 }
 
-void
-ExtrusionLoop::polygon(Polygon* polygon) const
+Polygon
+ExtrusionLoop::polygon() const
 {
+    Polygon polygon;
     for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
         // for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
-        polygon->points.insert(polygon->points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
+        polygon.points.insert(polygon.points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
     }
+    return polygon;
 }
 
 double
diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp
index 4fba7fec7..323d935a1 100644
--- a/xs/src/libslic3r/ExtrusionEntity.hpp
+++ b/xs/src/libslic3r/ExtrusionEntity.hpp
@@ -92,14 +92,13 @@ class ExtrusionLoop : public ExtrusionEntity
     bool is_loop() const {
         return true;
     };
-    operator Polygon() const;
     ExtrusionLoop* clone() const;
     bool make_clockwise();
     bool make_counter_clockwise();
     void reverse();
     Point first_point() const;
     Point last_point() const;
-    void polygon(Polygon* polygon) const;
+    Polygon polygon() const;
     double length() const;
     bool split_at_vertex(const Point &point);
     void split_at(const Point &point);
diff --git a/xs/src/libslic3r/GUI/3DScene.cpp b/xs/src/libslic3r/GUI/3DScene.cpp
index 3266ae09d..d7513d2fe 100644
--- a/xs/src/libslic3r/GUI/3DScene.cpp
+++ b/xs/src/libslic3r/GUI/3DScene.cpp
@@ -2,25 +2,33 @@
 
 namespace Slic3r {
 
+// caller is responsible for supplying NO lines with zero length
 void
 _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
         const std::vector<double> &heights, bool closed, double top_z, const Point &copy,
         GLVertexArray* qverts, GLVertexArray* tverts)
 {
+    /* It looks like it's faster without reserving capacity...
+    // each segment has 4 quads, thus 16 vertices; + 2 caps
+    qverts->reserve_more(3 * 4 * (4 * lines.size() + 2));
+    
+    // two triangles for each corner
+    tverts->reserve_more(3 * 3 * 2 * (lines.size() + 1));
+    */
+    
     Line prev_line;
     Pointf prev_b1, prev_b2;
     Vectorf3 prev_xy_left_normal, prev_xy_right_normal;
     
     // loop once more in case of closed loops
     bool first_done = false;
-    for (int i = 0; i <= lines.size(); ++i) {
+    for (size_t i = 0; i <= lines.size(); ++i) {
         if (i == lines.size()) i = 0;
         
         const Line &line = lines.at(i);
         if (i == 0 && first_done && !closed) break;
         
         double len = line.length();
-        if (len == 0) continue;
         double unscaled_len = unscale(len);
         
         double bottom_z = top_z - heights.at(i);
@@ -52,7 +60,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
             // if we're making a ccw turn, draw the triangles on the right side, otherwise draw them on the left side
             double ccw = line.b.ccw(prev_line);
             if (ccw > EPSILON) {
-                tverts->reserve_more(6);
                 // top-right vertex triangle between previous line and this one
                 {
                     // use the normal going to the right calculated for the previous line
@@ -82,7 +89,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
                     tverts->push_vert(a1.x, a1.y, middle_z);
                 }
             } else if (ccw < -EPSILON) {
-                tverts->reserve_more(6);
                 // top-left vertex triangle between previous line and this one
                 {
                     // use the normal going to the left calculated for the previous line
@@ -126,8 +132,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
         if (!closed) {
             // terminate open paths with caps
             if (i == 0) {
-                qverts->reserve_more(4);
-                
                 // normal pointing downwards
                 qverts->push_norm(0,0,-1);
                 qverts->push_vert(a.x, a.y, bottom_z);
@@ -144,8 +148,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
                 qverts->push_norm(xy_left_normal);
                 qverts->push_vert(a2.x, a2.y, middle_z);
             } else if (i == lines.size()-1) {
-                qverts->reserve_more(4);
-                
                 // normal pointing downwards
                 qverts->push_norm(0,0,-1);
                 qverts->push_vert(b.x, b.y, bottom_z);
@@ -164,8 +166,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
             }
         }
         
-        qverts->reserve_more(16);
-        
         // bottom-right face
         {
             // normal going downwards
@@ -228,7 +228,7 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
 void
 GLVertexArray::load_mesh(const TriangleMesh &mesh)
 {
-    this->reserve_more(3 * mesh.facets_count());
+    this->reserve_more(3 * 3 * mesh.facets_count());
     
     for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
         stl_facet &facet = mesh.stl.facet_start[i];
diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp
index 61c84a802..614306e42 100644
--- a/xs/src/libslic3r/MultiPoint.cpp
+++ b/xs/src/libslic3r/MultiPoint.cpp
@@ -89,6 +89,17 @@ MultiPoint::bounding_box() const
     return BoundingBox(this->points);
 }
 
+void
+MultiPoint::remove_duplicate_points()
+{
+    for (size_t i = 1; i < this->points.size(); ++i) {
+        if (this->points.at(i).coincides_with(this->points.at(i-1))) {
+            this->points.erase(this->points.begin() + i);
+            --i;
+        }
+    }
+}
+
 Points
 MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
 {
diff --git a/xs/src/libslic3r/MultiPoint.hpp b/xs/src/libslic3r/MultiPoint.hpp
index e87c5166e..12c500836 100644
--- a/xs/src/libslic3r/MultiPoint.hpp
+++ b/xs/src/libslic3r/MultiPoint.hpp
@@ -32,6 +32,7 @@ class MultiPoint
     int find_point(const Point &point) const;
     bool has_boundary_point(const Point &point) const;
     BoundingBox bounding_box() const;
+    void remove_duplicate_points();
     
     static Points _douglas_peucker(const Points &points, const double tolerance);
     
diff --git a/xs/xsp/ExtrusionLoop.xsp b/xs/xsp/ExtrusionLoop.xsp
index a0f8de27c..0da0fe0d4 100644
--- a/xs/xsp/ExtrusionLoop.xsp
+++ b/xs/xsp/ExtrusionLoop.xsp
@@ -15,8 +15,7 @@
     bool make_counter_clockwise();
     Clone<Point> first_point();
     Clone<Point> last_point();
-    Clone<Polygon> polygon()
-        %code{% RETVAL = Polygon(*THIS); %};
+    Clone<Polygon> polygon();
     void append(ExtrusionPath* path)
         %code{% THIS->paths.push_back(*path); %};
     double length();
diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp
index 3300f12c3..98cd44e94 100644
--- a/xs/xsp/Polyline.xsp
+++ b/xs/xsp/Polyline.xsp
@@ -37,6 +37,7 @@
         %code{% THIS->split_at(*point, p1, p2); %};
     bool is_straight();
     Clone<BoundingBox> bounding_box();
+    void remove_duplicate_points();
     std::string wkt();
 %{