How we drew several thousand interactive objects on the map without harming performance

Hi, my name is Daria and I am the Frontend developer of the Geo unit in Avito. I would like to share my experience of how we made a new map search on the web, replacing clusters with a more convenient solution and removing the limitation on the number of displayed objects.



In this article, I will tell you what the task was and how we dealt with the problems in the implementation process.





Why the old map search did not suit us



    ,  — .  —     ,  .  —    .



    . -,      ,       . -,  — .    , .



:







,  , , ,     . ,    — .



 ,   .   , ,   .



      , , , .  —  .     , , . ,    , , . :



limit=viewPort.width×viewPort.height/(pinDiameter2×9)



, , .



   , .   , .   :



  •   ( );
  •   ( , );
  • ,   ,   (  ).


    :





  — . ,  —





,  —





, , —



,     , , .





  ,   1000 .     , , . , :





 



-, API . ,   ObjectManager,  ,   1000.   , , 3000 ,    .



,    .   API - — ,   Layer.



API  ,   (  png svg ) , X, Y Z. ,   -     . , API   ,     ( ), - .





 .   .  —



  ,     .    .



,       :



func (*Tile) Deg2num(t *Tile) (x int, y int) {
    x = int(math.Floor((t.Long + 180.0) / 360.0 * (math.Exp2(float64(t.Z)))))
    y = int(math.Floor((1.0 - math.Log(math.Tan(t.Lat*math.Pi/180.0)+1.0/math.Cos(t.Lat*math.Pi/180.0))/math.Pi) / 2.0 * (math.Exp2(float64(t.Z)))))
    return
}

func (*Tile) Num2deg(t *Tile) (lat float64, long float64) {
    n := math.Pi - 2.0*math.Pi*float64(t.Y)/math.Exp2(float64(t.Z))
    lat = 180.0 / math.Pi * math.Atan(0.5*(math.Exp(n)-math.Exp(-n)))
    long = float64(t.X)/math.Exp2(float64(t.Z))*360.0 - 180.0
    return lat, long
}


 Go,      .



svg  , :





   ,  GET-  .     :



const createTilesUrl = (tileNumber, tileZoom) => {
// params -      ,     GET-
return `/web/1/map/tiles?${params}&z=${tileZoom}&x=${tileNumber[0]}&y=${tileNumber[1]}`;
};
const tilesLayer = new window.ymaps.Layer(createTilesUrl, { tileTransparent: true });
ymap.layers.add(tilesLayer);


 ,    Layer, :







,   15-30    ,       5000 rps.        ,   . ,     .



  ,     , . .     . ,  , , 4, 25.



.    ,     .





     Redis  -,   , .   ,     , ,  . ,      .



, ,  ,   .   , .



 Redis .   , ,    , ,     .  Redis  in-memory.    Redis.



  , ,     .  in-memory cache ,   . -.   :





 99  ~140 ms. 99% .  :     ~230 ms   .



:    , , .   ,   svg.   ,   .





,    .  .



,



.   ,  .    —    , ,       50 . , .    ,   , ,   .  —   ,  . ,   ,  —  ,  .



,  .  ,    .  ,  ,   .    —   . ,    . , , . ,   , —     , , id   . ,     .





.    —     ,   -  , . ,  .    10   forEach .





.    .  localStorage  1000 id . Ids , .   , ,    localStorage.



,  .  ,  — ,  — .   .



    ,    -.  /, , , .   .



    svg  .  - .





-





-





,       —   .




All Articles