Giter Club home page Giter Club logo

studio's Introduction

Studio

Studio is an interactive software diagnostics environment.

Studio imports dense and "messy" diagnostic data in an application's own native formats, then it applies all the tools that are needed to extract useful information, and finally it presents the results in an interactive graphical user interface.

Getting Started

Studio runs on Linux/x86-64 and publishes its GUI via VNC. You can run Studio on a Linux server, or in a Docker container on Linux/macOS/Windows, or in a virtual machine. You can then access the GUI from anywhere using a VNC client. (You can also run Studio directly via X11 if you prefer.)

Connecting with VNC

Once you have Studio running in VNC mode you can connect to the GUI like this:

vncviewer hostname:1

where hostname is the machine running Studio and :1 is the VNC desktop number (corresponding to TCP port 5901.)

We recommend using a VNC client such as TigerVNC that supports automatically resizing the desktop to match your client window.

Running Studio in Docker

You can run Studio via the Dockerhub repository studioproject/master. Studio CI automatically publishes the latest working build of the master branch (and every other branch) to Dockerhub for easy installation.

Here is a one-liner to start Studio in a Docker container (on macOS/Windows this automatically runs inside a Linux VM):

docker run --rm -ti -p 0.0.0.0:5901:5901 studioproject/master vnc

You can then connect to the GUI on this machine using VNC display :1 because TCP port 5901 is forwarded into the container. (If you want to use a different display number then change the first :5901 to a higher number.)

