innodb_ruby 0.9.12 → 0.9.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/bin/innodb_space +360 -4
  2. data/lib/innodb/version.rb +1 -1
  3. metadata +2 -2
@@ -11,6 +11,10 @@ def rgb_to_ansi(rgb)
11
11
  16 + (rgb_n[0] * 36) + (rgb_n[1] * 6) + rgb_n[2]
12
12
  end
13
13
 
14
+ def rgb_to_rgbhex(rgb)
15
+ rgb.map { |c| "%02x" % [(c * 255.0).round] }.join
16
+ end
17
+
14
18
  # Interpolate intermediate float-arrays between two float-arrays. Do not
15
19
  # include the points a and b in the result.
16
20
  def interpolate(a, b, count)
@@ -49,6 +53,10 @@ HEATMAP_PROGRESSION = [
49
53
  # Typical heatmap color progression.
50
54
  ANSI_COLORS_HEATMAP = interpolate_sequence(HEATMAP_PROGRESSION, 6).map { |rgb| rgb_to_ansi(rgb) }
51
55
 
56
+ RGBHEX_COLORS_HEATMAP = interpolate_sequence(HEATMAP_PROGRESSION, 41).map { |rgb| rgb_to_rgbhex(rgb) }
57
+
58
+ RGBHEX_COLORS_RANDOM = 100.times.inject([]) { |a, x| a << rgb_to_rgbhex([rand * 0.7 + 0.25, rand * 0.7 + 0.25, rand * 0.7 + 0.25]) }
59
+
52
60
  # The 24-step grayscale progression.
53
61
  ANSI_COLORS_GRAYSCALE = (0xe8..0xff).to_a
54
62
 
@@ -83,6 +91,35 @@ def filled_block(fraction, identifier=nil, block_chars=BLOCK_CHARS_V)
83
91
  end
84
92
  end
85
93
 
94
+ def svg_join_args(args)
95
+ args.map { |arg| "%s=\"%s\"" % [ arg[0], arg[1], ] }.join(" ")
96
+ end
97
+
98
+ def svg(elem, args, content=nil)
99
+ if content
100
+ "<" + elem.to_s + " " + svg_join_args(args) + ">" +
101
+ content.to_s +
102
+ "</" + elem.to_s + ">"
103
+ else
104
+ "<" + elem.to_s + " " + svg_join_args(args) + " />"
105
+ end
106
+ end
107
+
108
+ def svg_path_rounded_rect(x, y, w, h, r)
109
+ [
110
+ "M%i,%i" % [ x + r, y - r ],
111
+ "L%i,%i" % [ x + w - r, y - r ],
112
+ "S%i,%i %i,%i" % [ x + w + r, y - r, x + w + r, y + r ],
113
+ "L%i,%i" % [ x + w + r, y + h - r ],
114
+ "S%i,%i %i,%i" % [ x + w + r, y + h + r, x + w - r, y + h + r ],
115
+ "L%i,%i" % [ x + r, y + h + r ],
116
+ "S%i,%i %i,%i" % [ x - r, y + h + r, x - r, y + h - r ],
117
+ "L%i,%i" % [ x - r, y + r ],
118
+ "S%i,%i %i,%i" % [ x - r, y - r, x + r, y - r ],
119
+ "Z",
120
+ ].join(" ")
121
+ end
122
+
86
123
  # Print metadata about each list in an array of InnoDB::List objects.
87
124
  def print_lists(lists)
88
125
  puts "%-20s%-12s%-12s%-12s%-12s%-12s" % [
@@ -504,6 +541,7 @@ def space_extents_illustrate(space)
504
541
  },
505
542
  ]
506
543
  end
544
+ total_pages = count_by_identifier.values.reduce(:+)
507
545
 
508
546
  puts "%12s ╰%-#{width}s╯" % [ "", "─" * width ]
509
547
 
@@ -516,25 +554,210 @@ def space_extents_illustrate(space)
516
554
  filled_block(1.0, nil),
517
555
  "System",
518
556
  count_by_identifier[nil],
519
- 100.0 * (count_by_identifier[nil].to_f / space.pages.to_f),
557
+ 100.0 * (count_by_identifier[nil].to_f / total_pages.to_f),
520
558
  ]
521
559
  identifiers.sort.each do |identifier, description|
522
560
  puts " %s %-60s %8i %7.2f%%" % [
523
561
  filled_block(1.0, identifier),
524
562
  description,
525
563
  count_by_identifier[identifier],
526
- 100.0 * (count_by_identifier[identifier].to_f / space.pages.to_f),
564
+ 100.0 * (count_by_identifier[identifier].to_f / total_pages.to_f),
527
565
  ]
528
566
  end
