├── .gitignore ├── cpu1.svg ├── cpu2.svg ├── cpu3.svg ├── cpu4.svg ├── cpu5.svg ├── cpu6.svg ├── cpu7.svg ├── cpu8.svg ├── cpu9.svg ├── list.go ├── node.go ├── node_test.go └── testdata └── edges.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.prof 2 | *.test 3 | -------------------------------------------------------------------------------- /cpu6.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 292 | graphblog.test 293 | 294 | 295 | cluster_L 296 | 297 | 298 | 299 | 300 | L 301 | 302 | File: graphblog.test 303 | Type: cpu 304 | Time: Jul 23, 2017 at 1:37pm (BST) 305 | Duration: 8.020486356s 306 | 9.13s of 9.30s total (98.17%) 307 | Dropped 38 nodes (cum <= 0.05s) 308 | 309 | 310 | 311 | N1 312 | 313 | 314 | runtime.mach_semaphore_signal 315 | 1.87s(20.11%) 316 | 317 | 318 | 319 | 320 | 321 | N2 322 | 323 | 324 | runtime.usleep 325 | 1.79s(19.25%) 326 | 327 | 328 | 329 | 330 | 331 | N3 332 | 333 | 334 | runtime.heapBitsForObject 335 | 0.91s(9.78%) 336 | 337 | 338 | 339 | 340 | 341 | N4 342 | 343 | 344 | runtime.writebarrierptr_prewrite1 345 | 0.60s(6.45%) 346 | of 3.38s(36.34%) 347 | 348 | 349 | 350 | 351 | 352 | N10 353 | 354 | 355 | runtime.systemstack 356 | 0.35s(3.76%) 357 | of 6.42s(69.03%) 358 | 359 | 360 | 361 | 362 | 363 | N4->N10 364 | 365 | 366 | 367 | 368 | 369 | 370 | 2.78s 371 | 372 | 373 | 374 | 375 | 376 | N5 377 | 378 | 379 | runtime.shade 380 | 0.59s(6.34%) 381 | of 2.09s(22.47%) 382 | 383 | 384 | 385 | 386 | 387 | N5->N3 388 | 389 | 390 | 391 | 392 | 393 | 394 | 0.91s 395 | 396 | 397 | 398 | 399 | 400 | N8 401 | 402 | 403 | runtime.greyobject 404 | 0.41s(4.41%) 405 | of 0.42s(4.52%) 406 | 407 | 408 | 409 | 410 | 411 | N5->N8 412 | 413 | 414 | 415 | 416 | 417 | 418 | 0.40s 419 | 420 | 421 | 422 | 423 | 424 | N14 425 | 426 | 427 | runtime.(*gcWork).dispose 428 | 0.19s(2.04%) 429 | 430 | 431 | 432 | 433 | 434 | N5->N14 435 | 436 | 437 | 438 | 439 | 440 | 441 | 0.19s 442 | 443 | 444 | 445 | 446 | 447 | N6 448 | 449 | 450 | github.com/philpearl/graphblog.nodes.longestShortestPath 451 | 0.56s(6.02%) 452 | of 5.04s(54.19%) 453 | 454 | 455 | 456 | 457 | 458 | N13 459 | 460 | 461 | runtime.writebarrierptr 462 | 0.26s(2.80%) 463 | of 3.64s(39.14%) 464 | 465 | 466 | 467 | 468 | 469 | N6->N13 470 | 471 | 472 | 473 | 474 | 475 | 476 | 3.64s 477 | 478 | 479 | 480 | 481 | 482 | N32 483 | 484 | 485 | runtime.makeslice 486 | 0 of 0.84s(9.03%) 487 | 488 | 489 | 490 | 491 | 492 | N6->N32 493 | 494 | 495 | 496 | 497 | 498 | 499 | 0.84s 500 | 501 | 502 | 503 | 504 | 505 | N7 506 | 507 | 508 | runtime.gcmarkwb_m 509 | 0.42s(4.52%) 510 | of 2.51s(26.99%) 511 | 512 | 513 | 514 | 515 | 516 | N7->N5 517 | 518 | 519 | 520 | 521 | 522 | 523 | 2.09s 524 | 525 | 526 | 527 | 528 | 529 | N9 530 | 531 | 532 | runtime.mach_semaphore_timedwait 533 | 0.37s(3.98%) 534 | 535 | 536 | 537 | 538 | 539 | N12 540 | 541 | 542 | runtime.writebarrierptr_prewrite1.func1 543 | 0.27s(2.90%) 544 | of 2.78s(29.89%) 545 | 546 | 547 | 548 | 549 | 550 | N10->N12 551 | 552 | 553 | 554 | 555 | 556 | 557 | 2.78s 558 | 559 | 560 | 561 | 562 | 563 | N23 564 | 565 | 566 | runtime.gcBgMarkWorker.func2 567 | 0 of 0.10s(1.08%) 568 | 569 | 570 | 571 | 572 | 573 | N10->N23 574 | 575 | 576 | 577 | 578 | 579 | 580 | 0.10s 581 | 582 | 583 | 584 | 585 | 586 | N33 587 | 588 | 589 | runtime.markroot.func1 590 | 0 of 1.83s(19.68%) 591 | 592 | 593 | 594 | 595 | 596 | N10->N33 597 | 598 | 599 | 600 | 601 | 602 | 603 | 1.83s 604 | 605 | 606 | 607 | 608 | 609 | N45 610 | 611 | 612 | runtime.semasleep.func1 613 | 0 of 0.54s(5.81%) 614 | 615 | 616 | 617 | 618 | 619 | N10->N45 620 | 621 | 622 | 623 | 624 | 625 | 626 | 0.54s 627 | 628 | 629 | 630 | 631 | 632 | N48 633 | 634 | 635 | runtime.startTheWorldWithSema 636 | 0 of 0.76s(8.17%) 637 | 638 | 639 | 640 | 641 | 642 | N10->N48 643 | 644 | 645 | 646 | 647 | 648 | 649 | 0.76s 650 | 651 | 652 | 653 | 654 | 655 | N11 656 | 657 | 658 | runtime.duffcopy 659 | 0.31s(3.33%) 660 | 661 | 662 | 663 | 664 | 665 | N12->N7 666 | 667 | 668 | 669 | 670 | 671 | 672 | 2.51s 673 | 674 | 675 | 676 | 677 | 678 | N13->N4 679 | 680 | 681 | 682 | 683 | 684 | 685 | 3.38s 686 | 687 | 688 | 689 | 690 | 691 | N15 692 | 693 | 694 | runtime.mach_semaphore_wait 695 | 0.17s(1.83%) 696 | 697 | 698 | 699 | 700 | 701 | N16 702 | 703 | 704 | runtime.scanobject 705 | 0.05s(0.54%) 706 | of 0.07s(0.75%) 707 | 708 | 709 | 710 | 711 | 712 | N16->N8 713 | 714 | 715 | 716 | 717 | 718 | 719 | 0.02s 720 | 721 | 722 | 723 | 724 | 725 | N17 726 | 727 | 728 | runtime.mallocgc 729 | 0.01s(0.11%) 730 | of 0.84s(9.03%) 731 | 732 | 733 | 734 | 735 | 736 | N17->N10 737 | 738 | 739 | 740 | 741 | 742 | 743 | 0.02s 744 | 745 | 746 | 747 | 748 | 749 | N26 750 | 751 | 752 | runtime.gcStart 753 | 0 of 0.77s(8.28%) 754 | 755 | 756 | 757 | 758 | 759 | N17->N26 760 | 761 | 762 | 763 | 764 | 765 | 766 | 0.77s 767 | 768 | 769 | 770 | 771 | 772 | N18 773 | 774 | 775 | github.com/philpearl/graphblog.BenchmarkDiameter.func1 776 | 0 of 5.04s(54.19%) 777 | 778 | 779 | 780 | 781 | 782 | N19 783 | 784 | 785 | github.com/philpearl/graphblog.nodes.diameter 786 | 0 of 5.04s(54.19%) 787 | 788 | 789 | 790 | 791 | 792 | N18->N19 793 | 794 | 795 | 796 | 797 | 798 | 799 | 5.04s 800 | 801 | 802 | 803 | 804 | 805 | N19->N6 806 | 807 | 808 | 809 | 810 | 811 | 812 | 5.04s 813 | 814 | 815 | 816 | 817 | 818 | N20 819 | 820 | 821 | runtime._System 822 | 0 of 0.35s(3.76%) 823 | 824 | 825 | 826 | 827 | 828 | N20->N10 829 | 830 | 831 | 832 | 833 | 834 | 835 | 0.35s 836 | 837 | 838 | 839 | 840 | 841 | N21 842 | 843 | 844 | runtime.findrunnable 845 | 0 of 0.18s(1.94%) 846 | 847 | 848 | 849 | 850 | 851 | N27 852 | 853 | 854 | runtime.gcstopm 855 | 0 of 0.11s(1.18%) 856 | 857 | 858 | 859 | 860 | 861 | N21->N27 862 | 863 | 864 | 865 | 866 | 867 | 868 | 0.01s 869 | 870 | 871 | 872 | 873 | 874 | N50 875 | 876 | 877 | runtime.stopm 878 | 0 of 0.17s(1.83%) 879 | 880 | 881 | 882 | 883 | 884 | N21->N50 885 | 886 | 887 | 888 | 889 | 890 | 891 | 0.17s 892 | 893 | 894 | 895 | 896 | 897 | N22 898 | 899 | 900 | runtime.gcBgMarkWorker 901 | 0 of 2.33s(25.05%) 902 | 903 | 904 | 905 | 906 | 907 | N22->N10 908 | 909 | 910 | 911 | 912 | 913 | 914 | 1.93s 915 | 916 | 917 | 918 | 919 | 920 | N25 921 | 922 | 923 | runtime.gcMarkDone 924 | 0 of 0.41s(4.41%) 925 | 926 | 927 | 928 | 929 | 930 | N22->N25 931 | 932 | 933 | 934 | 935 | 936 | 937 | 0.40s 938 | 939 | 940 | 941 | 942 | 943 | N24 944 | 945 | 946 | runtime.gcDrain 947 | 0 of 0.10s(1.08%) 948 | 949 | 950 | 951 | 952 | 953 | N23->N24 954 | 955 | 956 | 957 | 958 | 959 | 960 | 0.10s 961 | 962 | 963 | 964 | 965 | 966 | N24->N16 967 | 968 | 969 | 970 | 971 | 972 | 973 | 0.06s 974 | 975 | 976 | 977 | 978 | 979 | N25->N10 980 | 981 | 982 | 983 | 984 | 985 | 986 | 0.37s 987 | 988 | 989 | 990 | 991 | 992 | N26->N10 993 | 994 | 995 | 996 | 997 | 998 | 999 | 0.76s 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | N38 1006 | 1007 | 1008 | runtime.notewakeup 1009 | 0 of 1.87s(20.11%) 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | N27->N38 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 0.11s 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | N28 1029 | 1030 | 1031 | runtime.goexit 1032 | 0 of 7.39s(79.46%) 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | N28->N22 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 2.33s 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | N52 1052 | 1053 | 1054 | testing.(*B).run1.func1 1055 | 0 of 5.05s(54.30%) 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | N28->N52 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 5.05s 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | N29 1075 | 1076 | 1077 | runtime.gopreempt_m 1078 | 0 of 1.05s(11.29%) 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | N30 1085 | 1086 | 1087 | runtime.goschedImpl 1088 | 0 of 1.05s(11.29%) 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | N29->N30 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1.05s 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | N43 1108 | 1109 | 1110 | runtime.schedule 1111 | 0 of 1.25s(13.44%) 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | N30->N43 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1.05s 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | N31 1131 | 1132 | 1133 | runtime.mach_semrelease 1134 | 0 of 1.87s(20.11%) 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | N31->N1 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1.87s 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | N32->N17 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 0.84s 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | N42 1167 | 1168 | 1169 | runtime.scang 1170 | 0 of 1.83s(19.68%) 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | N33->N42 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1.83s 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | N34 1190 | 1191 | 1192 | runtime.mcall 1193 | 0 of 0.20s(2.15%) 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | N40 1200 | 1201 | 1202 | runtime.park_m 1203 | 0 of 0.20s(2.15%) 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | N34->N40 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 0.20s 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | N35 1223 | 1224 | 1225 | runtime.morestack 1226 | 0 of 1.36s(14.62%) 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | N36 1233 | 1234 | 1235 | runtime.newstack 1236 | 0 of 1.36s(14.62%) 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | N35->N36 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1.36s 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | N36->N11 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 0.31s 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | N36->N29 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1.05s 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | N37 1282 | 1283 | 1284 | runtime.notesleep 1285 | 0 of 0.16s(1.72%) 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | N44 1292 | 1293 | 1294 | runtime.semasleep 1295 | 0 of 0.16s(1.72%) 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | N37->N44 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 0.16s 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | N47 1315 | 1316 | 1317 | runtime.semawakeup 1318 | 0 of 1.87s(20.11%) 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | N38->N47 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1.87s 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | N39 1338 | 1339 | 1340 | runtime.osyield 1341 | 0 of 1.79s(19.25%) 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | N39->N2 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1.79s 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | N40->N43 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 0.20s 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | N41 1374 | 1375 | 1376 | runtime.runSafePointFn 1377 | 0 of 0.95s(10.22%) 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | N41->N38 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 0.95s 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | N42->N39 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1.78s 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | N43->N21 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 0.18s 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | N43->N27 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 0.10s 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | N43->N41 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 0.95s 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | N44->N10 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 0.16s 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | N46 1462 | 1463 | 1464 | runtime.semasleep1 1465 | 0 of 0.54s(5.81%) 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | N45->N46 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 0.54s 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | N46->N9 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 0.37s 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | N46->N15 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 0.17s 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | N47->N31 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1.87s 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | N51 1524 | 1525 | 1526 | runtime.wakep 1527 | 0 of 0.78s(8.39%) 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | N48->N51 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 0.76s 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | N49 1547 | 1548 | 1549 | runtime.startm 1550 | 0 of 0.78s(8.39%) 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | N49->N38 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 0.78s 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | N50->N37 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 0.16s 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | N51->N49 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 0.78s 1590 | 1591 | 1592 | 1593 | 1594 | 1595 | N53 1596 | 1597 | 1598 | testing.(*B).runN 1599 | 0 of 5.05s(54.30%) 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | N52->N53 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 5.05s 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | N53->N18 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 5.04s 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | -------------------------------------------------------------------------------- /cpu7.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 292 | graphblog.test 293 | 294 | 295 | cluster_L 296 | 297 | 298 | 299 | 300 | L 301 | 302 | File: graphblog.test 303 | Type: cpu 304 | Time: Jul 23, 2017 at 1:42pm (BST) 305 | Duration: 1.826015987s 306 | 1.51s of 1.51s total (  100%) 307 | 308 | 309 | 310 | N1 311 | 312 | 313 | github.com/philpearl/graphblog.nodes.longestShortestPath 314 | 1.02s(67.55%) 315 | 316 | 317 | 318 | 319 | 320 | N2 321 | 322 | 323 | runtime.usleep 324 | 0.17s(11.26%) 325 | 326 | 327 | 328 | 329 | 330 | N3 331 | 332 | 333 | github.com/philpearl/graphblog.nodes.diameter 334 | 0.16s(10.60%) 335 | of 1.18s(78.15%) 336 | 337 | 338 | 339 | 340 | 341 | N3->N1 342 | 343 | 344 | 345 | 346 | 347 | 348 | 1.02s 349 | 350 | 351 | 352 | 353 | 354 | N4 355 | 356 | 357 | runtime.duffcopy 358 | 0.15s(9.93%) 359 | 360 | 361 | 362 | 363 | 364 | N5 365 | 366 | 367 | syscall.Syscall 368 | 0.01s(0.66%) 369 | 370 | 371 | 372 | 373 | 374 | N6 375 | 376 | 377 | bufio.(*Scanner).Scan 378 | 0 of 0.01s(0.66%) 379 | 380 | 381 | 382 | 383 | 384 | N9 385 | 386 | 387 | os.(*File).Read 388 | 0 of 0.01s(0.66%) 389 | 390 | 391 | 392 | 393 | 394 | N6->N9 395 | 396 | 397 | 398 | 399 | 400 | 401 | 0.01s 402 | 403 | 404 | 405 | 406 | 407 | N7 408 | 409 | 410 | github.com/philpearl/graphblog.BenchmarkDiameter 411 | 0 of 0.01s(0.66%) 412 | 413 | 414 | 415 | 416 | 417 | N7->N6 418 | 419 | 420 | 421 | 422 | 423 | 424 | 0.01s 425 | 426 | 427 | 428 | 429 | 430 | N8 431 | 432 | 433 | github.com/philpearl/graphblog.BenchmarkDiameter.func1 434 | 0 of 1.18s(78.15%) 435 | 436 | 437 | 438 | 439 | 440 | N8->N3 441 | 442 | 443 | 444 | 445 | 446 | 447 | 1.18s 448 | 449 | 450 | 451 | 452 | 453 | N10 454 | 455 | 456 | os.(*File).read 457 | 0 of 0.01s(0.66%) 458 | 459 | 460 | 461 | 462 | 463 | N9->N10 464 | 465 | 466 | 467 | 468 | 469 | 470 | 0.01s 471 | 472 | 473 | 474 | 475 | 476 | N17 477 | 478 | 479 | syscall.Read 480 | 0 of 0.01s(0.66%) 481 | 482 | 483 | 484 | 485 | 486 | N10->N17 487 | 488 | 489 | 490 | 491 | 492 | 493 | 0.01s 494 | 495 | 496 | 497 | 498 | 499 | N11 500 | 501 | 502 | runtime.goexit 503 | 0 of 1.19s(78.81%) 504 | 505 | 506 | 507 | 508 | 509 | N19 510 | 511 | 512 | testing.(*B).run1.func1 513 | 0 of 1.19s(78.81%) 514 | 515 | 516 | 517 | 518 | 519 | N11->N19 520 | 521 | 522 | 523 | 524 | 525 | 526 | 1.19s 527 | 528 | 529 | 530 | 531 | 532 | N12 533 | 534 | 535 | runtime.morestack 536 | 0 of 0.15s(9.93%) 537 | 538 | 539 | 540 | 541 | 542 | N15 543 | 544 | 545 | runtime.newstack 546 | 0 of 0.15s(9.93%) 547 | 548 | 549 | 550 | 551 | 552 | N12->N15 553 | 554 | 555 | 556 | 557 | 558 | 559 | 0.15s 560 | 561 | 562 | 563 | 564 | 565 | N13 566 | 567 | 568 | runtime.mstart 569 | 0 of 0.17s(11.26%) 570 | 571 | 572 | 573 | 574 | 575 | N14 576 | 577 | 578 | runtime.mstart1 579 | 0 of 0.17s(11.26%) 580 | 581 | 582 | 583 | 584 | 585 | N13->N14 586 | 587 | 588 | 589 | 590 | 591 | 592 | 0.17s 593 | 594 | 595 | 596 | 597 | 598 | N16 599 | 600 | 601 | runtime.sysmon 602 | 0 of 0.17s(11.26%) 603 | 604 | 605 | 606 | 607 | 608 | N14->N16 609 | 610 | 611 | 612 | 613 | 614 | 615 | 0.17s 616 | 617 | 618 | 619 | 620 | 621 | N15->N4 622 | 623 | 624 | 625 | 626 | 627 | 628 | 0.15s 629 | 630 | 631 | 632 | 633 | 634 | N16->N2 635 | 636 | 637 | 638 | 639 | 640 | 641 | 0.17s 642 | 643 | 644 | 645 | 646 | 647 | N18 648 | 649 | 650 | syscall.read 651 | 0 of 0.01s(0.66%) 652 | 653 | 654 | 655 | 656 | 657 | N17->N18 658 | 659 | 660 | 661 | 662 | 663 | 664 | 0.01s 665 | 666 | 667 | 668 | 669 | 670 | N18->N5 671 | 672 | 673 | 674 | 675 | 676 | 677 | 0.01s 678 | 679 | 680 | 681 | 682 | 683 | N20 684 | 685 | 686 | testing.(*B).runN 687 | 0 of 1.19s(78.81%) 688 | 689 | 690 | 691 | 692 | 693 | N19->N20 694 | 695 | 696 | 697 | 698 | 699 | 700 | 1.19s 701 | 702 | 703 | 704 | 705 | 706 | N20->N7 707 | 708 | 709 | 710 | 711 | 712 | 713 | 0.01s 714 | 715 | 716 | 717 | 718 | 719 | N20->N8 720 | 721 | 722 | 723 | 724 | 725 | 726 | 1.18s 727 | 728 | 729 | 730 | 731 | 732 | -------------------------------------------------------------------------------- /cpu8.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 292 | graphblog.test 293 | 294 | 295 | cluster_L 296 | 297 | 298 | 299 | 300 | L 301 | 302 | File: graphblog.test 303 | Type: cpu 304 | Time: Jul 23, 2017 at 1:47pm (BST) 305 | Duration: 1.463740942s 306 | 1.25s of 1.25s total (  100%) 307 | 308 | 309 | 310 | N1 311 | 312 | 313 | github.com/philpearl/graphblog.nodes.longestShortestPath 314 | 0.96s(76.80%) 315 | 316 | 317 | 318 | 319 | 320 | N2 321 | 322 | 323 | runtime.usleep 324 | 0.18s(14.40%) 325 | 326 | 327 | 328 | 329 | 330 | N3 331 | 332 | 333 | github.com/philpearl/graphblog.nodes.diameter 334 | 0.04s(3.20%) 335 | of 1s(80.00%) 336 | 337 | 338 | 339 | 340 | 341 | N3->N1 342 | 343 | 344 | 345 | 346 | 347 | 348 | 0.96s 349 | 350 | 351 | 352 | 353 | 354 | N4 355 | 356 | 357 | runtime.duffcopy 358 | 0.04s(3.20%) 359 | 360 | 361 | 362 | 363 | 364 | N5 365 | 366 | 367 | reflect.DeepEqual 368 | 0.01s(0.8%) 369 | 370 | 371 | 372 | 373 | 374 | N6 375 | 376 | 377 | runtime.memmove 378 | 0.01s(0.8%) 379 | 380 | 381 | 382 | 383 | 384 | N7 385 | 386 | 387 | runtime.morestack 388 | 0.01s(0.8%) 389 | of 0.05s(4.00%) 390 | 391 | 392 | 393 | 394 | 395 | N17 396 | 397 | 398 | runtime.newstack 399 | 0 of 0.04s(3.20%) 400 | 401 | 402 | 403 | 404 | 405 | N7->N17 406 | 407 | 408 | 409 | 410 | 411 | 412 | 0.04s 413 | 414 | 415 | 416 | 417 | 418 | N8 419 | 420 | 421 | github.com/philpearl/graphblog.BenchmarkDiameter 422 | 0 of 0.01s(0.8%) 423 | 424 | 425 | 426 | 427 | 428 | N13 429 | 430 | 431 | runtime.convT2E 432 | 0 of 0.01s(0.8%) 433 | 434 | 435 | 436 | 437 | 438 | N8->N13 439 | 440 | 441 | 442 | 443 | 444 | 445 | 0.01s 446 | 447 | 448 | 449 | 450 | 451 | N9 452 | 453 | 454 | github.com/philpearl/graphblog.BenchmarkDiameter.func1 455 | 0 of 1.01s(80.80%) 456 | 457 | 458 | 459 | 460 | 461 | N9->N3 462 | 463 | 464 | 465 | 466 | 467 | 468 | 1s 469 | 470 | 471 | 472 | 473 | 474 | N10 475 | 476 | 477 | github.com/stretchr/testify/assert.Equal 478 | 0 of 0.01s(0.8%) 479 | 480 | 481 | 482 | 483 | 484 | N9->N10 485 | 486 | 487 | 488 | 489 | 490 | 491 | 0.01s 492 | 493 | 494 | 495 | 496 | 497 | N11 498 | 499 | 500 | github.com/stretchr/testify/assert.ObjectsAreEqual 501 | 0 of 0.01s(0.8%) 502 | 503 | 504 | 505 | 506 | 507 | N10->N11 508 | 509 | 510 | 511 | 512 | 513 | 514 | 0.01s 515 | 516 | 517 | 518 | 519 | 520 | N11->N5 521 | 522 | 523 | 524 | 525 | 526 | 527 | 0.01s 528 | 529 | 530 | 531 | 532 | 533 | N12 534 | 535 | 536 | runtime._System 537 | 0 of 0.01s(0.8%) 538 | 539 | 540 | 541 | 542 | 543 | N12->N7 544 | 545 | 546 | 547 | 548 | 549 | 550 | 0.01s 551 | 552 | 553 | 554 | 555 | 556 | N19 557 | 558 | 559 | runtime.typedmemmove 560 | 0 of 0.01s(0.8%) 561 | 562 | 563 | 564 | 565 | 566 | N13->N19 567 | 568 | 569 | 570 | 571 | 572 | 573 | 0.01s 574 | 575 | 576 | 577 | 578 | 579 | N14 580 | 581 | 582 | runtime.goexit 583 | 0 of 1.02s(81.60%) 584 | 585 | 586 | 587 | 588 | 589 | N20 590 | 591 | 592 | testing.(*B).run1.func1 593 | 0 of 1.02s(81.60%) 594 | 595 | 596 | 597 | 598 | 599 | N14->N20 600 | 601 | 602 | 603 | 604 | 605 | 606 | 1.02s 607 | 608 | 609 | 610 | 611 | 612 | N15 613 | 614 | 615 | runtime.mstart 616 | 0 of 0.18s(14.40%) 617 | 618 | 619 | 620 | 621 | 622 | N16 623 | 624 | 625 | runtime.mstart1 626 | 0 of 0.18s(14.40%) 627 | 628 | 629 | 630 | 631 | 632 | N15->N16 633 | 634 | 635 | 636 | 637 | 638 | 639 | 0.18s 640 | 641 | 642 | 643 | 644 | 645 | N18 646 | 647 | 648 | runtime.sysmon 649 | 0 of 0.18s(14.40%) 650 | 651 | 652 | 653 | 654 | 655 | N16->N18 656 | 657 | 658 | 659 | 660 | 661 | 662 | 0.18s 663 | 664 | 665 | 666 | 667 | 668 | N17->N4 669 | 670 | 671 | 672 | 673 | 674 | 675 | 0.04s 676 | 677 | 678 | 679 | 680 | 681 | N18->N2 682 | 683 | 684 | 685 | 686 | 687 | 688 | 0.18s 689 | 690 | 691 | 692 | 693 | 694 | N19->N6 695 | 696 | 697 | 698 | 699 | 700 | 701 | 0.01s 702 | 703 | 704 | 705 | 706 | 707 | N21 708 | 709 | 710 | testing.(*B).runN 711 | 0 of 1.02s(81.60%) 712 | 713 | 714 | 715 | 716 | 717 | N20->N21 718 | 719 | 720 | 721 | 722 | 723 | 724 | 1.02s 725 | 726 | 727 | 728 | 729 | 730 | N21->N8 731 | 732 | 733 | 734 | 735 | 736 | 737 | 0.01s 738 | 739 | 740 | 741 | 742 | 743 | N21->N9 744 | 745 | 746 | 747 | 748 | 749 | 750 | 1.01s 751 | 752 | 753 | 754 | 755 | 756 | -------------------------------------------------------------------------------- /cpu9.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 292 | graphblog.test 293 | 294 | 295 | cluster_L 296 | 297 | 298 | 299 | 300 | L 301 | 302 | File: graphblog.test 303 | Type: cpu 304 | Time: Jul 23, 2017 at 1:50pm (BST) 305 | Duration: 2.763904366s 306 | 14030ms of 14090ms total (99.57%) 307 | Dropped 24 nodes (cum <= 70.45ms) 308 | 309 | 310 | 311 | N1 312 | 313 | 314 | github.com/philpearl/graphblog.nodes.longestShortestPath 315 | 12280ms(87.15%) 316 | of 12320ms(87.44%) 317 | 318 | 319 | 320 | 321 | 322 | N2 323 | 324 | 325 | runtime.duffcopy 326 | 1190ms(8.45%) 327 | 328 | 329 | 330 | 331 | 332 | N3 333 | 334 | 335 | github.com/philpearl/graphblog.nodes.diameter.func1 336 | 370ms(2.63%) 337 | of 12880ms(91.41%) 338 | 339 | 340 | 341 | 342 | 343 | N3->N1 344 | 345 | 346 | 347 | 348 | 349 | 350 | 12320ms 351 | 352 | 353 | 354 | 355 | 356 | N5 357 | 358 | 359 | runtime.deferreturn 360 | 0 of 190ms(1.35%) 361 | 362 | 363 | 364 | 365 | 366 | N3->N5 367 | 368 | 369 | 370 | 371 | 372 | 373 | 190ms 374 | 375 | 376 | 377 | 378 | 379 | N4 380 | 381 | 382 | runtime.freedefer 383 | 190ms(1.35%) 384 | 385 | 386 | 387 | 388 | 389 | N5->N4 390 | 391 | 392 | 393 | 394 | 395 | 396 | 190ms 397 | 398 | 399 | 400 | 401 | 402 | N6 403 | 404 | 405 | runtime.goexit 406 | 0 of 12890ms(91.48%) 407 | 408 | 409 | 410 | 411 | 412 | N6->N3 413 | 414 | 415 | 416 | 417 | 418 | 419 | 12880ms 420 | 421 | 422 | 423 | 424 | 425 | N7 426 | 427 | 428 | runtime.morestack 429 | 0 of 1190ms(8.45%) 430 | 431 | 432 | 433 | 434 | 435 | N8 436 | 437 | 438 | runtime.newstack 439 | 0 of 1190ms(8.45%) 440 | 441 | 442 | 443 | 444 | 445 | N7->N8 446 | 447 | 448 | 449 | 450 | 451 | 452 | 1190ms 453 | 454 | 455 | 456 | 457 | 458 | N8->N2 459 | 460 | 461 | 462 | 463 | 464 | 465 | 1190ms 466 | 467 | 468 | 469 | 470 | 471 | -------------------------------------------------------------------------------- /list.go: -------------------------------------------------------------------------------- 1 | package graphblog 2 | 3 | type listElt struct { 4 | next *listElt 5 | node *node 6 | } 7 | 8 | type list struct { 9 | head *listElt 10 | tail *listElt 11 | 12 | free *listElt 13 | } 14 | 15 | func (l *list) getHead() *node { 16 | elt := l.head 17 | if elt == nil { 18 | return nil 19 | } 20 | 21 | // Remove elt from the list 22 | l.head = elt.next 23 | if l.head == nil { 24 | l.tail = nil 25 | } 26 | // Add elt to the free list 27 | elt.next = l.free 28 | l.free = elt 29 | 30 | n := elt.node 31 | elt.node = nil 32 | return n 33 | } 34 | 35 | func (l *list) pushBack(n *node) { 36 | // Get a free listElt to use to point to this node 37 | elt := l.free 38 | if elt == nil { 39 | elt = &listElt{} 40 | } else { 41 | l.free = elt.next 42 | elt.next = nil 43 | } 44 | 45 | // Add the element to the tail of the list 46 | elt.node = n 47 | if l.tail == nil { 48 | l.tail = elt 49 | l.head = elt 50 | } else { 51 | l.tail.next = elt 52 | l.tail = elt 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /node.go: -------------------------------------------------------------------------------- 1 | package graphblog 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | ) 7 | 8 | type nodeId int32 9 | type nodeName string 10 | 11 | type symbolTable map[nodeName]nodeId 12 | 13 | func (s symbolTable) getId(name nodeName) nodeId { 14 | id, ok := s[name] 15 | if !ok { 16 | id = nodeId(len(s)) 17 | s[name] = id 18 | } 19 | return id 20 | } 21 | 22 | type graph struct { 23 | symbolTable 24 | nodes 25 | } 26 | 27 | func New(numNodes int) *graph { 28 | g := &graph{ 29 | symbolTable: make(symbolTable, numNodes), 30 | nodes: make(nodes, numNodes), 31 | } 32 | g.nodes.init() 33 | return g 34 | } 35 | 36 | func (g *graph) addEdge(a, b nodeName) { 37 | aid := g.symbolTable.getId(a) 38 | bid := g.symbolTable.getId(b) 39 | 40 | g.nodes.addEdge(aid, bid) 41 | } 42 | 43 | type node struct { 44 | id nodeId 45 | 46 | // adjacent edges 47 | adj []nodeId 48 | } 49 | 50 | func (n *node) add(adjNode *node) { 51 | for _, id := range n.adj { 52 | if id == adjNode.id { 53 | return 54 | } 55 | } 56 | n.adj = append(n.adj, adjNode.id) 57 | } 58 | 59 | type nodes []node 60 | 61 | func (nl nodes) init() { 62 | for i := range nl { 63 | nl[i].id = nodeId(i) 64 | } 65 | } 66 | 67 | func (nl nodes) get(id nodeId) *node { 68 | return &nl[id] 69 | } 70 | 71 | func (nl nodes) addEdge(a, b nodeId) { 72 | an := nl.get(a) 73 | bn := nl.get(b) 74 | 75 | an.add(bn) 76 | bn.add(an) 77 | } 78 | 79 | // diameter is the maximum length of a shortest path in the network 80 | func (nl nodes) diameter() int { 81 | 82 | cpus := runtime.NumCPU() 83 | numNodes := len(nl) 84 | nodesPerCpu := numNodes / cpus 85 | 86 | results := make([]int, cpus) 87 | wg := &sync.WaitGroup{} 88 | wg.Add(cpus) 89 | start := 0 90 | for cpu := 0; cpu < cpus; cpu++ { 91 | end := start + nodesPerCpu 92 | if cpu == cpus-1 { 93 | end = numNodes 94 | } 95 | 96 | go func(cpu int, start, end nodeId) { 97 | defer wg.Done() 98 | var diameter int 99 | q := &list{} 100 | depths := make([]bfsNode, numNodes) 101 | for id := start; id < end; id++ { 102 | // Need to reset the bfsData between runs 103 | for i := range depths { 104 | depths[i] = -1 105 | } 106 | 107 | df := nl.longestShortestPath(nodeId(id), q, depths) 108 | if df > diameter { 109 | diameter = df 110 | } 111 | } 112 | results[cpu] = diameter 113 | }(cpu, nodeId(start), nodeId(end)) 114 | start += nodesPerCpu 115 | } 116 | 117 | wg.Wait() 118 | 119 | diameter := 0 120 | for _, result := range results { 121 | if result > diameter { 122 | diameter = result 123 | } 124 | } 125 | return diameter 126 | } 127 | 128 | // bfs tracking data 129 | type bfsNode int16 130 | 131 | func (nodes nodes) longestShortestPath(start nodeId, q *list, depths []bfsNode) int { 132 | 133 | n := nodes.get(start) 134 | depths[n.id] = 0 135 | q.pushBack(n) 136 | 137 | for { 138 | newN := q.getHead() 139 | if newN == nil { 140 | break 141 | } 142 | n = newN 143 | 144 | for _, id := range n.adj { 145 | if depths[id] == -1 { 146 | depths[id] = depths[n.id] + 1 147 | q.pushBack(nodes.get(id)) 148 | } 149 | } 150 | } 151 | 152 | return int(depths[n.id]) 153 | } 154 | -------------------------------------------------------------------------------- /node_test.go: -------------------------------------------------------------------------------- 1 | package graphblog 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "bufio" 8 | 9 | "strings" 10 | 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | type edge struct{ a, b nodeName } 15 | type edgeList []edge 16 | 17 | func (e edgeList) build(g *graph) { 18 | for _, edge := range e { 19 | g.addEdge(edge.a, edge.b) 20 | } 21 | } 22 | 23 | func TestDiameter(t *testing.T) { 24 | 25 | tests := []struct { 26 | name string 27 | edgeList edgeList 28 | expDiameter int 29 | }{ 30 | { 31 | name: "empty", 32 | }, 33 | { 34 | name: "1 edge", 35 | edgeList: edgeList{{"a", "b"}}, 36 | expDiameter: 1, 37 | }, 38 | { 39 | name: "3 in line", 40 | edgeList: edgeList{{"a", "b"}, {"b", "c"}}, 41 | expDiameter: 2, 42 | }, 43 | { 44 | name: "4 in line", 45 | edgeList: edgeList{{"a", "b"}, {"b", "c"}, {"c", "d"}}, 46 | expDiameter: 3, 47 | }, 48 | { 49 | name: "Triangle", 50 | edgeList: edgeList{{"a", "b"}, {"b", "c"}, {"a", "c"}}, 51 | expDiameter: 1, 52 | }, 53 | { 54 | name: "Square", 55 | edgeList: edgeList{{"a", "b"}, {"b", "c"}, {"c", "d"}, {"a", "d"}}, 56 | expDiameter: 2, 57 | }, 58 | { 59 | name: "2 loops", 60 | edgeList: edgeList{{"a", "b"}, {"b", "c"}, {"c", "a"}, {"c", "d"}, {"d", "e"}, {"e", "c"}}, 61 | expDiameter: 2, 62 | }, 63 | } 64 | 65 | for _, test := range tests { 66 | t.Run(test.name, func(t *testing.T) { 67 | g := New(100) 68 | test.edgeList.build(g) 69 | dia := g.diameter() 70 | if dia != test.expDiameter { 71 | t.Errorf("Diameter not as expected. Have %d, expected %d", dia, test.expDiameter) 72 | } 73 | }) 74 | } 75 | } 76 | 77 | func BenchmarkDiameter(b *testing.B) { 78 | g := New(10000) 79 | // Load the test data 80 | f, err := os.Open("testdata/edges.txt") 81 | assert.NoError(b, err) 82 | s := bufio.NewScanner(f) 83 | for s.Scan() { 84 | line := s.Text() 85 | edge := strings.Fields(line) 86 | assert.Len(b, edge, 2) 87 | g.addEdge(nodeName(edge[0]), nodeName(edge[1])) 88 | } 89 | assert.NoError(b, err) 90 | 91 | b.Run("diameter", func(b *testing.B) { 92 | b.ReportAllocs() 93 | for i := 0; i < b.N; i++ { 94 | d := g.diameter() 95 | assert.Equal(b, 82, d) 96 | } 97 | }) 98 | } 99 | --------------------------------------------------------------------------------