Docker tips:

  • docker pull studioproject/master will upgrade to the latest Studio image from CI.
  • docker run ... studioproject/FOO will run Studio from the branch named FOO (for any value of FOO.)
  • docker build . will build the Docker container for Studio from source.
  • docker run -v /:/host ... bind-mounts local files to be accessible to Studio under /host/* from inside the container.

Running Studio directly on Linux

You can also run Studio on Linux directly from source:

# Install the Nix package manager to automatically manage dependencies.
curl https://nixos.org/nix/install | sh

# Setup Cachix to speed up Nix by downloading cached binaries when available.
# (This step is optional but recommended.)
nix-env -iA cachix -f https://cachix.org/api/v1/install
cachix use studio 

# Download and run Studio
git clone https://github.com/studio/studio
studio/bin/studio vnc  # or x11

Hacking Studio

... To be written!


Studio screenshot
RaptorJIT IR visualization example

studio's People

Contributors

alexandergall avatar asrp avatar benagricola avatar dtzwill avatar eugeneia avatar lukego avatar takikawa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

studio's Issues

studio decode fails with "MessageNotUnderstood: Studio class>>decodeFrom:to:"

When trying to run the command

$ bin/studio decode /var/run/snabb/29515/audit.log ./out

I get this error

Studio decoding from File @ /var/run/snabb/29515/audit.log to File @ out
'Errors in script loaded from /nix/store/l6ksh8sykibbv0ih97d2gbpv74liyvq0-studio-decode-script.st'
MessageNotUnderstood: Studio class>>decodeFrom:to:
Studio class(Object)>>doesNotUnderstand: #decodeFrom:to:
UndefinedObject>>DoIt
OpalCompiler>>evaluate
DoItChunk>>importFor:logSource:
[ :declaration | 
requestor ifNotNil: [ requestor contents: declaration contents ].
value := declaration importFor: requestor logSource: logSource ] in CodeImporter>>evaluate in Block: [ :declaration | ...
OrderedCollection>>do:
CodeImporter>>evaluate
[ codeImporter evaluate ] in STCommandLineHandler>>installSourceFile: in Block: [ codeImporter evaluate ]
BlockClosure>>on:do:
STCommandLineHandler>>handleErrorsDuring:reference:
STCommandLineHandler>>installSourceFile:
[ :reference | self installSourceFile: reference ] in [ sourceFiles do: [ :reference | self installSourceFile: reference ] ] in STCommandLineHandler>>installSourceFiles in Block: [ :reference | self installSourceFile: reference ]...etc...
OrderedCollection>>do:
[ sourceFiles do: [ :reference | self installSourceFile: reference ] ] in STCommandLineHandler>>installSourceFiles in Block: [ sourceFiles do: [ :reference | self installSourc...etc...
BlockClosure>>ensure:
STCommandLineHandler>>installSourceFiles
STCommandLineHandler>>activate
STCommandLineHandler class(CommandLineHandler class)>>activateWith:
[ aCommandLinehandler activateWith: commandLine ] in PharoCommandLineHandler(BasicCommandLineHandler)>>activateSubCommand: in Block: [ aCommandLinehandler activateWith: commandLine ]
BlockClosure>>on:do:
PharoCommandLineHandler(BasicCommandLineHandler)>>activateSubCommand:
PharoCommandLineHandler(BasicCommandLineHandler)>>handleSubcommand
PharoCommandLineHandler(BasicCommandLineHandler)>>handleArgument:
[ self
	handleArgument:
		(self arguments
			ifEmpty: [ '' ]
			ifNotEmpty: [ :arguments | arguments first ]) ] in [ [ self
	handleArgument:
		(self arguments
			ifEmpty: [ '' ]
			ifNotEmpty: [ :arguments | arguments first ]) ]
	on: Exit
	do: [ :exit | 
		"If the command line is protected by password, we just exit the image because in non-headless mode the handleExit will let the image open. If the password protection is enabled, it is to avoid to let the access to the image."
		self class commandLinePasswordManager hasPasswordSet
			ifTrue: [ Smalltalk snapshot: false andQuit: true ].
		^ self handleExit: exit ] ] in PharoCommandLineHandler(BasicCommandLineHandler)>>activate in Block: [ self...
BlockClosure>>on:do:
[ [ self
	handleArgument:
		(self arguments
			ifEmpty: [ '' ]
			ifNotEmpty: [ :arguments | arguments first ]) ]
	on: Exit
	do: [ :exit | 
		"If the command line is protected by password, we just exit the image because in non-headless mode the handleExit will let the image open. If the password protection is enabled, it is to avoid to let the access to the image."
		self class commandLinePasswordManager hasPasswordSet
			ifTrue: [ Smalltalk snapshot: false andQuit: true ].
		^ self handleExit: exit ] ] in PharoCommandLineHandler(BasicCommandLineHandler)>>activate in Block: [ [ self...
[ self value.
Processor terminateActive ] in BlockClosure>>newProcess in Block: [ self value....

Add inspector view: IR listing

Add an IR Listing inspector view for RaptorJIT traces. This will show the list of IR instructions in a similar format to the LuaJIT -jdump textual listing.

UI hangs when clicking on Profiler datasets

After launching studio for the first time and loading snabb.processDirectory A window with Profiler datasets appear. When clicking a Profile in the window, it takes along time for UI to refresh. During this time I am not able to scroll this window to see other items nor UI responds to any other clicks.

The shm directory I am using has a size of 106MB, which might be the reason why it takes so long. But an indication about studio being busy and a progress bar would be nice.

Hide Smalltalk tools

The default Studio behavior should be to suppress the tools/gadgets/widgets for the underlying Smalltalk environment. For example the Raw and Meta tabs in the inspector should be disabled by default because they are showing "under the hood" details that are only of interest when hacking on the UI.

The underlying framework (Glamorous Toolkit) does support this selective disabling. Just have to do it.

Create IR<->MCode mapping

Create a well-defined mapping between IR code and machine code. Clicking on an IR instruction should be able to show the exact machine code instructions generated.

This may require an extension in RaptorJIT to record the mapping. One simple solution would be for the assembler phase to count the number of bytes assembled for each IR instruction.

Update to GToolkit beta

Studio should be updated to GToolkit "beta" version.

  • Update to latest Smalltalk VM.
  • Update to latest version of GToolkit C/C++ dependencies.
  • Update Studio code with any API porting required to migrate from alpha- to beta- version.

pharo-x11 script overwrites ./pharo.image and ./pharo.changes

The studio-x11 script copies Pharo image files from the nix store into the current directory. This is naughty because it can overwrite other files e.g. from other Studio processes that are still running or even precious files belonging to the user. These files must go somewhere else.

  • Fix studio-x11 script.
  • Fix other scripts defined in the same file.

Error opening an shm file.

Opening an shm file (taken from a running snabb) caused the following error:

debugProcess: process context: context label: title fullView: bool notification: notificationString
	"Open a notifier in response to an error, halt, or notify. A notifier view
	just shows a short view of the sender stack and provides a menu that
	lets the user open a full debugger."

	| debugSession |

	debugSession := process newDebugSessionNamed: title startedAt: context.
	
	debugSession logStackToFileIfNeeded.
	debugSession isAboutUIProcess ifTrue: [ 
		DefaultExecutionEnvironment beActiveDuring: [self spawnNewProcess]].
		
	self defer:	[ 
			"schedule debugger in deferred UI message to address
			redraw problems after opening a debugger e.g. from
			the testrunner."
		[ Smalltalk tools debugger 
				openOn: debugSession withFullView: bool andNotification: notificationString.
		] on: Error do: [ :ex | 	debugSession signalDebuggerError: ex] 
	].

	process suspend.

Note for future: the file name is 20180413-121301-31352

Studio doesn't run from the repo

tubuntu ~/studio % nix -v -v -v -v -v --version
nix (Nix) 2.0
Features: gc, signed-caches
Configuration file: /etc/nix/nix.conf
Store directory: /nix/store
State directory: /nix/var/nix

Studio does run if I do nix-env -iA studio -f https://github.com/studio/studio/archive/master.tar.gz, as per the documentation, and then run studio-x11.

If on the other hand I follow the instructions in the README for running it from the repo - excluding curl https://nixos.org/nix/install | sh, since (I already had Nix installed - when running bin/studio x11`, I get this:

tubuntu ~/studio % bin/studio x11
nix-build is /home/tom/.nix-profile/bin/nix-build
warning: unknown setting 'signed-binary-caches'
these derivations will be built:
  /nix/store/z88fcpb1sd1d7hbd1jl5g3bbbjf6cygj-studio-x11-0.1.1.drv
these paths will be fetched (114.94 MiB download, 539.36 MiB unpacked):
  /nix/store/00mb4m87gpj2xhigkhxlyssl0yy80qbd-libxml2-2.9.4
  /nix/store/04pawbpmrjqkrqm52glmalapipqfb5lx-libxcb-1.12-dev
[and so on, and so on, for many, many lines...]
  /nix/store/zj3da1dwbfhqvwl8q3cyfb30yzjii2nv-nix-1.12pre5413_b4b1f452-debug
  /nix/store/zl01n2l4dlzcdzgr071s5dhh6w6v5gfw-aws-sdk-cpp-1.0.153
warning: substituter 'https://hydra.snabb.co' does not have a valid signature for path '/nix/store/j0m1756cqa0jfwa22m7vvw9lcdaj7ynm-pharo'
warning: substituter 'https://hydra.snabb.co' does not have a valid signature for path '/nix/store/f23m84qbx2whwmiikhgzxdv26h7xn87j-studio-image'
cannot build derivation '/nix/store/z88fcpb1sd1d7hbd1jl5g3bbbjf6cygj-studio-x11-0.1.1.drv': 1 dependencies couldn't be built
error: build of '/nix/store/4wi3piyx5xyiqvfsng7ljx5m2qcl9fpy-xauth-1.0.10.drv', '/nix/store/i7bg36lx1gj2r2wywfclrwa46gqypw3l-nix-1.12pre5413_b4b1f452.drv', '/nix/store/knfqqkmb9gfpfgngzwd2wldpcl87yjrq-perl-5.22.3.drv', '/nix/store/pnab762zrvljvi5i3lf5g146n8cb01pk-bash-4.4-p12.drv', '/nix/store/xma87wys255q656sg7c9r8mww4dv1qgf-stdenv.drv', '/nix/store/z88fcpb1sd1d7hbd1jl5g3bbbjf6cygj-studio-x11-0.1.1.drv' failed

I tried adding an couple of lines to /etc/nix/nix.conf, copying some stuff from NixOS/nix#1897:

trusted-binary-caches = https://cache.nixos.org https://hydra.snabb.co
binary-cache-public-keys = hydra.snabb.co-1:zPzKSJ1mynGtYEVbUR0QVZf9TLcaygz/OyzHlWo5AMM= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=

That didn't seem to make any difference :( - this is my first time using Nix, though, and I don't really know what I'm doing.

Thanks,

--Tom

Add inspector view: Machine code listing

Add an MCode Listing inspector view for RaptorJIT traces. This will show the list of machine code (x86-64 asm) instructions in a similar format to the LuaJIT -jdump textual listing.

The disassembly listing can be built by the backend e.g. with a callout to objdump.

Add Continuous Integration

Test with Continuous Integration to make sure the master branch always works well.

Bonus points would be to build on a Hydra that can provide a binary cache for Nix i.e. ensure that installations can always download prebuilt copies of RaptorJIT, etc, on demand from the CI instead of everybody building locally.

UI hangs when running Nix builds with a lot of output

There seems to be a problem where a Nix build that prints a lot of output will consistently get stuck. This seems to be a deadlock where the UI is waiting for the process to complete but the process is waiting for the UI to read from its output pipe.

Solution would be to find the correct usage of the Smalltalk subprocess API so that we continuously read from the process while it runs so that the stdout pipe always makes forward progress.

This is tricky because it happens "rarely" for me, since most of my usual builds are accessing cached results, but it will happen immediately for "you" because all the first things you try in Studio will need to build a bunch of stuff. So - high prio to fix it.

Provide binary-cache for Studio packages

Installing Studio should be streamlined. The various software packages should be downloaded as binaries and not built locally unless actually modified. For example the user should not have to wait for our customized Pharo virtual machine to be compiled during installation.

This is tricky because the default Nix installation will only trust binaries from cache.nixos.org whereas we are building Studio packages on hydra.snabb.co. So even if a binary is available from a cache the default Nix behavior will be not to use it for fear that it is untrustworthy.

The best solution is not immediately clear to me and I have reached out to Nix upstream for advice at NixOS/nix#1812.

dwarfish link broken?

The RaptorJIT example section in the manual references a "dwarfish" tool, the link for which goes nowhere.

RJITFlashbackDataMissing on browsing VMProfile

rjitflashbackdatamissing

To reproduce: load the VMProfile data and go to the VMProfile tab, select the engine profile. Either scroll down the "Source code locations" table or enlarge it by dragging the bottom margin, I only get the debugger to pop up in the latter case. Here is the data is question (its just the one process that was used to produce this):

22854.zip

loop seems necessary

This code works:
with import <studio>; raptorjit.run '' for M=1,100 do x = 1 end ''

while this:
with import <studio>; raptorjit.run '' x = 1 ''
drops me into the Pharo debugger (AssertionFailure).

The loop seems somehow necessary, but the error window is confusing.
@eugeneia says there's no trace being recorded otherwise.

Show reference number on 'pval' IR ins

IR dumps should show the instruction number that is referenced by pval as is missing in

trace 2 line from (x)<toplevel>:5 to (x)<toplevel>:6
0001 rbx       int    sload  #4 P
0002 rbp       obj    pval

First heap visualization

Goal: run a Snabb process and explore the LuaJIT heap while it is running.

  • Snapshot the Snabb process (coredump.)
  • Import Snabb executable and coredump into Nix store.
  • Extract LuaJIT heap format (C structs) with dwarf2xml ./snabb.
  • Load XML into Pharo and use to decode the coredump.
  • Present visually with the Pharo inspector.

This could start simple, e.g. in the style of GDB clicking through C structs, and be extended ad infinitum by decoding more information from the core dump: dump JIT trace bytecode/IR/mcode, locate and present interesting Snabb objects like the engine / config objects / apps / latency histogram / timeline log / etc. Pharo would do the presentation and the actual decoding could be done however is most convenient -- directly in Pharo or with a Nix expression that builds the decoded representation using tools.

RaptorJIT: Show profiler MCode/VM/GC columns for trace sets

The middle column of the profiler data should show the MCode/VM/GC time for sets of traces.

This is to support a drill-down workflow where you have selected a profiler dataset that has a lot of (say) GC activity and you are looking for which traces that are responsible.

Studio attempts to load shared libraries from /usr

When I press β€œplay” I get thrown into the Debugger because Studio attempted to load a shared library from /usr instead of /nix. Below are the Debugger stack trace and the console output:

ExternalLibraryFunction(Object)>>error:
ExternalLibraryFunction(Object)>>externalCallFailed
ExternalLibraryFunction(ExternalFunction)>>invokeWithArguments:
AthensCairoSurface class>>primImage:width:height:
FFICalloutAPI>>function:module:
AthensCairoSurface class(Object)>>nbCall:
AthensCairoSurface class>>primImage:width:height:
AthensCairoSurface class>>extent:format:
AthensCairoSurface class>>extent:
TRCanvas>>initialize
TRCanvas class(Behavior)>>new
RTView>>initialize
RTView class(Behavior)>>new
RTMondrian(RTBuilder)>>createView
RTMondrian>>createView
RTMondrian(RTBuilder)>>initialize
RTMondrian>>initialize
RTMondrian class(Behavior)>>new
RJITAuditLog>>visualizeMondrianOverview
RJITProcess>>gtInspectorJITIn:
[ :eachPragma | 
eachPragma methodSelector numArgs = 0
	ifTrue: [ | presentationSource |
		presentationSource := self perform: eachPragma selector.
		presentationSource glmPresentation
			cull: composite
			cull: aGTInspector
			cull: self ].
eachPragma methodSelector numArgs = 1
	ifTrue: [ thisContext
			object: self
			perform: eachPragma methodSelector
			withArguments: {composite}
			inClass: self class ].
eachPragma methodSelector numArgs = 2
	ifTrue: [ thisContext
			object: self
			perform: eachPragma methodSelector
			withArguments:
				{composite.
				aGTInspector}
			inClass: self class ] ] in RJITProcess(ProtoObject)>>gtInspectorPresentationsFromPragmas:In:inContext:
Array(SequenceableCollection)>>do:
RJITProcess(ProtoObject)>>gtInspectorPresentationsFromPragmas:In:inContext:
RJITProcess(ProtoObject)>>gtInspectorPresentationsIn:inContext:
[ :d | each gtInspectorPresentationsIn: d inContext: self ] in [ :x | 
(GLMCompositePresentation new
	with:
		[ :d | each gtInspectorPresentationsIn: d inContext: self ])
	startOn: x ] in [ :a :each | 
a title: [ self printObjectAsAnItem: each ].
a
	dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
a titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
a dynamic
	display: [ :x | 
		(GLMCompositePresentation new
			with:
				[ :d | each gtInspectorPresentationsIn: d inContext: self ])
			startOn: x ] ] in [ :browser | 
browser fixedSizePanes: self class numberOfInspectorPanes.
browser
	show: [ :a :each | 
		a title: [ self printObjectAsAnItem: each ].
		a
			dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
		a
			titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
		a dynamic
			display: [ :x | 
				(GLMCompositePresentation new
					with:
						[ :d | each gtInspectorPresentationsIn: d inContext: self ])
					startOn: x ] ] ] in StudioInspector(GTInspector)>>compose
GLMCompositePresentation(GLMPresentation)>>with:
[ :x | 
(GLMCompositePresentation new
	with:
		[ :d | each gtInspectorPresentationsIn: d inContext: self ])
	startOn: x ] in [ :a :each | 
a title: [ self printObjectAsAnItem: each ].
a
	dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
a titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
a dynamic
	display: [ :x | 
		(GLMCompositePresentation new
			with:
				[ :d | each gtInspectorPresentationsIn: d inContext: self ])
			startOn: x ] ] in [ :browser | 
browser fixedSizePanes: self class numberOfInspectorPanes.
browser
	show: [ :a :each | 
		a title: [ self printObjectAsAnItem: each ].
		a
			dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
		a
			titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
		a dynamic
			display: [ :x | 
				(GLMCompositePresentation new
					with:
						[ :d | each gtInspectorPresentationsIn: d inContext: self ])
					startOn: x ] ] ] in StudioInspector(GTInspector)>>compose
BlockClosure>>glamourValueWithArgs:
BlockClosure(ProtoObject)>>glamourValue:
GLMDynamicPresentation(GLMPresentation)>>displayValue
GLMDynamicPresentation>>currentPresentation
GLMMorphicDynamicRenderer>>render:
GLMMorphicDynamicRenderer class(GLMMorphicWidgetRenderer class)>>render:from:
GLMMorphicRenderer>>renderDynamicPresentation:
GLMDynamicPresentation>>renderGlamorouslyOn:
GLMMorphicRenderer(GLMRenderer)>>render:
GLMMorphicTabbedRenderer(GLMMorphicWidgetRenderer)>>renderObject:
GLMMorphicTabbedRenderer(GLMMorphicWidgetRenderer)>>renderWithTitleOrNil:
GLMMorphicTabbedRenderer>>render:
GLMMorphicTabbedRenderer class(GLMMorphicWidgetRenderer class)>>render:from:
GLMMorphicRenderer>>renderTabbedCompositePresentation:
GLMTabbedArrangement>>renderGlamorouslyOn:
GLMCompositePresentation>>renderGlamorouslyOn:
GLMMorphicRenderer(GLMRenderer)>>render:
GLMMorphicPaneRenderer(GLMMorphicWidgetRenderer)>>renderObject:
GLMMorphicPaneRenderer>>renderContainerFor:
GLMMorphicPaneRenderer>>render:
GLMMorphicPaneRenderer class(GLMMorphicWidgetRenderer class)>>render:from:
GLMMorphicRenderer>>renderPane:
GLMPane>>renderGlamorouslyOn:
GLMMorphicRenderer(GLMRenderer)>>render:
GLMMorphicPagerRenderer(GLMMorphicWidgetRenderer)>>renderObject:
GLMMorphicPagerRenderer>>actOnPaneAdded:
MessageSend>>value:
MessageSend>>cull:
MessageSend>>cull:cull:
[ action cull: anAnnouncement cull: announcer ] in AnnouncementSubscription>>deliver:
BlockClosure>>on:do:
BlockClosure>>on:fork:
AnnouncementSubscription>>deliver:
[ "Ensure delivery to remaining announcements" subscription deliver: anAnnouncement ] in SubscriptionRegistry>>deliver:to:startingAt:
BlockClosure>>ifCurtailed:
SubscriptionRegistry>>deliver:to:startingAt:
SubscriptionRegistry>>deliver:to:
SubscriptionRegistry>>deliver:
GLMPager(Announcer)>>announce:
GLMPager(GLMAnnouncer)>>announce:
GLMPager(GLMLoggedObject)>>announce:
GLMPager(GLMFinder)>>innerPortEvent:
GLMPane>>portEvent:
[ self silentValue: anObject.
self pane
	portEvent:
		(GLMPortEvent
			on: self
			previouslyValued: oldValue
			in: aTransmissionContext) ] in GLMPanePort>>changeValueTo:in:
GLMPane>>notingPresentationChangeDo:
GLMPanePort>>changeValueTo:in:
GLMPanePort>>value:in:
GLMPanePort(GLMPort)>>value:
GLMPortUpdater>>glamourValueWithArgs:
GLMGenericAction(GLMAction)>>actOn:
GLMGenericAction(GLMAction)>>morphicActOn:
GLMPluggableButtonMorph(PluggableButtonMorph)>>performAction:
[ :m | 
(m containsPoint: evt cursorPoint)
	ifTrue: [ m enabled
			ifTrue: [ m performAction: evt ] ] ] in GLMPluggableButtonMorph(PluggableButtonMorph)>>mouseUp:
Array(SequenceableCollection)>>do:
GLMPluggableButtonMorph(PluggableButtonMorph)>>mouseUp:
GLMPluggableButtonMorph(Morph)>>handleMouseUp:
MouseButtonEvent>>sentTo:
GLMPluggableButtonMorph(Morph)>>handleEvent:
GLMPluggableButtonMorph(Morph)>>handleFocusEvent:
[ ActiveHand := self.
ActiveEvent := anEvent.
result := focusHolder
	handleFocusEvent: (anEvent transformedBy: (focusHolder transformedFrom: self)) ] in HandMorph>>sendFocusEvent:to:clear:
BlockClosure>>on:do:
WorldMorph(PasteUpMorph)>>becomeActiveDuring:
HandMorph>>sendFocusEvent:to:clear:
HandMorph>>sendEvent:focus:clear:
HandMorph>>sendMouseEvent:
HandMorph>>handleEvent:
HandMorph>>processEventsFromQueue:
HandMorph>>processEvents
[ :h | 
self activeHand: h.
h processEvents.
self activeHand: nil ] in WorldState>>doOneCycleNowFor:
Array(SequenceableCollection)>>do:
WorldState>>handsDo:
WorldState>>doOneCycleNowFor:
WorldState>>doOneCycleFor:
WorldMorph>>doOneCycle
WorldMorph class>>doOneCycle
[ [ WorldMorph doOneCycle.
Processor yield.
false ] whileFalse: [  ] ] in MorphicUIManager>>spawnNewProcess
[ self value.
Processor terminateActive ] in BlockClosure>>newProcess
% studio-x11
setlocale() failed (check values of LC_CTYPE, LANG and LC_ALL)
pthread_setschedparam failed: Operation not permitted
ioLoadModule(//usr/lib/libcairo.so.2):
  libpixman-1.so.0: cannot open shared object file: No such file or directory
Error: External module not found
ExternalLibraryFunction(Object)>>error:
ExternalLibraryFunction(Object)>>externalCallFailed
ExternalLibraryFunction(ExternalFunction)>>invokeWithArguments:
AthensCairoSurface class>>primImage:width:height:
FFICalloutAPI>>function:module:
AthensCairoSurface class(Object)>>nbCall:
AthensCairoSurface class>>primImage:width:height:
AthensCairoSurface class>>extent:format:
AthensCairoSurface class>>extent:
TRCanvas>>initialize
TRCanvas class(Behavior)>>new
RTView>>initialize
RTView class(Behavior)>>new
RTMondrian(RTBuilder)>>createView
RTMondrian>>createView
RTMondrian(RTBuilder)>>initialize
RTMondrian>>initialize
RTMondrian class(Behavior)>>new
RJITAuditLog>>visualizeMondrianOverview
RJITProcess>>gtInspectorJITIn:
[ :eachPragma | 
eachPragma methodSelector numArgs = 0
	ifTrue: [ | presentationSource |
		presentationSource := self perform: eachPragma selector.
		presentationSource glmPresentation
			cull: composite
			cull: aGTInspector
			cull: self ].
eachPragma methodSelector numArgs = 1
	ifTrue: [ thisContext
			object: self
			perform: eachPragma methodSelector
			withArguments: {composite}
			inClass: self class ].
eachPragma methodSelector numArgs = 2
	ifTrue: [ thisContext
			object: self
			perform: eachPragma methodSelector
			withArguments:
				{composite.
				aGTInspector}
			inClass: self class ] ] in RJITProcess(ProtoObject)>>gtInspectorPresentationsFromPragmas:In:inContext: in Block: [ :eachPragma | ...
Array(SequenceableCollection)>>do:
RJITProcess(ProtoObject)>>gtInspectorPresentationsFromPragmas:In:inContext:
RJITProcess(ProtoObject)>>gtInspectorPresentationsIn:inContext:
[ :d | each gtInspectorPresentationsIn: d inContext: self ] in [ :x | 
(GLMCompositePresentation new
	with:
		[ :d | each gtInspectorPresentationsIn: d inContext: self ])
	startOn: x ] in [ :a :each | 
a title: [ self printObjectAsAnItem: each ].
a
	dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
a titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
a dynamic
	display: [ :x | 
		(GLMCompositePresentation new
			with:
				[ :d | each gtInspectorPresentationsIn: d inContext: self ])
			startOn: x ] ] in [ :browser | 
browser fixedSizePanes: self class numberOfInspectorPanes.
browser
	show: [ :a :each | 
		a title: [ self printObjectAsAnItem: each ].
		a
			dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
		a
			titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
		a dynamic
			display: [ :x | 
				(GLMCompositePresentation new
					with:
						[ :d | each gtInspectorPresentationsIn: d inContext: self ])
					startOn: x ] ] ] in StudioInspector(GTInspector)>>compose in Block: [ :d | each gtInspectorPresentationsIn: d inContex...etc...
GLMCompositePresentation(GLMPresentation)>>with:
[ :x | 
(GLMCompositePresentation new
	with:
		[ :d | each gtInspectorPresentationsIn: d inContext: self ])
	startOn: x ] in [ :a :each | 
a title: [ self printObjectAsAnItem: each ].
a
	dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
a titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
a dynamic
	display: [ :x | 
		(GLMCompositePresentation new
			with:
				[ :d | each gtInspectorPresentationsIn: d inContext: self ])
			startOn: x ] ] in [ :browser | 
browser fixedSizePanes: self class numberOfInspectorPanes.
browser
	show: [ :a :each | 
		a title: [ self printObjectAsAnItem: each ].
		a
			dynamicActions: [ :aPresentation | each gtInspectorActions asOrderedCollection ].
		a
			titleAction: [ :aPresentation | self closeActionFor: aPresentation ].
		a dynamic
			display: [ :x | 
				(GLMCompositePresentation new
					with:
						[ :d | each gtInspectorPresentationsIn: d inContext: self ])
					startOn: x ] ] ] in StudioInspector(GTInspector)>>compose in Block: [ :x | ...
BlockClosure>>glamourValueWithArgs:
BlockClosure(ProtoObject)>>glamourValue:
GLMDynamicPresentation(GLMPresentation)>>displayValue

RaptorJIT load: follows symlinks recursively and loads same audit.log multiple times

In case of named Snabb programs their SHM directories contain a name symlink that leads to the same directory. When pointing RaptorJIT load: at such a SHM directory it will try to load the audit.log ten times instead of only once.

Possibly we should either not follow symlinks at all or somehow detect if we attempt to load the same audit.log and avoid that.

Nix-based installer

Create an installation process.

  • Create nix expression to install Studio.
  • Include packaging of dependencies not already in nixpkgs e.g. suitable Pharo image.

Studio version 2

I have started porting Studio onto the latest release of the GToolkit graphical inspector framework. See raptorjit/raptorjit#227. The new GToolkit is a much improved rewrite and it offers opportunities to do some things better.

The big one is to unify the user-interface, the manual, and the test suite into one living document (a collection of notebooks for individual topics and applications.) This should make Studio much easier to get started with, to master and to maintain. This will also make Studio more extensible because users can create their own notebooks and copy-paste useful snippets e.g. for downloading objects from their CI servers etc.

Screenshot preview:

screen shot 2019-01-28 at 10 17 04

There are a few changes that seem natural to make while adopting the new framework...

Using Smalltalk code snippets to drive the UI instead of Nix expressions. Nix will be driven by Smalltalk code, not directly by the user. This way we can take advantage of GToolkit's native support for editing Smalltalk snippets with error detection, syntax coloring, completion, etc. This also removes one indirection: the Smalltalk code will know in advance what objects the Nix code is building rather than having to infer that using the .studio/product-info.yaml metadata.

Rethinking the object model for the existing RaptorJIT inspection code. Have we chosen the right set of objects? Should we refactor into a more logical structure? There seem to be some aspects worth improving e.g. to make Profiles into first-class objects that can be sliced and diced. Have a uniform way to look at the profile of a whole process; one VMProfile dataset; one set of traces with a common root; one trace.

Rethinking individual views. Are we over-using "table-trees"? Is there a better way to present IR code in the new GToolkit? It has nice features such as text listings with inline expandable objects. It is also not backwards-compatible with the graphics framework that the existing visualizations are based on (Roassal2). So it seems at least worth rethinking any view that requires major porting effort to preserve.

I'll push a preview branch when I have a chance. Just now I don't have much integrated beyond what you can see in the screenshot above but a lot of existing functionality should be easy to port.

Create a Studio User Manual

Create a manual that explains how to get started as a Studio user.

Cover the UI that is inherited from the Glamorous Toolkit such as:

  • The Miller Columns left-to-right flow of the inspector.
  • How to pan back/forth between inspector panes (click or drag the little circles at the bottom.)
  • How to control the number of panes to display at once (drag edge near little circles at the bottom.)

Can't find licensing terms

Hello, this project looks really cool; I'm a heavy user of Nix, and a long time fan of Smalltalk (although not had reason to use it in anger yet!).

I'm a bit wary of downloading this to try it out though, since I can't seem to find any licensing terms for the code. Maybe they're just buried somewhere I didn't look? It's common to put terms into a file called COPYING or LICENSE at the top of the respository. Since you're using Nix, you could also use the metadata field in default.nix; that way, it will interact properly with Nix's allowUnfree option :)

Test in pristine environment

Studio should be tested in a pristine environment with no uncontrolled software available in $PATH. This could find undocumented dependencies.

Has been reported that xauth needs to be installed for Studio to work and that is a bug.

Show Nix build progress / manage user expectations

Studio often runs Nix builds. These builds should show progress to the user while they are running and ideally be executed asynchronously.

Studio can otherwise appear stuck if the user runs an expression that happens to take a long time. For example, the first time you enter a RaptorJIT expression Nix will need to download and build the RaptorJIT VM.

RaptorJIT: Add "Blacklist" tab

RaptorJIT inspector should show which source code has been "blacklisted" in a neat little summary.

This information can be gleaned from the Events list but that has a needle-in-the-haystack problem.

Create a short "walkthrough" demo video

Demo videos are an effective way to introduce Pharo-based applications. Create a brief step-by-step demo of Studio from installation to browsing RaptorJIT traces.

Create a Studio backend reference manual

Create a reference manual for the Nix API that is made available by with import <studio>. Users can call the API functions from their scripts to create objects to browse.

Show references from IR loop to head

The IR Tree view should show edges where loop instructions reference head instructions. Currently there are no edges between the loop and the head.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.