529
567
  puts " %s %-60s %8i %7.2f%%" % [
530
568
  filled_block(0.0, nil),
531
569
  "Free space",
532
570
  count_by_identifier[:free],
533
- 100.0 * (count_by_identifier[:free].to_f / space.pages.to_f),
571
+ 100.0 * (count_by_identifier[:free].to_f / total_pages.to_f),
534
572
  ]
535
573
  puts
536
574
  end
537
575
 
576
+ def svg_extent_legend(x, y, block_size, color=nil, description=nil, pages=nil, ratio=nil)
577
+ [
578
+ svg("rect", {
579
+ "y" => y,
580
+ "x" => x,
581
+ "width" => block_size,
582
+ "height" => block_size,
583
+ "fill" => color ? color : "white",
584
+ "stroke" => description ? "black" : "none",
585
+ }),
586
+ svg("text", {
587
+ "y" => y + block_size - 4,
588
+ "x" => x + (description ? block_size + 5 : 0),
589
+ "font-family" => "monospace",
590
+ "font-size" => block_size,
591
+ "font-weight" => description ? "normal" : "bold",
592
+ "text-anchor" => "start",
593
+ }, description ? description : "Page Type"),
594
+ svg("text", {
595
+ "y" => y + block_size - 4,
596
+ "x" => x + block_size + 5 + (40 * block_size),
597
+ "font-family" => "monospace",
598
+ "font-size" => block_size,
599
+ "font-weight" => description ? "normal" : "bold",
600
+ "text-anchor" => "end",
601
+ }, pages ? pages : "Pages"),
602
+ svg("text", {
603
+ "y" => y + block_size - 4,
604
+ "x" => x + block_size + 5 + (40 * block_size) + (10 * block_size),
605
+ "font-family" => "monospace",
606
+ "font-size" => block_size,
607
+ "font-weight" => description ? "normal" : "bold",
608
+ "text-anchor" => "end",
609
+ }, ratio ? ("%7.2f%%" % [ratio]) : "Ratio"),
610
+ ].join("\n")
611
+ end
612
+
613
+ # Illustrate the space by printing each extent and for each page, printing a
614
+ # filled block colored based on the index the page is part of. Print a legend
615
+ # for the colors used afterwards.
616
+ def space_extents_illustrate_svg(space)
617
+ width = space.pages_per_extent
618
+
619
+ puts "<?xml version=\"1.0\"?>"
620
+ puts "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
621
+
622
+ identifiers = {}
623
+ count_by_identifier = Hash.new(0)
624
+
625
+ block_size = 16
626
+ graphic_x = 48
627
+ graphic_y = 16
628
+
629
+ puts svg("text", {
630
+ "y" => graphic_y - 3,
631
+ "x" => graphic_x - 7,
632
+ "font-family" => "monospace",
633
+ "font-size" => block_size,
634
+ "font-weight" => "bold",
635
+ "text-anchor" => "end",
636
+ }, "Page")
637
+
638
+ block_x = 0
639
+ block_y = 0
640
+ space.each_xdes do |entry|
641
+ block_x = 0
642
+
643
+ puts svg("text", {
644
+ "y" => graphic_y + block_y + block_size,
645
+ "x" => graphic_x - 7,
646
+ "font-family" => "monospace",
647
+ "font-size" => block_size,
648
+ "text-anchor" => "end",
649
+ }, entry.xdes[:start_page])
650
+
651
+ entry.each_page_status do |page_number, page_status|
652
+ if page_number < space.pages
653
+ used_fraction = 1.0
654
+ identifier = nil
655
+ if page_status[:free]
656
+ used_fraction = 0.0
657
+ else
658
+ page = space.page(page_number)
659
+ if page.respond_to?(:used_space)
660
+ used_fraction = page.used_space.to_f / page.size.to_f
661
+ end
662
+ if page.respond_to?(:index_id)
663
+ identifier = page.index_id
664
+ unless identifiers[identifier]
665
+ identifiers[identifier] = (page.index_id == Innodb::IbufIndex::INDEX_ID) ?
666
+ "Insert Buffer Index" :
667
+ "Index #{page.index_id}"
668
+ if space.innodb_system
669
+ table, index = space.innodb_system.table_and_index_name_by_id(page.index_id)
670
+ if table && index
671
+ identifiers[identifier] += " (%s.%s)" % [table, index]
672
+ end
673
+ end
674
+ end
675
+ end
676
+ end
677
+ if used_fraction != 0.0
678
+ count_by_identifier[identifier] += 1
679
+ else
680
+ count_by_identifier[:free] += 1
681
+ end
682
+
683
+ block_height = block_size * used_fraction
684
+ color = "black"
685
+ if identifier
686
+ color = "#" + RGBHEX_COLORS_RANDOM[(identifier * COLOR_SPACING_PRIME) % RGBHEX_COLORS_RANDOM.size]
687
+ end
688
+ puts svg("rect", {
689
+ "x" => graphic_x + block_x,
690
+ "y" => graphic_y + block_y + (block_size - block_height),
691
+ "width" => block_size,
692
+ "height" => block_height,
693
+ "fill" => color,
694
+ })
695
+ end
696
+ block_x += block_size
697
+ end
698
+ block_y += block_size
699
+ end
700
+
701
+ puts svg("path", {
702
+ "stroke" => "black",
703
+ "stroke-width" => 1,
704
+ "fill" => "none",
705
+ "d" => svg_path_rounded_rect(
706
+ graphic_x,
707
+ graphic_y,
708
+ block_x,
709
+ block_y,
710
+ 4
711
+ ),
712
+ })
713
+
714
+ block_x = 0
715
+ block_y += 10
716
+ puts svg_extent_legend(
717
+ graphic_x + block_x,
718
+ graphic_y + block_y,
719
+ block_size,
720
+ )
721
+ block_y += block_size + 2
722
+
723
+ puts svg_extent_legend(
724
+ graphic_x + block_x,
725
+ graphic_y + block_y,
726
+ block_size,
727
+ "black",
728
+ "System",
729
+ count_by_identifier[nil],
730
+ 100.0 * (count_by_identifier[nil].to_f / space.pages.to_f)
731
+ )
732
+ block_y += block_size + 2
733
+
734
+ identifiers.sort.each do |identifier, description|
735
+ puts svg_extent_legend(
736
+ graphic_x + block_x,
737
+ graphic_y + block_y,
738
+ block_size,
739
+ "#" + RGBHEX_COLORS_RANDOM[(identifier * COLOR_SPACING_PRIME) % RGBHEX_COLORS_RANDOM.size],
740
+ description,
741
+ count_by_identifier[identifier],
742
+ 100.0 * (count_by_identifier[identifier].to_f / space.pages.to_f)
743
+ )
744
+ block_y += block_size + 2
745
+ end
746
+
747
+ puts svg_extent_legend(
748
+ graphic_x + block_x,
749
+ graphic_y + block_y,
750
+ block_size,
751
+ "white",
752
+ "Free space",
753
+ count_by_identifier[:free],
754
+ 100.0 * (count_by_identifier[:free].to_f / space.pages.to_f)
755
+ )
756
+
757
+ puts "</svg>"
758
+ end
759
+
760
+
538
761
  def space_lsn_age_illustrate(space)
