@@ -501,34 +501,56 @@ struct commit *pop_commit(struct commit_list **stack)
501501 return item ;
502502}
503503
504+ struct commit_slab_piece {
505+ int buf ;
506+ };
507+
504508struct commit_slab {
505- int * buf ;
506- int alloc ;
509+ int piece_size ;
510+ int piece_count ;
511+ struct commit_slab_piece * * piece ;
507512};
508513
509514static void slab_init (struct commit_slab * s )
510515{
511- memset (s , 0 , sizeof (* s ));
516+ /* allocate ~512kB at once, allowing for malloc overhead */
517+ int size = (512 * 1024 - 32 ) / sizeof (struct commit_slab_piece );
518+
519+ s -> piece_size = size ;
520+ s -> piece_count = 0 ;
521+ s -> piece = NULL ;
512522}
513523
514524static void slab_clear (struct commit_slab * s )
515525{
516- free (s -> buf );
517- slab_init (s );
526+ int i ;
527+
528+ for (i = 0 ; i < s -> piece_count ; i ++ )
529+ free (s -> piece [i ]);
530+ s -> piece_count = 0 ;
531+ free (s -> piece );
532+ s -> piece = NULL ;
518533}
519534
520- static inline int * slab_at (struct commit_slab * s , const struct commit * c )
535+ static inline struct commit_slab_piece * slab_at (struct commit_slab * s ,
536+ const struct commit * c )
521537{
522- if (s -> alloc <= c -> index ) {
523- int new_alloc = alloc_nr (s -> alloc );
524- if (new_alloc <= c -> index )
525- new_alloc = c -> index + 1 ;
526-
527- s -> buf = xrealloc (s -> buf , new_alloc * sizeof (* s -> buf ));
528- memset (s -> buf + s -> alloc , 0 , new_alloc - s -> alloc );
529- s -> alloc = new_alloc ;
538+ int nth_piece , nth_slot ;
539+
540+ nth_piece = c -> index / s -> piece_size ;
541+ nth_slot = c -> index % s -> piece_size ;
542+
543+ if (s -> piece_count <= nth_piece ) {
544+ int i ;
545+
546+ s -> piece = xrealloc (s -> piece , (nth_piece + 1 ) * sizeof (s -> piece ));
547+ for (i = s -> piece_count ; i <= nth_piece ; i ++ )
548+ s -> piece [i ] = NULL ;
549+ s -> piece_count = nth_piece + 1 ;
530550 }
531- return s -> buf + c -> index ;
551+ if (!s -> piece [nth_piece ])
552+ s -> piece [nth_piece ] = xcalloc (s -> piece_size , sizeof (* * s -> piece ));
553+ return & s -> piece [nth_piece ][nth_slot ];
532554}
533555
534556/*
@@ -550,15 +572,15 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
550572 /* Mark them and clear the indegree */
551573 for (next = orig ; next ; next = next -> next ) {
552574 struct commit * commit = next -> item ;
553- * slab_at (& indegree , commit ) = 1 ;
575+ slab_at (& indegree , commit )-> buf = 1 ;
554576 }
555577
556578 /* update the indegree */
557579 for (next = orig ; next ; next = next -> next ) {
558580 struct commit_list * parents = next -> item -> parents ;
559581 while (parents ) {
560582 struct commit * parent = parents -> item ;
561- int * pi = slab_at (& indegree , parent );
583+ int * pi = & slab_at (& indegree , parent )-> buf ;
562584
563585 if (* pi )
564586 (* pi )++ ;
@@ -578,7 +600,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
578600 for (next = orig ; next ; next = next -> next ) {
579601 struct commit * commit = next -> item ;
580602
581- if (* slab_at (& indegree , commit ) == 1 )
603+ if (slab_at (& indegree , commit )-> buf == 1 )
582604 insert = & commit_list_insert (commit , insert )-> next ;
583605 }
584606
@@ -599,7 +621,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
599621 commit = work_item -> item ;
600622 for (parents = commit -> parents ; parents ; parents = parents -> next ) {
601623 struct commit * parent = parents -> item ;
602- int * pi = slab_at (& indegree , parent );
624+ int * pi = & slab_at (& indegree , parent )-> buf ;
603625
604626 if (!* pi )
605627 continue ;
@@ -620,7 +642,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
620642 * work_item is a commit all of whose children
621643 * have already been emitted. we can emit it now.
622644 */
623- * slab_at (& indegree , commit ) = 0 ;
645+ slab_at (& indegree , commit )-> buf = 0 ;
624646 * pptr = work_item ;
625647 pptr = & work_item -> next ;
626648 }
0 commit comments