npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

barsort

v0.13.1

Published

Javascripts fastest numeric sort

Downloads

8

Readme

Barsort

Possibly the fastest general purpose and stable numeric sort function on NPM. Specialised to work on numeric input only (integers and reals).

Barsort utilises a specialised algorithm similar to 'counting sort' which was made to place array elements into groups of equal size with similar magnitudes. It is combined here with tweaked insert and merge sorts, and with edge case processing to create a very fast numeric sort.

Testing across a large range of possible input distributions and sizes shows barsort is many times faster than nodes native sort and faster in most cases than a profficient javascript implementation of Pythons optimised 'Timsort' - which is for numeric input the next fastest sorting module on npm.

Usage


//node install
npm install --save barsort

Barsort=require('./barsort.js')
 
//return a sorted index to array ([opt. params])
index_arr = Barsort.sortorder( array [,index_arr][,"descend"] )  
 
//return a sorted clone of array
sorted_arr = Barsort.sort( array [,"descend"] )      
  

Summary of speedtests:

Pre-sorted input, Lengths: | 100 | 10,000 | 1,000,000 :-------------- | :-------: | :---------: | :---------- Barsort sort | 100 % | 100 % | 100 % Native sort | 5 % | 2 % | 2 % Timsort sort | 100 % | 100 % | 100 %

Gaussian distribution | 100 | 10,000 | 1,000,000 :-------------- | :-------: | :---------: | :---------- Barsort sort | 100 % | 100 % | 100 % Native sort | 2 % | 2 % | 2 % Timsort sort | 100 % | 60 % | 60 %

Tough distribution | 100 | 10,000 | 1,000,000
:-------------- | :-------: | :---------: | :---------- Barsort sort | 100 % | 100 % | 100 % Native sort | 10 % | 10 % | 10 % Timsort sort | 100 % | 65 % | 65 %

These summarise very generally benchmark results in test_sort.log

Barsort is about twice as fast as Timsort in many cases and significantly slower in very few.

See also

Timsort is a popular multipurpose in-place sort.

LSD Radix Sort is 3x Barsort speed but is limited to unsigned integers and can not arrange an index.

Barsort algorithm basics - a "counting sort"

The input numbers are first tallied into bins as though calculating a histogram (by dividing by a suitable factor and casting to integer to get a bin number). Like this:

  for(var i=0; i<e; i++) 
  { kysbin[i]=(binperval*(kysval[i]-minv))>>0  } 

These "counting bins" are subsequently indexed by a fewer number of "placement bins". Originally the algorithm was developed to sort data roughly into histogram bars ( without sorting within the bars). The "counting bins" were subdivisions of the bars to reduce spillage between the bars. So, the cumulative sum of the populations of the placement bins is calculated so that for each placement bin an anchor position in the sorting index (output) is known (for values of bins range).

Like this:

  for(var bin=0; bin<nbin; bin++){
    
    barofbin[bin]=fillbar            //fillbar is the bar to fill currently
    barsfill[fillbar]+=cntofbin[bin] //here it is being allocated a bins tally 

    while(barsfill[fillbar]>=fcap){   //when bar is full... 
      barsfill[fillbar+1]+=barsfill[fillbar]-fcap
      barsfill[fillbar]=fcap
      fillbar++                //...fill next bar
      nxtcap+=kysperbar-fcap   //nxtcap and kysperbar are floats
      fcap=nxtcap >>>0         //fcap is integer (it differs for each bar)
    }
  } 

Finally some 'curious' multi-indirected lookup and updating is done for each input to use the base placement info to assign inputs their position in the sorting index.

Here is that final 'curious' code:

  var bapos=new Array(nbar); bapos[0]=0 //( before_anchor_pos )
  for(var i=0;i<nbar-1;i++){ bapos[i+1]=bapos[i]+barsfill[i] }

  for(var i=st; i<ov; i++){
    var binofel=kysbin[i] 
    
    //(change barofbin if barsfill is empty)
    while( barsfill[barofbin[binofel]]===0 ){ 
      barofbin[binofel]++ 
    }
    barsfill[barofbin[binofel]]--          
    sortix[ bapos[barofbin[binofel]]++ ]=i //sort index gets ordered by bar
  }
  // (this is not the unpresentable part...)

The counting sort is used to get elements quite close to where thay should be but they need to be fine-sorted afterward. The classic "insertion sort" is perfect for fine sorting as long it never has to move any elements too far. It is combined with mergesort to cope with rare problem cases.

Version History

  • 0.5.0 - pre release, in use and testing ...
  • 0.6.0 - repo fixed, pre release in use and testing ...
  • 0.9.0 - much developed and testing ...
  • 0.13.0 - ...much more developed and tested.