539
762
  colors = ANSI_COLORS_HEATMAP
540
763
 
@@ -615,6 +838,125 @@ def space_lsn_age_illustrate(space)
615
838
  ]
616
839
  end
617
840
 
841
+ def space_lsn_age_illustrate_svg(space)
842
+ colors = RGBHEX_COLORS_HEATMAP
843
+
844
+ puts "<?xml version=\"1.0\"?>"
845
+ puts "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">"
846
+
847
+ # Calculate the minimum and maximum LSN in the space. This is pretty
848
+ # inefficient as we end up scanning all pages twice.
849
+ page_lsn = Array.new(space.pages)
850
+
851
+ lsn_min = lsn_max = space.page(0).lsn
852
+ space.each_page do |page_number, page|
853
+ if page.lsn != 0
854
+ page_lsn[page_number] = page.lsn
855
+ lsn_min = page.lsn < lsn_min ? page.lsn : lsn_min
856
+ lsn_max = page.lsn > lsn_max ? page.lsn : lsn_max
857
+ end
858
+ end
859
+ lsn_delta = lsn_max - lsn_min
860
+
861
+ block_size = 16
862
+ graphic_x = 48
863
+ graphic_y = 16
864
+
865
+ block_x = 0
866
+ block_y = 0
867
+
868
+ puts svg("text", {
869
+ "y" => graphic_y - 3,
870
+ "x" => graphic_x - 7,
871
+ "font-family" => "monospace",
872
+ "font-size" => block_size,
873
+ "font-weight" => "bold",
874
+ "text-anchor" => "end",
875
+ }, "Page")
876
+
877
+ start_page = 0
878
+ page_lsn.each_slice(64) do |slice|
879
+ block_x = 0
880
+ slice.each do |lsn|
881
+ rgbhex = ""
882
+ if lsn
883
+ age_ratio = (lsn - lsn_min).to_f / lsn_delta.to_f
884
+ color = colors[(age_ratio * colors.size.to_f).floor]
885
+ end
886
+ puts svg("rect", {
887
+ "y" => graphic_y + block_y,
888
+ "x" => graphic_x + block_x,
889
+ "width" => block_size,
890
+ "height" => block_size,
891
+ "fill" => color ? "#" + color : "black",
892
+ })
893
+ block_x += block_size
894
+ end
895
+ puts svg("text", {
896
+ "y" => graphic_y + block_y + block_size,
897
+ "x" => graphic_x - 7,
898
+ "font-family" => "monospace",
899
+ "font-size" => block_size,
900
+ "text-anchor" => "end",
901
+ }, start_page)
902
+ block_y += block_size
903
+ start_page += 64
904
+ end
905
+
906
+ puts svg("path", {
907
+ "stroke" => "black",
908
+ "stroke-width" => 1,
909
+ "fill" => "none",
910
+ "d" => svg_path_rounded_rect(
911
+ graphic_x,
912
+ graphic_y,
913
+ block_x,
914
+ block_y,
915
+ 4
916
+ ),
917
+ })
918
+
919
+ block_x = 0
920
+ block_y += 16
921
+ puts svg("text", {
922
+ "y" => graphic_y + block_y + block_size - 4,
923
+ "x" => graphic_x + block_x,
924
+ "font-family" => "monospace",
925
+ "font-size" => block_size,
926
+ "text-anchor" => "start",
927
+ }, lsn_min)
928
+ color_width = ((64.0 * block_size.to_f) / colors.size.to_f).round
929
+ colors.each do |color|
930
+ puts svg("rect", {
931
+ "y" => graphic_y + block_y + block_size,
932
+ "x" => graphic_x + block_x,
933
+ "width" => color_width,
934
+ "height" => block_size,
935
+ "fill" => "#" + color,
936
+ })
937
+ block_x += color_width
938
+ end
939
+ puts svg("text", {
940
+ "y" => graphic_y + block_y + block_size - 4,
941
+ "x" => graphic_x + block_x,
942
+ "font-family" => "monospace",
943
+ "font-size" => block_size,
944
+ "text-anchor" => "end",
945
+ }, lsn_max)
946
+
947
+ puts svg("text", {
948
+ "y" => graphic_y + block_y + block_size - 4,
949
+ "x" => graphic_x + (block_x / 2),
950
+ "font-family" => "monospace",
951
+ "font-weight" => "bold",
952
+ "font-size" => block_size,
953
+ "text-anchor" => "middle",
954
+ }, "LSN Age")
955
+
956
+
957
+ puts "</svg>\n"
958
+ end
959
+
618
960
  def print_inode_summary(inode)
