diff --git a/src/bundles/graphics/_graphics/mesh_edges.cpp b/src/bundles/graphics/_graphics/mesh_edges.cpp
index e0537a835..d4449d505 100644
--- a/src/bundles/graphics/_graphics/mesh_edges.cpp
+++ b/src/bundles/graphics/_graphics/mesh_edges.cpp
@@ -13,7 +13,7 @@
  * === UCSF ChimeraX Copyright ===
  */
 
-#include <set>				// use std::set
+#include <unordered_set>				// use std::unordered_set
 
 #include <arrays/pythonarray.h>		// use array_from_python()
 #include <arrays/rcarray.h>		// use Numeric_Array, Array<T>
@@ -25,6 +25,16 @@
 namespace Map_Cpp
 {
 
+
+struct edge_hash
+{
+  std::size_t operator() (const std::pair<int, int> &edge) const noexcept
+  {
+    // hash used by Blender: https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/blenlib/intern/edgehash.c#L93
+    return edge.first << 8 ^ edge.second; 
+  }
+};
+
 // ----------------------------------------------------------------------------
 // Find edges of displayed triangles.  Edges that appear in 2 or more triangles
 // are only listed once.
@@ -32,7 +42,7 @@ namespace Map_Cpp
 static IArray calculate_masked_edges(const IArray &triangles,
 				     const BArray &tmask, const BArray &emask)
 {
-  std::set< std::pair<int,int> > edges;
+  std::unordered_set< std::pair<int,int>, edge_hash > edges;
 
   unsigned char *show_t = (tmask.size() > 0 ? tmask.values() : NULL);
   unsigned char *show_e = (emask.size() > 0 ? emask.values() : NULL);
@@ -56,7 +66,7 @@ static IArray calculate_masked_edges(const IArray &triangles,
   int64_t size[2] = {(int64_t)edges.size(), 2};
   IArray masked_edges(2, size);
   int *eiarray = masked_edges.values();
-  for (std::set< std::pair<int,int> >::iterator ei = edges.begin() ; 
+  for (auto ei = edges.begin() ; 
        ei != edges.end() ; ++ei)
     {
       *eiarray = (*ei).first; eiarray += 1;