619
961
  puts "INODE fseg_id=%d, pages=%d, frag=%d, full=%d, not_full=%d, free=%d" % [
620
962
  inode.fseg_id,
@@ -1193,9 +1535,19 @@ The following modes are supported:
1193
1535
  color and Unicode box drawing characters to show page usage throughout
1194
1536
  the space.
1195
1537
 
1538
+ space-extents-illustrate-svg
1539
+ Iterate through all extents, illustrating the extent usage in SVG format
1540
+ printed to stdout to show page usage throughout the space.
1541
+
1196
1542
  space-lsn-age-illustrate
1197
1543
  Iterate through all pages, producing a heat map colored by the page LSN
1198
- allowing the user to get an overview of page modification recency.
1544
+ using ANSI color and Unicode box drawing characters, allowing the user to
1545
+ get an overview of page modification recency.
1546
+
1547
+ space-lsn-age-illustrate-svg
1548
+ Iterate through all pages, producing a heat map colored by the page LSN
1549
+ producing SVG format output, allowing the user to get an overview of page
1550
+ modification recency.
1199
1551
 
1200
1552
  space-inodes-summary
1201
1553
  Iterate through all inodes, printing a short summary of each FSEG.
@@ -1468,8 +1820,12 @@ when "space-extents"
1468
1820
  space_extents(space)
1469
1821
  when "space-extents-illustrate"
1470
1822
  space_extents_illustrate(space)
1823
+ when "space-extents-illustrate-svg"
1824
+ space_extents_illustrate_svg(space)
1471
1825
  when "space-lsn-age-illustrate"
1472
1826
  space_lsn_age_illustrate(space)
1827
+ when "space-lsn-age-illustrate-svg"
1828
+ space_lsn_age_illustrate_svg(space)
1473
1829
  when "space-inodes-summary"
1474
1830
  space_inodes_summary(space)
1475
1831
  when "space-inodes-detail"
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  module Innodb
4
- VERSION = "0.9.12"
4
+ VERSION = "0.9.13"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: innodb_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.12
4
+ version: 0.9.13
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-10-03 00:00:00.000000000 Z
13
+ date: 2015-06-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bindata